Validating RS256-signed JWT in Azure API Management without an Open ID Connect configuration endpoint.

What a long blog title 🙂 Today, I’ve encountered an issue while using the validate-jwt policy in Azure API Management.  Let’s have a look at it and let me explain how I worked around it.

The scenario

For a proof of concept, I had to integrate Azure API Management with a custom SSO implementation.  The custom SSO supports OAuth2 and I was able to retrieve valid JSON Web Tokens (JWT).  The next challenge was to validate the JWT in Azure API Management.

The error

As always, I configured the validate-jwt policy.  I had the public signing certificate, so I tried the following:

<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized" require-expiration-time="true" require-scheme="Bearer" require-signed-tokens="true">
   <issuer-signing-keys>
      <key>[base64-encoded public signing certificate]</key>
   </issuer-signing-keys>
   <audiences>
     <audience>[SSO audience]</audience>
   </audiences>
</validate-jwt>

At runtime, this gave an internal server error.  The detailed traces showed this exception:

System.NotSupportedException: IDX10634: Unable to create the SignatureProvider. Algorithm: ‘RS256’, SecurityKey: ‘Microsoft.IdentityModel.Tokens.SymmetricSecurityKey’ is not supported.

A very strange error, because the RS256 algorithm is an asymmetric way of signing and not a symmetric, as the exception states.

The solution

After some troubleshooting, it appeared that Azure API Management only supports RS256 signatures, when using an Open ID Connect configuration endpoint (https://YOUR_DOMAIN/.well-known/openid-configuration).  Apparently, inline base64-encoded certificates are considered as symmetric keys.

APIM Warning

As the SSO implementation did not implement this configuration endpoint, my only resort was to mock it.  Therefor, I’ve created a public blob storage container.  In this container, I’ve created two files.

The first one contained the JSON Web Key Set:

{
  "keys": [
    {
      "alg":  "RS256",
      "kty": "RSA",
      "use": "sig",
      "x5c": [
        "[base-64 encoded public signing certificate]"
      ],
      "kid": "1"
    }
  ]
}

The second one contains the minimal discovery configuration that API Management requires.  This file refers with the jwks_uri to the first blob (via a publicly accessible URL)

{
  "jwks_uri": "https://tvhblog.blob.core.windows.net/openid-connect/jwk-set.json",
  "issuer": "[issuer]"
}

Now, I’ was able to configure the validate-jwt policy with the configuration URL:

<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
   <openid-config url="https://tvhblog.blob.core.windows.net/openid-connect/openid-configuration.json" />
</validate-jwt>

With this workaround, API Management is correctly validating the JWT signature.  Additionally, I can extend the policy to validate the audience and claims.

Conclusion

This is a rather strange limitation of Azure API Management.  Fortunately, I was able to work around it by mocking an Open ID connect configuration endpoint.  Public blob storage is ideal for such scenarios.

Hope this helps you out, if you encounter this issue!

Cheers
Toon

About me

Hi! I’m Toon Vanhoutte, a hands-on Azure architect – based in Belgium – with a big passion for teaching and helping people out. I’m happy to assist you during your Azure journey with high-quality advisory and I would love to teach you Azure’s possibilities via my tailored training courses.

Subscribe to the blog