Code Flow - the raw way
If you don't use (or don't want to use a library that supports OAuth/OpenID Connect), you totally can! The protocol is actually quite simple from the app's point of view. (the spec is hundreds pages for provider though ...)
This section will explain how to implement the Code Flow
in your back-end along with some info to watch out for.
To implement the Code Flow
please make sure you have:
- read through the Introduction to have a rough idea on what is the
Code Flow
and - followed the App to have the SimpleLogin AppId and AppSecret.
As recommended in the The Twelve Factors, let's export these values into env variables:
export CLIENT_ID={your_app_id}
export CLIENT_SECRET={your_app_secret}
The way to read these env variables in the code differs from language to language, a quick google read env var {your language}
should return some results.
To implement the Code Flow
, you would need 2 endpoints:
- Login endpoint: that redirects user to SimpleLogin authorization page
- Callback endpoint: user is redirected back to this page along with a
code
that allows you to exchange for anaccess token
which in turn can be used to obtainuser info
.
Let's jump into each endpoint.
Login endpoint
This endpoint handles user clicking on Sign in with SimpleLogin button (e.g. <a href="https://your-app/login">Sign in with SimpleLogin</a>
) and redirects user to a formatted SimpleLogin url. This url has the following format. Line breaks are added for visibility, please remove them in your code.
https://app.simplelogin.io/oauth2/authorize
?response_type=code
&client_id=CLIENT_ID
&redirect_uri=REDIRECT_URI
&scope=profile
&state=STATE
Let's split this long url down to components:
response_type=code
: indicates the flow. Its value iscode
forcode flow
andtoken
forimplicit flow
. In our case, it's alwayscode
.client_id=CLIENT_ID
:CLIENT_ID
is your SimpleLogin AppID. In OAuth terminology,client
is actually your app.redirect_uri=REDIRECT_URI
: upon user approval, user will be redirected to this url. This should be the url of your callback endpoint that we are going to create in the next step. If your app is https://my-app.com on production and http://localhost:8000 locally, this url would probably be https://my-app.com/callback when you deploy your app on production. Please make sure to add this redirect url on your SimpleLogin Developer page. (see App)scope=profile
: the user information you want. SimpleLogin supports onlyprofile
scope which contains user email, name and avatar.state=STATE
: thisSTATE
value should be generated randomly to avoid CSRF attack. This value will be checked in the callback endpoint and one standard way is to save this value into the cookie that you can retrieve later in the callback endpoint.
Callback endpoint
Upon user approval, they will be redirected to this below url. Line breaks are also added here for visibility only, please remove them in your code.
REDIRECT_URI
?code=CODE
&state=STATE
Let's break the components down:
REDIRECT_URI
the sameREDIRECT_URI
in the login endpointSTATE
: the state generated in the login endpoint. It's your app's responsibility to compare thisSTATE
to the one generated in previous step, typically by retrieving it from the cookie.CODE
: used to exchange for theaccess token
in a POST request to SimpleLogin:
curl -X POST https://app.simplelogin.io/oauth2/token \
-F 'grant_type=authorization_code' \
-F 'code=CODE' \
-F 'redirect_uri=REDIRECT_URI' \
-F 'client_id=CLIENT_ID' \
-F 'client_secret=CLIENT_SECRET'
REDIRECT_URI
is sent once again. The CLIENT_ID
and CLIENT_SECRET
are retrieved from env variable.
SimpleLogin will return this response if everything is correct:
{
"access_token": "LONG_STRING",
"expires_in": 3600,
"scope": "profile",
"token_type": "Bearer",
"user": {
"avatar_url": "https://avatar.png",
"client": "YOUR_APP_NAME",
"email": "EMAIL@simplelogin.co",
"email_verified": true,
"id": 36,
"name": "FIRST LAST",
"sub": "36"
}
}
With this user info, you should now either be logged in or have access to some reserved information.
Congratulations, you just implemented a OAuth client!