Implement login using the Authorization Code flow¶
See the instructions given below to implement login with OpenID Connect in your application by using the authorization code flow. This method is suitable for confidential clients such as traditional web applications.
The following diagram explains how this flow works with WSO2 Identity Server:
As shown above, you need to configure your application to get the authorization code from WSO2 Identity Server, and then exchange it for the required tokens.
Prerequisites¶
To get started, you need to have an application registered in WSO2 Identity Server. If you don't already have one, register a web app with OIDC.
Note
Note that only users can log in to business applications. Therefore, to test login on your application, you need a user account.
Get the authorization code¶
First, your app must initiate a login request to the authorization endpoint of WSO2 Identity Server. After redirecting to WSO2 Identity Server, the user should be prompted with a login page if the user is not authenticated.
Authorization endpoint
https://localhost:9443/oauth2/authorize
Request format
https://localhost:9443/oauth2/authorize?scope={scope}&response_type=code&redirect_uri={redirect_uri}&client_id={client_id}&login_hint={email-address-passed-as-a-hint}
Request sample
https://localhost:9443/oauth2/authorize?response_type=code&client_id=z8RB6ysdDZhe4QO0zJAQzKbi6P4a&scope=openid&redirect_uri=http://localhost:3000&login_hint=[email protected]
Request Parameter | Description |
---|---|
response_type |
Required grant type. Use code to represent the authorization code grant type. |
redirect_uri |
This is where the response is redirected to at the end of the process. This needs to be the same as one of the URLs given in the registered apps. |
client_id |
The client ID obtained when registering the application in WSO2 Identity Server. |
scope |
For OpenId Connect login, use openid as one of the scopes. There can be additional scopes as well. Scopes should be space separated. Example: openid email profile |
login_hint |
The email address of the user can be passed as a query parameter. This will trigger a prompt for the user to input their password directly, streamlining the authentication process. Note that the functionality of this query parameter is only valid if the basic authenticator is used as the first step in the sign-in flow. |
Once the user is successfully authenticated, WSO2 Identity Server redirects the user to the redirect_uri
with the authorization code.
Sample response
https://localhost:3000/?code=97c85a59-a758-3a56-95cd-e71a505b493d&session_state=a0c3bc89849ba0f236791f7fe76a837b7b4422fdc9aca16db394d19a28724a29.wQc7eSHSRrGNfECJRMhSAw
Get tokens¶
After receiving the authorization code, the application has to exchange it to get the tokens given below:
access_token
id_token
refresh_token
(only if therefresh_token
grant type is enabled for the application registered in WSO2 Identity Server)
Token endpoint
https://localhost:9443/oauth2/token
Token request
When your application is a confidential client, it needs to identify itself to the token endpoint by submitting its credentials. There are several ways to implement client authentication at the token endpoint:
Note
See the list of client authentication methods in the OIDC specification.
-
Use client_secret_post: The
client_id
andclient_secret
are both sent as body parameters in the POST message. See the example given below.curl --location --request POST 'https://localhost:9443/oauth2/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'code={authorization_code}' \ --data-urlencode 'grant_type=authorization_code' \ --data-urlencode 'client_id={client_id}' \ --data-urlencode 'client_secret={client_secret}' \ --data-urlencode 'redirect_uri={redirect_uri}'
var settings = { "url": "https://localhost:9443/oauth2/token", "method": "POST", "timeout": 0, "headers": { "Content-Type": "application/x-www-form-urlencoded" }, "data": { "code": "{authorization_code}", "grant_type": "authorization_code", "client_id": "{client_id}", "client_secret": "{client_secret}", "redirect_uri": "{redirect_uri}" } }; $.ajax(settings).done(function (response) { console.log(response); });
var axios = require('axios'); var qs = require('qs'); var data = qs.stringify({ 'code': '{authorization_code}', 'grant_type': 'authorization_code', 'client_id': '{client_id}', 'client_secret': '{client_secret}', 'redirect_uri': '{redirect_uri}' }); var config = { method: 'post', url: 'https://localhost:9443/oauth2/token', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, data : data }; axios(config) .then(function (response) { console.log(JSON.stringify(response.data)); }) .catch(function (error) { console.log(error); });
-
Use client_secret_basic: The client secret is sent as an authorization header in the request (
Authorization: Basic BASE46_ENCODING<client_id:client_secret>
). See the example given below.curl --location --request POST 'https://localhost:9443/oauth2/token' \ --header 'Authorization: Basic ejhSQjZ5c2REWmhlNFFPMHpKQVF6S2JpNlA0YTp6MEM3OXpsb3B4OGk3QnlPdzhLMTVBOWRwbFlh' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'code=97c85a59-a758-3a56-95cd-e71a505b493d' \ --data-urlencode 'grant_type=authorization_code' \ --data-urlencode 'redirect_uri=https://myfirstwebapp.io/login'
-
Use a private key JWT: A secured JWT assertion with the data required for client authentication is sent in the token request. See the example given below.
Note
Learn more about private key JWT client authentication in WSO2 Identity Server.
--header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'code={authorization_code}' \ --data-urlencode 'grant_type=authorization_code' \ --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer'\ --data-urlencode 'client_assertion={jwt_assertion}' \ --data-urlencode 'redirect_uri={redirect_uri}'
The token request has the following parameters in addition to the credentials for authentication:
Request Parameter | Description |
---|---|
code |
The authorization code received from the authorization request. |
grant_type |
The grant type. Here we are using the authorization_code grant. |
redirect_uri |
This is where the response is redirected to at the end of the process. |
client_assertion_type |
This parameter is only used for client authentication using a private JWT key. |
Sample response will be as follows:
{
"access_token": "54bd024f-5080-3db5-9422-785f5d610605",
"scope": "openid",
"id_token": "eyJ4NXQiOiJZemM1T1Rnd1pURTNNV1F6TVdFek5ERm1OelZoTTJOaU9UQmxOamN3TlRJNU9HTTBNbVExWWprd1lqZzJNVEl3WldNd056TTRNemcxWkdJeVpEZzNaQSIsImtpZCI6Ill6YzVPVGd3WlRFM01XUXpNV0V6TkRGbU56VmhNMk5pT1RCbE5qY3dOVEk1T0dNME1tUTFZamt3WWpnMk1USXdaV013TnpNNE16ZzFaR0l5WkRnM1pBX1JTMjU2IiwiYWxnIjoiUlMyNTYifQ.eyJpc2siOiI4ZTQyYjgzOTQzYWViYTkwMGU3MjJkMWI5NzU3Nzc3OTAyOGRhM2NiZWJmZjhhZTQxMDVhZTA5OTRiZjU5ZDYxIiwiYXRfaGFzaCI6IlZETXZUaWFsbjRRWEk4VUlJUjVlbnciLCJhdWQiOiJ6OFJCNnlzZERaaGU0UU8wekpBUXpLYmk2UDRhIiwiY19oYXNoIjoiOXRMaHJvQnV6Z0I4aDlIWWV6cTBpZyIsInN1YiI6InVzZXIxQGJpZnJvc3QuY29tIiwibmJmIjoxNjIwNzAzODA5LCJhenAiOiJ6OFJCNnlzZERaaGU0UU8wekpBUXpLYmk2UDRhIiwiYW1yIjpbIkJhc2ljQXV0aGVudGljYXRvciJdLCJpc3MiOiJodHRwczpcL1wvYWNjb3VudHMuYXNnYXJkZW8uaW9cL3RcL2JpZnJvc3RcL29hdXRoMlwvdG9rZW4iLCJleHAiOjE2MjA3MDc0MDksImlhdCI6MTYyMDcwMzgwOSwic2lkIjoiYWQ3M2NlZGMtMzM3Ny00NDU3LWExYjUtNTZjODgyMTg1MzZmIn0.RSSL3InOFlvt_xQWFDKZY4FjKFFxh8rqGAlm1vKxleP6dKVlDAT4E0sudCJV5paJ-HdxVMd8MveWwpxrIL5NJw9XCa_sCEfso2fsMgRzQyEn1gjKLmr6Fj8Up3BoPnzPzn1cqVd-pKeXomzciM_ZDwsLr8qAEgVp663D4fg_F6pjVdDr17JRCUgO96yyjHRC5Eiqd7MP20Xhb-ZCMe0OhAlJlCmXB0FZV3nOTbza-jGvG8e_k80g3KVPFO7USek2Px3dCYfcbcA3k3cVzbTN8r8PIY3CEIIHtu5RyO_m1v3A0fjKvSaatfN0K2sndnlRpXFtOosIKQDYsy94wGnWkQ",
"token_type": "Bearer",
"expires_in": 3600
}
To get a refresh token, you need to enable the Refresh Token grant type for the application. By default, it is enabled for traditional web application templates.