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