Why does MobilePay have Code Challenge in the OIDC implementation?

MobilePay has chosen to use Code Challenge, since it removes potential attack options. An intercepted code is unusable in itself, but the problem really lies in how "easy" it is to get a cliendID + ClientSecret valid for the Api Gateway. That depends on a hackers ability to decode either the stored client in the MobilePay app or any other 3rd party app. In other words, we cannot rely on it to secure a specific user credentials. Since there is no coupling between the code and the api-connect client, any MobilePay client will probably do. However, by using PKCE, MobilePay solves that problem.

PKCE / Code Challenge

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. 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. 

Terminology: 

  • code verifier: A cryptographically random string that is used to correlate the authorization request to the token request.
  • code challenge: A challenge derived from the code verifier that is sent in the authorization request, to be verified against later.
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.