OAUTH2 Authorization Code grant with PKCE
To secure JavaScript single page browser applications with refresh token functionality, use OAUTH2 Authorization Code grant with PKCE (Proof Key for Code Exchange).
Prerequisites#
- Platform Application: The platform application acts as an OAUTH2 client. Register the redirect URI when you create your app. In the authentication process, specify the registered redirect URI, appId, code challenge, and code challenge method. Follow the tutorial to create your app on the platform.
- An understanding of the following concepts:
- Oauth2 Authorization Code
- PKCE
Authorization and authentication workflow#
For an overview of the OAUTH2 Authorization Code grant with PKCE process for a user, application, and the passport service, see the following workflow diagram:
Figure: Auth flow diagram

Setting up the authentication process#
To direct the user to the authorization web flow, make a HTTP authorize request from a browser application with the following mandatory path and parameters:
- Endpoint:
- Parameters:
response_type: Tells the OAuth server to use the authorization_code grant type, for examplecode.redirect_uri: The URL you want to redirect the user to after a successful login, such as . Replace the value here with the appropriate URL for your web app. The URL must be one of the values you specified for the _redirectUris parameter in your registered platform application.client_id: Enter your app’s ID, for example548a0869-0d46-4dd2-afbb-7ba83a000162.code_challenge: The encrypted value (sha-256 and Base 64) for a random string of 16 to 64 characters to verify the token API request, for exampleYTU2YjIzOTYzMzcxMWIxZjg1ODUwM2E0Y2JkODJiMjBiYTc5ODc0ZjkzMWQwMjFlY2U5OGQxMjEzYzc2MDY3Zg.code_challenge_method: Declares the encryption algorithm that generates the code challenge. Always use the values256.scope: Use read and write as the scope for exampleread write.
This is the complete example request:
`https://general-dev.company.com/passportsvc/api/v1/oauth/authorize?client_id=548a0869-0d46-4dd2-afbb-7ba83a000162&scope=read write&response_type=code&redirect_uri=https://general-dev.company.com/ipa-dev&code_challenge=YTU2YjIzOTYzMzcxMWIxZjg1ODUwM2E0Y2JkODJiMjBiYTc5ODc0ZjkzMWQwMjFlY2U5OGQxMjEzYzc2MDY3Zg&code_challenge_method=S256`Step result: The request takes the user to the Sign In page. When the user enters their credentials successfully, the user is redirected to the callback URL you pass as the
redirect_uriparameter. The authorization code is included as a fragment of the URL.
Extract the authorization code from the URL. For more information, see the
codeparameter in the following example endpoint URL:To exchange the authorization code for an access token, use the following POST request endpoint and parameters:
- Request: POST
- Endpoint:
- Parameters:
client_id: 548a0869-0d46-4dd2-afbb-7ba83a000162redirect_uri:grant_type: authorization_codecode: CIJ6Vicode_verifier: 14b96d8037dde437c9ab53c7eee399aff52eaff9b872afa7eb86116d7dab5602030671c943d578699f0fd33e1e0eeee06fe9f7cde6a5482157adabeccc267ea1
- Response codes:
200: Success403: Forbidden
For more information, see the following request example:
curl -v 'https://api.company.com/passportsvc/api/v1/oauth/token' \ -X 'POST' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=authorization_code' \ -d 'code=IuUW1b' \ -d 'redirect_uri=https://apps.company.com/digitaltwin' \ -d 'client_id=6f42efd3-0d2e-45c2-b829-7614dd8343c4' \ -d 'code_verifier=4cc9b165-1230-4607-873b-3a78afcf60c5'Step result: The POST request returns the following response:
{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJlM2M3YTlmNy0zY2M3LTRiMjUtOTYxNy05ODg1OTRjMzNmNjAiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiZXhwIjoxNjY3NjAwMTM1LCJhcHBfaWQiOiI1NDhhMDg2OS0wZDQ2LTRkZDItYWZiYi03YmE4M2EwMDAxNjIiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiNmYzYWZjYTQtYmI1Ni00OGQ5LWEwY2EtNmYzMTliMmY3ZDFkIiwiY2xpZW50X2lkIjoiNTQ4YTA4NjktMGQ0Ni00ZGQyLWFmYmItN2JhODNhMDAwMTYyIn0.YbpNiswURRteTNCYe7cLcYDuoAl91BOb-GmhTH7VGyFz2RJtrSQEhs5AHnFg5l0KlYltB1mOU_pKgDev02YX8KLh6vDwK-MCfPcDfwKSpdaxhEM5C7DoorJCzMZWwy2tOSfJCMfZJchhY3KfvgZ_H1WmdUyIh3qXVU04X5hYe06yBvPVR50MByWrp_yM66kCO_GCsHpQ6y5FlVzwwDszIps1affX0Vclz4qjY3zZP1gtpb5n98WmRWJFSj6sI_FSM_jbzGa0YefZNE_G-wGi0Yq6deOOyMHAQHxRfWTznykOTEN7DOq5Jof8sZPtL0cjVPJP28PbnaL9nt7PFFaiKg", "token_type": "bearer", "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJlM2M3YTlmNy0zY2M3LTRiMjUtOTYxNy05ODg1OTRjMzNmNjAiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiYXRpIjoiNmYzYWZjYTQtYmI1Ni00OGQ5LWEwY2EtNmYzMTliMmY3ZDFkIiwiZXhwIjoxNjcwMTQ4OTM1LCJhcHBfaWQiOiI1NDhhMDg2OS0wZDQ2LTRkZDItYWZiYi03YmE4M2EwMDAxNjIiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMzFkYmU2MmYtYjMwMC00ODY4LWE3ZDctYThhNDZkMWVlYmQ2IiwiY2xpZW50X2lkIjoiNTQ4YTA4NjktMGQ0Ni00ZGQyLWFmYmItN2JhODNhMDAwMTYyIn0.bQUz9tjdz4Pf45Btii06ZqJiG636XlmTfnbdfDNqBB_Ud9KO3Vx9ISDlRij3RMkz15g1CNK4WmTFfEIByR4nLjzgcAqhLPMNsdcVkJTTnun8CZpm1xAKFFDT5ztcEilUhUXELz1OhB13nfIzPf3BH28q5jJms9CDtLFuVNiu8rfNkaQyijA1QLZmVc-_Q7XMo2O2Z2VnBZpK1QFhBixwMsLvlv9yFvyAWVl8vU6WESC_oyR3xKFtoK5VT6-kA0nEL6G_I0bpCBKZ5DA4D85CfBl94sUnSsGv7VDoFoIEie1u5cbi6JzJY0EgzfGYsya26viaKI28KL_CTn4hJY-oCw", "expires_in": 43199, "scope": "read write", "user_name": "e3c7a9f7-3cc7-4b25-9617-988594c33f60", "app_id": "548a0869-0d46-4dd2-afbb-7ba83a000162", "jti": "6f3afca4-bb56-48d9-a0ca-6f319b2f7d1d"}To get a new set of access tokens from a refresh token after the current access token expires, make a GET request with the following endpoint and parameters:
- Request: GET
- Endpoint:
- Parameters:
client_id: 548a0869-0d46-4dd2-afbb-7ba83a000162redirect_uri:grant_type: refresh_code
- Response codes:
200: Success403: Forbidden
For more information, see the following request example:
curl --location --request POST 'https://api.company.com/passportsvc/api/v1/oauth/token?grant_type=refresh_token&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJmZGJjOGQ3MC0wMTllLTRjYmQtYWQ2Mi02MGE3YTY2ODMwOTciLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiYXRpIjoiZmIyZDljYmUtYTBiMi00ZDkyLWFiMTktYzY2N2UwNzQxZGMzIiwiZXhwIjoxNjQwMjUyMTQ1LCJhcHBfaWQiOiI2ZjQyZWZkMy0wZDJlLTQ1YzItYjgyOS03NjE0ZGQ4MzQzYzQiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiYmRjZDI4YjktNzdhNy00OWFlLWE5OGQtMzljMmQwYjdjY2RjIiwiY2xpZW50X2lkIjoiNmY0MmVmZDMtMGQyZS00NWMyLWI4MjktNzYxNGRkODM0M2M0In0.Dk6rWz9GH6qql9lREAWpavZlUOz9XjLeGeAxAyjuQF3-zjtqofih8gWhVrMAMIzN5yIV29HXQl5mMCpEhjptJ04iZuz7ZeP8XzzLzpDzxuKWuPb0ajLpfh4xErEaWzlhh4XvN_siZwJ7hbefD-BpzEOjdBqfyWWWsQfjr9xi7KBqoXHn9NKy79eZzMhybahbtgVxSYTZSnhDP0jc04Z0GAOJKpxxQM-YanW2Se3R4fxvWpnCeZ5KbN2Ur0W-m-b3rf6QtDKlPtxW8VP9-sPVMBUZEiIaHSI7DEffr_4OxrL5B-2wKzuhYoqCrEoLsRcw3lkCJcgrR6Z7Tsct9Me-Bw&client_id=6f42efd3-0d2e-45c2-b829-7614dd8343c4' \Step result: The GET request returns the following response:
{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJlM2M3YTlmNy0zY2M3LTRiMjUtOTYxNy05ODg1OTRjMzNmNjAiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiZXhwIjoxNjY3NjAwMTM1LCJhcHBfaWQiOiI1NDhhMDg2OS0wZDQ2LTRkZDItYWZiYi03YmE4M2EwMDAxNjIiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiNmYzYWZjYTQtYmI1Ni00OGQ5LWEwY2EtNmYzMTliMmY3ZDFkIiwiY2xpZW50X2lkIjoiNTQ4YTA4NjktMGQ0Ni00ZGQyLWFmYmItN2JhODNhMDAwMTYyIn0.YbpNiswURRteTNCYe7cLcYDuoAl91BOb-GmhTH7VGyFz2RJtrSQEhs5AHnFg5l0KlYltB1mOU_pKgDev02YX8KLh6vDwK-MCfPcDfwKSpdaxhEM5C7DoorJCzMZWwy2tOSfJCMfZJchhY3KfvgZ_H1WmdUyIh3qXVU04X5hYe06yBvPVR50MByWrp_yM66kCO_GCsHpQ6y5FlVzwwDszIps1affX0Vclz4qjY3zZP1gtpb5n98WmRWJFSj6sI_FSM_jbzGa0YefZNE_G-wGi0Yq6deOOyMHAQHxRfWTznykOTEN7DOq5Jof8sZPtL0cjVPJP28PbnaL9nt7PFFaiKg", "token_type": "bearer", "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJlM2M3YTlmNy0zY2M3LTRiMjUtOTYxNy05ODg1OTRjMzNmNjAiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiYXRpIjoiNmYzYWZjYTQtYmI1Ni00OGQ5LWEwY2EtNmYzMTliMmY3ZDFkIiwiZXhwIjoxNjcwMTQ4OTM1LCJhcHBfaWQiOiI1NDhhMDg2OS0wZDQ2LTRkZDItYWZiYi03YmE4M2EwMDAxNjIiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMzFkYmU2MmYtYjMwMC00ODY4LWE3ZDctYThhNDZkMWVlYmQ2IiwiY2xpZW50X2lkIjoiNTQ4YTA4NjktMGQ0Ni00ZGQyLWFmYmItN2JhODNhMDAwMTYyIn0.bQUz9tjdz4Pf45Btii06ZqJiG636XlmTfnbdfDNqBB_Ud9KO3Vx9ISDlRij3RMkz15g1CNK4WmTFfEIByR4nLjzgcAqhLPMNsdcVkJTTnun8CZpm1xAKFFDT5ztcEilUhUXELz1OhB13nfIzPf3BH28q5jJms9CDtLFuVNiu8rfNkaQyijA1QLZmVc-_Q7XMo2O2Z2VnBZpK1QFhBixwMsLvlv9yFvyAWVl8vU6WESC_oyR3xKFtoK5VT6-kA0nEL6G_I0bpCBKZ5DA4D85CfBl94sUnSsGv7VDoFoIEie1u5cbi6JzJY0EgzfGYsya26viaKI28KL_CTn4hJY-oCw", "expires_in": 43199, "scope": "read write", "user_name": "e3c7a9f7-3cc7-4b25-9617-988594c33f60", "app_id": "548a0869-0d46-4dd2-afbb-7ba83a000162", "jti": "6f3afca4-bb56-48d9-a0ca-6f319b2f7d1d"}