Step 4: Refresh token

To get a Refresh Token, you must include the offline_access scope when you initiate an authentication request through the authorize endpoint. To refresh your token, using the Refresh Token you already got during authorization, make a POST request to the token endpoint. Read more here 

Step 4: Keep the session alive by using the refresh token

Whenever an ccess_token is required to access a protected resource, a client may use a refresh_token to get a new Access Token issued by the Authentication Server. Although access_token can be renewed at any time using refresh_tokens, they should be renewed when old ones have expired, or when getting access to a new resource for the first time. When the access_token expires, the refresh_token can be used to obtain a fresh access_token with the same permissions, without further involvement from a user.

When the access_token expires, you can use the refresh_token to get a new access_token by using the token endpoint as shown below:

Sample request:

POST https://api.sandbox.mobilepay.dk/merchant-authentication-openidconnect/connect/token
Content-Type: application/x-www-form-urlencoded
Host: api.sandbox.mobilepay.dk
Body
&grant_type
=refresh_token
&refresh_token=01cab0f861cdb89c326604cae408ae6e8c57e72c70c84143b93e04bbecb8c748
&client_id=some.test.client.received.in.zipfile
&client_secret=mysecret.received.in.zip.file

Explanation of parameters:

Parameter Description Value Required
grant_type
 A way to specify how the client will interact with the server Must be set to "refresh token" yes
refresh_token The refresh token to be used The existing refresh token  yes
client_id The client_id that you received by zip file This is not the same as the MerchantID or the e-mail log-in to https://sandprod-admin.mobilepay.dk The client-id given in the zip file yes
client_secret The client_secret that you received by zip file  The client_secret tht you received  in the zip file.  yes

refresh_tokens are long-lived. This means when a client gets one from a server, this token must be stored securely to keep it from being used by potential attackers. Therefore, it is not safe to store them in the browser. If a refresh_token is leaked, it may be used to obtain new access_token (and access protected resources) until it is blacklisted. 

  • Please ensure
    • that the required parameters are sent in the request
    • that the request is authorized. Check that the client_id and client_secret received in the zip file are present in the request and hold valid values. 

To get a Refresh Token, you must include the offline_access scope when you initiate an authentication request through the authorize endpoint. Read more about the Authorization Request here

If the refresh token is valid, then you get back a new access/refresh token combination:

{
    "id-token" : "MIOf-U1zQbyfa3[...]MUfJHhvnUqIut9ClH0xjlDXGJAyqo"
    "access_token": "eyJhbGciOiJ[...]K1Sun9bA",
    "token_type": "Bearer",
    "expires_in": 300,
    "token_type": "Bearer",
    "refresh_token": "MIOf-U1zQbyfa3[...]MUfJHhvnUqIut9ClH0xjlDXGJAyqo"
}

 

Maintaining tokens 

You can exchange your refresh token for a new pair of access token and refresh token.

SingleUse:

    1. Get the access token and refresh_token by redirecting the merchant to login URI and handling the response
    2. IT-integrator stores the  access token somewhere, along with its validity (cache, in-memory dictionary or something else) and use it until it is valid. You can save the  access token  persistent. It depends on the implementation 
    3. IT-integrator store the refresh_token somewhere, where it would be persistent and secure.
      1. Note: that if a merchant revokes the consent, then there is a delay of 5 minutes where the integrator still can use the  access token until it expires.  refresh_token will not be able to be used, and this means that the integrator will not be able to obtain a new access_token 
    4. Once the  access_token expires, you use your stored  refresh_token  to get new  access token  and new refresh_token  and repeat #3 and #4. It will contain  access_token ,  refresh_token and ExpiresIn property.
    5. If refresh token is no longer valid (that is, if you fail to refresh your tokens using it before it expires) – you need to go back to step #1

    If you’re using the same .NET library that’s used in our sample solution for interacting with OpenID Connect flow, then you can use OidcClient.RefreshTokenAsync() method to make the exchange. Also, the LoginResult class, coming back from OidcClient.ProcessResponseAsync() has a property called AccessTokenExpiration, which tells you how long the access token is valid, so that the IT-integrator can know, when it’s time to refresh the access token, without making a call to MobilePay service and receiving 401.

    Note: Do not call multiple times to get refresh_token, to be sure that you have the access_token. Prioritize having a code logic, that checks whether the access_token is expired, and then you use refresh_token to get a new valid access_token

    Invalid tokens  

     If you make an API call using an invalid token, you will receive a "401 Unauthorized" response back from the server.  A token could be invalid and in need of regeneration because:

    • It has expired.
    • The user has revoked the permission they initially granted 
    • You have changed the (scope) your application is requesting.
    • A subsequent OpenID Connect flow that generated a new access token. The previous token will be invalidated.

    You should only ask for a new token if the Access Token has expired or you want to refresh the claims contained in the ID Token. For example, it's a bad practice to call the endpoint to get a new Access Token every time you call an API. 

    Refresh tokens can expire but are long-lived.

    Refresh tokens are subject to strict storage requirements to ensure they are not leaked. 

    Since a predictable expiry time is not the only contributing factor to token invalidation, it is very important that you code your applications to properly handle an encounter with a 401 error by redirecting the user back to the start of the authorization workflow.

    PKCE / Code Challenge

    For more information on the PKCE protocol and the security considerations, see IETF RFC 7636

    MobilePay supports the Proof Key for Code Exchange protocol to make the flow more secure. 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. Example: you can find it in the C# example. Note that it is hidden in the framework. This line calls a identitymodel feature which automatically uses PKCE. 

    Terminology: 

    • code verifier: A cryptographically random string that is used to correlate the authorization request to the token request. The client creates a one-time secret (code verifier)  that is used to generate a code challenge
    • code challenge: A challenge derived from the code verifier that is sent in the authorization request, to be verified against later. Code challenge is also referred to as the code that you generated, and made cryptographically secure and sent to us in ./authorize endpoint property code challenge. 
    PKCE Parameters
    code_verifier

    A random value of 43-128 characters. Created by the client. Stored on the server upon an authorization request.

     The recommended value is a 32-octet sequence that is base64url-encoded to create a 43-octet URL safe string.  

    code_challenge_method

    The code challenge method used to generate the code challenge value.

    • S256 – SHA256 encoding is performed: code_challenge=base64url(sha256(code_verifier))
    code_challenge Value based on the code_verifier and the code_challenge_method.
    private string CreateCodeChallenge()
    {
        _codeVerifier = RandomNumberGenerator.CreateUniqueId();
        var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256);
        var challengeBuffer = sha256.HashData(
            CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(_codeVerifier)));
        byte[] challengeBytes;
        CryptographicBuffer.CopyToByteArray(challengeBuffer, out challengeBytes);
        return Base64Url.Encode(challengeBytes);
    }

     Regarding code_challenge. Here is how Identity Server does validation: 

    • var codeVerifierBytes = Encoding.ASCII.GetBytes(codeVerifier);
    • var hashedBytes = codeVerifierBytes.Sha256();
    • var transformedCodeVerifier = Base64Url.Encode(hashedBytes);
    • return TimeConstantComparer.IsEqual(transformedCodeVerifier.Sha256(), codeChallenge);

    If you get an error that the code challenge is either too short or too long, please update the value of code_challenge to meet the requirements and try again. Regarding code_verifier, it has the length requirements as code challenge. 

    • CodeChallengeMinLength = 43
    • CodeChallengeMaxLength = 128

    The method for calculating code_challenge base64urlencoder(Sha256(code_verifier)) when challenge method is S256. 


    How Can Access be Revoked?

    It might be useful for you to know, what happens in theory, if your merchant decides to revoke the consent. 

    • The merchant can revoke the consent for the Integrator. It's done from menu item Settings → Integration. The Tab is not displayed if no consent is granted.
    • If a merchant grants consent to multiple integrators, all of them will have access to all the subscription providers and all agreements. Most merchants only have one subscription provider, and therefore have little reason to work with two seperate integrators at the same time. 
    • access can be revoked at any time though, and once consent is revoked, the integrator won't be able to access that merchant with their token, nor will they be able to refresh the token. 

    Revoke consent

    Safely Storing Credentials

    Keeping credentials secure is important. Please consider these safety suggestions when working with the MobilePay platform.   

     

    Previous step Best Practice