Use the validate-jwt policy with an asymmetric issuer signing key configured from the public key. The signature is validated against the public key; if the modulus/exponent are wrong, validation must fail.
To validate with only a public key, configure one of these options in the validate-jwt policy:
- Use an OpenID configuration endpoint (recommended)
<validate-jwt header-name="Authorization" require-scheme="Bearer">
<openid-config url="https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>api://your-api-app-id</audience>
</audiences>
<issuers>
<issuer>https://login.microsoftonline.com/{tenant}/v2.0</issuer>
</issuers>
</validate-jwt>
openid-config causes API Management to pull the JWKS (public keys) from the identity provider and use them to validate the JWT signature. This is the simplest and most robust way when only the public key is available.
- Use modulus and exponent directly
If the OpenID configuration endpoint cannot be used, specify the RSA public key via issuer-signing-keys with n and e:
<validate-jwt header-name="Authorization" require-scheme="Bearer">
<issuer-signing-keys>
<key id="your-kid" n="{base64url-modulus}" e="{base64url-exponent}" />
</issuer-signing-keys>
<audiences>
<audience>api://your-api-app-id</audience>
</audiences>
<issuers>
<issuer>https://your-issuer</issuer>
</issuers>
</validate-jwt>
Key points to ensure signature is actually validated:
- Do not disable signing
Make sure require-signed-tokens is not set to false:
<validate-jwt header-name="Authorization" require-scheme="Bearer" require-signed-tokens="true">
...
</validate-jwt>
If require-signed-tokens is false, the token is accepted without signature validation, which matches the behavior described (changing key values has no effect).
- Configure
issuer-signing-keys correctly
Within issuer-signing-keys:
- Use
<key id="..." n="..." e="..." /> for an RSA public key.
-
n and e must be Base64url-encoded values of the modulus and exponent.
- If
id is set, it is matched to the token’s kid claim; if no kid matches, API Management will try all keys.
If the key element is misconfigured but require-signed-tokens is false, the token still passes. With require-signed-tokens="true", a mismatched n/e causes validation to fail.
- Ensure other required elements are present
For full validation, configure:
<audiences>
<audience>...</audience>
</audiences>
<issuers>
<issuer>...</issuer>
</issuers>
and keep require-expiration-time at its default true unless there is a specific reason to allow tokens without exp.
- Alternative: certificate-based public key
If the public key is available as a certificate uploaded to API Management, use certificate-id instead of n/e:
<issuer-signing-keys>
<key certificate-id="your-cert-id" />
</issuer-signing-keys>
This also validates the signature using the public key from the certificate.
In summary, to ensure the JWT signature is actually validated when only a public key is available, configure validate-jwt with either openid-config or issuer-signing-keys (n/e or certificate-id) and keep require-signed-tokens="true". If changing modulus/exponent has no effect, the policy is likely not using those keys (for example, because require-signed-tokens is disabled or the token is not signed with an asymmetric algorithm supported by the policy).
References: