Proof Key for Code Exchange Flow

Last updated: December 21, 2020

Introduction

OAuth 2.0

At Decathlon, we value the integrity and security of our members' data above all else.  In order for your applications to access Decathlon member data and/or act on their behalf, they must be Authenticated.  To make this process as easy as possible, Decathlon relies on the industry-standard OAuth 2.0 protocol for granting access. 



OAuth 2.0 [RFC6749] public clients are susceptible to the authorization code interception attack.

In this attack, the attacker intercepts the authorization code returned from the authorization endpoint within a communication path not protected by Transport Layer Security (TLS), such as inter- application communication within the client's operating system.

Once the attacker has gained access to the authorization code, it can use it to obtain the access token.

To mitigate this attack, this flow utilizes a dynamically created cryptographically random key called "code verifier". A unique code verifier is created for every authorization request, and its transformed value, called "code challenge", is sent to the authorization server to obtain the authorization code. The authorization code obtained is then sent to the token endpoint with the "code verifier", and the server compares it with the previously received request code so that it can perform the proof of possession of the "code verifier" by the client. This works as the mitigation since the attacker would not know this one-time key, since it is sent over TLS and cannot be intercepted.

PKCE is a RFC standard, you can find the full documentation here.

Disclaimer

Configuring your application


If you have not already done so, request for your application creation.


Useful Tip:

In order to request your access, you will need to provide us some information
  • Application Name (displayed to the user)
  • Redirect URI (can have multiple)
  • Logo (100x100 .png)
  • Your Privacy Policy URL
  • Your Terms of Service URL
  • Your Logout URL
  • The scope you need to access to :

To prevent fraudulent transactions during the authentication process, we will only communicate with URLs that you have identified as trusted endpoints.
Ensure the "OAuth 2.0 Redirect URLs" field for your application contains a valid callback URL to your server that is listening to complete your portion of the authentication workflow.


Once created, your application will be assigned a unique Client ID value.

How To Implement?

Request an Authorization Code


It's time to request an authorization code.

The authorization code is not the final token that you use to make calls to Decathlon.  It is used in the next step of the OAuth 2.0 flow to exchange for an actual access token. 

Creating the verifier
First, you should create a code verifier, "code_verifier", in the following manner:
code_verifier = high-entropy cryptographic random STRING using the unreserved characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" from Section 2.3 of [RFC3986], with a minimum length of 43 characters and a maximum length of 128 characters.

Creating the Code Challenge
Then, you should create a code challenge derived from the code verifier by using one of the following transformations on the code verifier:

plain

code_challenge = code_verifier

S256

code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

If your application is capable of using "S256", it MUST use "S256", as "S256" is Mandatory To Implement (MTI) on the server. Clients are permitted to use "plain" only if you cannot support "S256" for some technical reason and know via out-of-band configuration that the server supports "plain".

The plain transformation is for compatibility with existing deployments and for constrained environments that can't use the S256 transformation.

Sending the Code Challenge with the Authorization Request

To request an authorization code, you must direct the user's browser to Decathlon Login's OAuth 2.0 authorization endpoint.

Also, you need to send the code challenge as part of the OAuth 2.0 Authorization Request (Section 4.1.1 of [RFC6749]) using the following additional parameters:

code_challenge

REQUIRED. Code challenge.

code_challenge_method

OPTIONAL, defaults to "plain" if not present in the request. Code verifier transformation method is "S256" or "plain".

Notes:
  • If the user has not previously accepted the application's permission request, or the grant has expired or been manually revoked by the user, the browser will be redirected to Decathlon Login's authorization screen.
  • If there is a valid existing permission grant from the user, the authorization screen is by-passed
Redirecting the User
When the user completes the authorization process, the browser is redirected to the URL provided in the redirect_uri query parameter.

GET https://api-global.decathlon.net/connect/oauth/authorize

Parameters :
Parameter Description Required
client_id The "API Key" value generated when you registered your application. Yes
redirect_uri

The URI your users will be sent back to after authorization.  This value must match one of your configured OAuth 2.0 Redirect URLs

Yes
response_type The value of this field should always be: code for this flow (token for Implicit flow) Yes
state

A unique string value of your choice that is hard to guess. Used to prevent CSRF

Yes
code_challenge

The code challenge generated as previously described.

Yes
code_challenge_method

Either S256 or plain, depending on whether the challenge is the SHA256 hash of the verifier or the plain verifier string. If this parameter is omitted, the server will assume plain.

Optional
scope

A URL-encoded, space-delimited list of member permissions your application is requesting on behalf of the user. 

Optional


Example :
https://api-global.decathlon.net/connect/oauth/authorize?client_id=a97za22a-1320-41f6-9aad-ee3118654fbe&redirect_uri=https%3A%2F%2Fblablabla.com&response_type=code&code_challenge=f1P0WWFXx1nuKzzbAk7mlzHGOKMN5YVSTT64h2f8ED8&code_challenge_method=S256&scope=profile%20sports
                                            

Application is approved

If the user was not logged in, Decathlon Login would ask him for a login and a password.
If it the first time he uses your application OR if you asked for a new scope access, he will have to approve your application's request to access data.
This approval instructs Decathlon Login to redirect the user back to your redirect_uri parameter.

Attached to the redirect_uri will be two important URL arguments that you need to read from the request:

  • code — The OAuth 2.0 authorization code.
  • state — A value used to test for possible CSRF attacks. It should be the same one you entered in your request

The code is a value that you will exchange with Decathlon Login for an actual OAuth 2.0 access token in the next step of the process.
For security reasons, the authorization code has a very short lifetime and must be used within moments of receiving it.

Exchange Authorization Code for an Access Token

The final step towards obtaining an Access Token is for your application to ask for one using the Authorization Code it just acquired.


POST https://api-global.decathlon.net/connect/oauth/token

Parameters :
Parameter Description Required
client_id The "API Key" value generated when you registered your application. Yes
client_secret The "Secret Key" value generated when you registered your application. Yes
code The authorization code you received from the previous call. Yes
redirect_uri The same 'redirect_uri' value that you passed in the previous step Yes
grant_type The value of this field should always be: authorization_code Yes
code_verifier The code verifier for the PKCE request, that the app originally generated before the authorization request. Yes

For example, a call should like the following:



curl -X POST \
  'https://api-global.decathlon.net/connect/oauth/token?client_id=fake_client_id&grant_type=authorization_code&code=3Qx7Vz&code_verifier=aaxD8mWaqiZJAIiLyhgliE9PNL-3boDvls0xo65HNpQ&redirect_uri=https://apiproxy-v3.preprod.subsidia.org/connect/oauth/mock_redirect_uri' \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: f144e6a1-5009-4d19-b85f-057b855d50e7' \
  -H 'cache-control: no-cache'

                                                

Response: Access Token

In response, you will get a JSON object containing the following fields:

  • access_token: The access token for the user. This value must be secured.
  • token_typeThe type of token this is, typically just the string “bearer”.
  • expires_inThe number of seconds remaining, from the time it was requested before the token will expire.
  • refresh_token: (optional) can be used to obtain another access token after access_token expiration.
  • jti: (optional) The "jti" (JWT ID) claim provides a unique identifier for the JWT.

For example, a successful token response may look like the following:


{
    "access_token": "eyJhbGciOiJSUzI1NEnR5cCI6IkpXVCJ9.eyJzdWIiOiI1YWIxMjY3OC1hYzhmLTRkM2YtOTMzOC02NTJlNzkxZGMyZWEiLCJzY29wZSI6WyJwcm9maWxlIl0sImlzcyI6ImRrY29ubmVjdC5vcmciLCJkYXX2NlbnRlciI6IkVVIiwicGVyc29uaWQiOiI1MDAwMDIzNDcwMSIsImV4cCI6MTU0NTEyNjA2NCwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjgxOTgxMTllLWQ4YjktNDc1ZC04MTlmLWExYTQyYWQ5YzNkMCIsImNsaWVudF9pZCI6ImRrY29ubmVjdCJ9.HGNlzYh_mlAmdazSMejNd2totNYChUZ33oZUHo27L_xfWR-C_b8-IUg-MKC0w-Or6zahifqJN5y1NfNlqrsLrAWXFg-ZDAyUYgec3kQmRaFG1AgLFUjwsCvGSYcIGY41PHM0WKRENyU_oDL7bN9AjaOLe3Ob-c2BRWBQu6a5W6fmqugQ28ZFLTGDUTcIcsOdTg0DqBU82B_CjsVrK_x1gLM4y2ozkXJ_OmvCl5CjNsvaYJHKANl8gA5TQgX7IaUAwf7YNcun_rnO1k-FeYoc_OLHWIQG1UDrbDrtUUH-WQo7AE9X5BhgzXjWd1rubv703nbq6RP3BeeoeoJIDQ",
    "token_type": "bearer",
    "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1YWIxMjY3OC1hYzhmLTRkM2YtOTMzOC02NTJlNzkxZGMyZWEiLCJzY29wZSI6WyJwcm9maWxlIl0sImF0aSI6IjgxOTgxMTllLWQ4YjktNDc1ZTlmLWExYTQyYWQ5YzNkMCIsImlzcyI6ImRrY29ubmVjdC5vcmciLCJkYXRhX2NlbnRlciI6IkVVIiwicGVyc29uaWQiOiI1MDAwMDIzNDcwMSIsImV4cCI6MTU0NzcxNzE2NCwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjM2NTIyZmZkLWNkZDQtNDE5Ny1iYTVlLWNmNDQ2YzA2OWIzYSIsImNsaWVudF9pZCI6ImRrY29ubmVjdCJ9.5f9tqB1G6qZRpGcVwMQQMtLslNeqX$$$$4Ehi4TFmvVNGofFJpFh-AW5lt-7ye7aKGzYqFdcusDzuuaEDnBnS44qIKUTxomclj1T9BGBYDI5-2PFDFnOaN--ly6dx4vu_TIw9pXJycVCzeq22H5EDrgcF0hbTE4wDQ9lTpV4tDAyYJ3l4QSah9wnWnJQ-Y5rh2v5znQ0Eutu36-tSC_2seII5la_HGrrFuUKNVIu5AJrh_dvs_9Vq-PGu9ODu74bVa8UfMDOEr8sk-ZVvfhiJzzsWBbf7f2wiNneWtA-EhngEA4ZI7RyOeCC_DaGZm6W9N11YyZY-SreFgA",
    "expires_in": 899,
    "scope": "profile",
    "jti": "8198119e-d8b9-475d-819f-a1a42ad9c3d0"
}

                                                

What is a refresh Token?

A Refresh Token is a special kind of token that can be used to obtain a renewed access token —that allows accessing a protected resource— at any time.
You can request new access tokens until the refresh token is blacklisted.
Refresh tokens must be stored securely by an application because they essentially allow a user to remain authenticated forever.

Response: Error

Error responses are returned with an HTTP 400 status code, with error and error_description parameters. The error parameter will always be one of the values listed below.

  • invalid_request: Missing parameter or unsupported one
  • invalid_client: Invalid client ID or secret
  • invalid_grant: The authorization code is invalid or expired, the verifier code is invalid, or the redirect URL given in the authorization grant does not match the URL provided in this access token request
  • invalid_scope: Invalid scope value in the request
  • unauthorized_client: This client is not authorized to use the requested grant type
  • unsupported_grant_type: If a grant type is requested that the authorization server doesn’t recognize

The optional "error_description" parameter is meant to give developers more information about the error, not intended to be shown to end users.

For example, an error response may look like the following:


{
    "error": "invalid_grant",
    "error_description": "Invalid authorization code: 3Qx7Vz"
}

                                                
Terms & Services