Authorization Code
Web Applications (Server) | Single Page Applications | Mobile Applications |
---|---|---|
Discouraged | Not Supported | Not Supported |
The Authorization Code Flow is the most common OAuth 2.0 flow. It can be used by web applications that run on a server and therefore can securely store their client secret. Neverthless, we recommend to use the Authorization Code Flow with PKCE flow instead. It is more secure and can be used by all types of applications. The next version of the OAuth 2.0 specification will deprecate the Authorization Code Flow. We only support it for backwards compatibility.
Migrating to Authorization Code with PKCE
If you are currently using the Authorization Code Flow, you should migrate to the Authorization Code Flow with PKCE flow. It is based on the Authorization Code Flow and therefore very similar. The flow is basically the same and just adds an additional security layer to prevent authorization code interception attacks. The flow is by now widely used and should be avaliable in all OAuth 2.0 libraries.
We will deprecate the Authorization Code Flow in the future and remove it at some point. Even though we will announce the deprecation in advance and will give you enough time to migrate, it's best to start with the more secure flow right away.
Overview
The Authorization Code flow consists of five major steps:
- The user clicks on your Tile in the Eduplaces platform, opening your Login URL in a new tab or the user clicks on a "Login with Eduplaces" button in your application.
- The user is redirected to our authorization server to authenticate and authorize your application.
- The user is redirected back to your application with an authorization code.
- Your application exchanges the authorization code for an ID and access token.
- Your application uses the ID token to identify the user and the access token to make API requests on behalf of the user.
The following diagram shows the flow in detail:
Step 1: Start an Authentication
Authentication is always started by an user interaction. This could be:
- The user clicking on your Tile in the Eduplaces platform, opening your Login URL in a new tab.
- The user clicking on a "Login with Eduplaces" button on your applications login page.
Step 2: Request User Authorization
Your application redirects the user to our authorization server to authenticate and authorize your application.
This is done by sending an authentication request to our authorization endpoint.
The GET
request can include the following query parameters:
Query Parameter | Value |
---|---|
response_type | required Always set to code to indicate the flow to be used. |
client_id | required The client ID of your application. |
redirect_uri | required The URL we will redirect the user back to after they authorized your application. This must exactly match one of your pre-registered allowed redirect URIs for your client. |
scope | required A space-separated list of scopes your application is requesting access to. You have to include openid to receive an ID token. |
state | strongly recommended A random string generated by your application. This will be included in the response from our authorization server and can be used to verify the response. We provide some tips below. |
nonce | strongly recommended A random string generated by your application. This will be included in the ID token and can be used to verify the token. |
login_hint | optional or required A string telling our authorization server to make sure a specific user is logged in. This is only required if the flow was started via your Login URL and we included a login_hint parameter. |
prompt | optional A space-separated list of strings that define whether the user should be prompted for reauthentication and consent. Values are none , login , consent . See prompt Parameter for more information. |
id_token_hint | optional A previously issued ID token. If the user identified by the ID Token is logged in or is logged in by the request, then the Authorization Server returns a positive response; otherwise, it returns an error. This could be used in combination with prompt=none to check if the user is still logged in. |
max_age | optional Maximum Authentication Age. Specifies the allowable elapsed time in seconds since the last time the End-User was actively authenticated by Eduplaces. If the elapsed time is greater than this value, we will reauthenticate the user. Usage is discouraged! |
HTTP/1.1 302 Found
Location: https://auth.eduplaces.io/oauth2/auth
?response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=https://your.awesome-education.app/sso/callback
&scope=openid school profile
&state=YOUR_STATE
&nonce=YOUR_NONCE
The user will be redirected to our authorization server where they can log in and authorize your application. If the user is already logged in, they will be asked to authorize your application right away. We remember the user's decision and will not ask them again for the same application.
Step 3: Redirect back to your Application
After the user authorized your application, they will be redirected back to your application with an authorization code. The authorization code is a short-lived, one-time code that can be exchanged for an ID and access token.
To which URI we redirect the user depends on the redirect_uri
parameter you included in the authentication request.
Just keep in mind that the redirect URI must exactly match one of your pre-registered allowed redirect URIs for your client.
We will also redirect the user to the redirect_uri
if they denied your application access to their data or if they canceled the authentication process.
If the user authorized your application, we will redirect them back to your application with an authorization code and the state you included in the authentication request.
The GET
request will include the following query parameters:
Query Parameter | Value |
---|---|
code | The authorization code your application can use to obtain an ID and access token. |
state | The state you included in the authentication request. |
GET https://your.awesome-education.app/sso/callback
?code=ory_ac_MLN1fCSPt1v85onDiZM5FbBhXq2SVFPBQITrGYk4dr8.766I7lY1jKYKadkBikQjcugyt5ki8lDT3u8-JVei-Sc
&state=YOUR_STATE
Error Response
If the user denied your application access to their data or if they canceled the authentication process, we will redirect them back to your application with an error.
The GET
request will include the following query parameters:
Query Parameter | Value |
---|---|
error | The error code. |
error_description | A human-readable text providing additional information. |
state | The state you included in the authentication request. |
GET https://your.awesome-education.app/sso/callback
?error=access_denied
&error_description=The+resource+owner+or+authorization+server+denied+the+request.
&state=YOUR_STATE
Refer to the OpenID Connect specification for a list of error codes.
The error_description
is optional and might not be included in the response.
We will try to include it if possible, but you should not rely on its presence.
state
parameter is only included in the response if you included it in the authentication request.
You should always verify that the state
parameter in the response matches the state
parameter you included in the authentication request.Step 4: Exchange Authorization Code for Tokens
The user is now back on your application and you can exchange the authorization code for an ID and access token.
To do so, you have to send a POST
request to our token endpoint.
As this flow is only available for confidential clients, you have to authenticate yourself by including your client ID and secret in the Authorization
header.
To exchange the authorization code for an ID and access token, you have to make a POST
request to our token endpoint.
The POST
request must include the following parameters in the body:
Request Body Parameter | Value |
---|---|
grant_type | required Always set to authorization_code to indicate you are exchanging an authorization code for an ID and access token. |
redirect_uri | required The Redirect URI used while requesting the authorization code. |
In addition to the request body parameters, you have to set the following headers:
Header | Value |
---|---|
Content-Type | required Set to application/x-www-form-urlencoded . This will most likely be set automatically by your HTTP client. |
Authorization | required Set to Basic <base64(client_id:client_secret)> . Never include the client secret in a request from a public client like a single page application or a mobile application. |
POST /oauth2/token HTTP/1.1
Host: auth.eduplaces.io
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=ory_ac_MLN1fCSPt1v85onDiZM5FbBhXq2SVFPBQITrGYk4dr8.766I7lY1jKYKadkBikQjcugyt5ki8lDT3u8-JVei-Sc
&redirect_uri=https://your.awesome-education.app/sso/callback
If the request was successful, we will respond with a 200 OK
status code and a JSON body containing the following parameters:
Key | Value |
---|---|
access_token | The access token your application can use to make API requests on behalf of the user. |
token_type | The type of the access token. Always set to bearer . Note: It should be Bearer but unfortunately, our OAuth 2.0 server returns it in lowercase. Make sure to be able to handle both as this might change. |
expires_in | The remaining lifetime of the access token in seconds. |
scope | The scopes the user authorized your application to access. |
id_token | The ID token your application can use to identify the user. Requires the openid scope. |
refresh_token | The refresh token your application can use to obtain a new access token when the current one expired and the user is not present to re-authorize your application. Requires the offline_access scope. Learn more about Refresh Tokens. |
HTTP/1.1 200
Content-Type: application/json
{
"access_token": "ory_at_FYfL9jJTZO15HI6EQCO-0uZg8W_KMTJHunpmXTLp8lg.uGGOCQEGOlunY9mdsWrZA3uGT03JYWdTTj8iar5MIvs",
"token_type": "bearer"
"expires_in": 3599,
"scope": "openid offline_access",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg4MzIwZjlmLTBhZjQtNDFjMC1iMzAwLTczMGFmZmRjYjVhMCIsInR5cCI6IkpXVCJ9.eyJhdF9oYXNoIjoiSXdDQmFTc0tEZTI3R1JQQS12NG1JUSIsImF1ZCI6WyJkYzYxZjk5ZC1hZGZlLTQ1OGEtODZiZi0zYTMxNmYyYTc4OWMiXSwiYXV0aF90aW1lIjoxNjkzMzAyNzAwLCJleHAiOjE2OTMzMDYzMTQsImlhdCI6MTY5MzMwMjcxNCwiaXNzIjoiaHR0cHM6Ly9zaWxseS1lbGlvbi13ZWN4dHhtY2c1LnByb2plY3RzLm9yeWFwaXMuY29tIiwianRpIjoiMWMyZDUzMmQtMWUzNi00ZmFiLTkwMjgtMjc1MDcwM2FiMTczIiwicmF0IjoxNjkzMzAyNjkzLCJzaWQiOiIzM2RiOWU3Ny1iNGRiLTQ2M2YtOTc4My1kZmY3NmU5NDQxNDciLCJzdWIiOiI3NGQ3YjYyNS01YzA4LTRjYmItOWQwZC1lZWQxZTgzNjQ2YzMifQ.EPWFwVioQZYxmaZVy_3drs2-3jr2DIszkrI9TZpz6dJluDPQ6F6M2Kq7q-zKthnHM7rWvb-bfBJh6Olo1UF6TG0F93WXQIdI7HgIhtQH5a9Cfwbv-h8GQieVc2cQmxzqyiqIxa4e0Z3VoLvsqCE76JVfdo0tmI1SfnauYx3BSxlu6LeVzYWWclQU9fJg1pfurvw6hzVdtJTjdyUvh45bNMAb_QWFDMhkF36yMX7CqzVd8eHX5jnMuk2e1WDLKS6qZxJ3oGux_VDqKg9Qu0x8rb1e4WPAJJ35n2AcqmsO0ex14yxUfhCZDRM31MMC11MfIH1wiTrZKTF9EqZ0yys_vZoQ8DBoHvnDA7cjYZ-0FXO1cirDflzo0jMxihwFaES-_E1pAr4vkiInIigSc4YmTMfOyTttlT-U31zlOh5tiaLhzLO9ImmyLenj9CGCi_GYPqoLf0JTbeSKA9J7DkrO-ed_xMYn-fHt1oqukJmEVg7KJz3Ey5G4h_mL8wMR2Vj-wopFC01RIYpo3a-KjEPdFUktyNB678-iY-n0JuEdDLJ743RfWsR4zQOKpfy3XMK3jIfcE_sAg5Yz3rgUWtVdZ_NSy1rvOCzbJ3-PoxzGNS1qbp6Ma0aK-FU_ZHyUnLRoRa5O6q1vwLe-DX5nfsfIX9S2FapS6nTC_hPITyq9YRI",
"refresh_token": "ory_rt_XfPjrVDSXtVXK-WA9rbjAp5g7ZkAG-hXR76nN38VIAM.disRRBbHn71r2JfpLKuiq3F5EyJPKg7dmWQZdsFm-rw",
}
Error Response
If the request was not successful, we will respond with an error.
The authorization server will respond with a 400 Bad Request
status code and a JSON body containing the following parameters:
Key | Value |
---|---|
error | The error code. |
error_description | A human-readable text providing additional information. |
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_request",
"error_description": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
}
Refer to the OAuth 2.0 specification for a list of error codes.
The error_description
is optional and might not be included in the response. We will try to include it if possible, but you should not rely on its presence.
Step 5: Use the ID Token to Identify the User
To Authenticate the user, you have to verify the ID token. The ID token is a JSON Web Token (JWT) that contains information about the user and is signed by Eduplaces. Part of the information is the user's unique ID, which you can use to identify the user in your application. The ID token can also contain information about the user's school and role. Head over to our Scopes section for more information on the available additional claims.
Validating the ID token is a two-step process:
- Verify the signature of the ID token to ensure it was signed by Eduplaces.
- Verify the claims in the ID token to ensure the token is valid.
How to verify the signature is out of scope for this documentation. We recommend using one of the many open source libraries available that can help you with the ID token validation. In our Authenticate Users Guide, we provide a full example you can use as a reference.
On our Endpoints page, you can find the URLs containing the public keys you can use to verify the signature of the ID token. Common libraries will be able to automatically fetch the public keys automatically by using the OpenID Connect Discovery endpoint we provide.
The ID token contains a JSON object with at least the following claims:
Claim | Description |
---|---|
iss | The issuer identifier for the issuer of the response. Always set to https://auth.eduplaces.io . |
aud | Array containing the client ID of your application. |
sub | The unique identifier for the user. |
nonce | The nonce you included in the authentication request. |
jti | A unique identifier for the token. |
sid | The Eduplaces session ID. |
at_hash | The access token hash. |
auth_time | The time the user authenticated. |
rat | The time the ID token was requested. |
iat | The time the ID token was issued. |
exp | The expiration time of the ID token. |
If you requested additional scopes, the ID token can contain additional claims. Head over to our Scopes section for more information on the available additional claims.
{
"iss": "https://auth.eduplaces.io",
"aud": [
"YOUR_CLIENT_ID"
],
"sub": "f80763f1-96da-4071-b29d-1f15d83ca8b6",
"nonce": "YOUR_NONCE",
"jti": "30e58376-ed53-4c5b-91c1-9fd5517e7f55",
"sid": "7ddc71e6-e932-43e5-9d86-2ada68a490af",
"at_hash": "cw8qL0ENYRYrslktjHXEtw",
"auth_time": 1692706900,
"rat": 1692706896,
"iat": 1692706914,
"exp": 1692710514
}
The most important claim when authenticating a user is the sub
claim.
It contains the unique identifier for the user.
You can use this identifier to identify the user in your application and log them in automatically.
Just like you would with a username and password.
If you receive an ID token with a sub
claim you don't recognize, you should create a new user account on-the-fly in your database and associate it with the user's Eduplaces ID.
The next time the user logs in to your application with Eduplaces, you can use the ID token to identify the user and log them in automatically.
Additional Information
state
Parameter
The state
parameter is a random string generated by your application.
It is included in the response from our authorization server and can be used to verify the response.
You should always verify that the state
parameter in the response matches the state
parameter you included in the authentication request.
It is strongly recommended to include the state
parameter in the authentication request as it can prevent CSRF attacks.
Some documentation you might find on the internet recommends to use the state
parameter to store the user's session.
This is not recommended as it can lead to session fixation attacks.
Instead, you should use a session cookie to store the user's session and store the state
parameter in the session.
This is how we recommend to use the state
parameter:
- Create a random string when the user starts the authentication flow.
- Store the random string in a protected cookie (
secure
andhttpOnly
) for server-side web applications, in Local Storage for single page applications, or in a protected key-value store for mobile applications. - Include the random string as
state
in the authentication request. - Verify that the
state
parameter in the response matches the random string you stored in the cookie, Local Storage, or key-value store. - Delete the random string from the cookie, Local Storage, or key-value store.
As the state is stored in a cookie, Local Storage, or key-value store on the user's device, it is not possible to resume a flow in another browser or device by knowing the state. This is a good thing as it prevents session fixation attacks.
prompt
Parameter
The prompt
parameter is a space-separated list of strings that define whether the user should be prompted for reauthentication and consent.
There is no need to include the prompt
parameter if you only want to authenticate the user.
Only include it if you have a specific use case for it.
The following values are supported:
none
: The user should not be prompted for reauthentication or consent. If the user is not logged in or if they are logged in but haven't authorized your application yet, we will respond with an error.login
: The user should be prompted for reauthentication even if they are currently logged in.consent
: The user should be prompted for consent.
The prompt
parameter is useful in combination with the id_token_hint
parameter if you want to make sure the user is still logged in on Eduplaces.
This could be the case if the user is logged in to your application but hasn't used it for a while.
In this case, you could include the prompt=none
parameter in the authentication request and the id_token_hint
parameter with the ID token you received the last time the user logged in even if it is expired.
This concept is also known as Silent Authentication as the user is not prompted for reauthentication or consent.