14-Jul-2022 07:31 - edited 14-Jul-2022 07:33
Dear F5 community,
Using F5 APM 16.1.3 (as an oauth resource server) I am trying to implement a per-request policy that will verify the signature of JWT tokens sent by the client. These JWT tokens can be issued from two differents issuer (Azure AD or STS).
I am able to verify JWT tokens for each provider seperatly using a dedicated "JWT provider" with only one Provider attached.
When using 2 providers as follow
I got following error message:
WWW-Authenticate: Bearer error="invalid_token",error_description="Issuer Mismatch : Claim issuer= https://sts.windows.net/ Provider issuer=https://login.microsoftonline.com/v2.0"
Based on F5 doc below, the built-in object supports having multiple JWT providers
Configuration is pretty simple:
- 1 Access Policy with "Allow" all ending
- 1 Per-Request Policy with "OAuth Scope" set to "Internal" with the "jwt-allowed-providers-list"
I guess It is most likely a bug.
Anyone was able to make it work with multiple JWT providers ?
I can workaround this by parsing the JWT payload, then determining the issuer and based on the issuer make two branches in the VPE:
- first branch with the "oauth scope A" that will validate the token using JWT-Provider-A
- second branch with the "oauth scope B" that will validate the token using JWT-Provider-B
You confirm that the JWT and JWK objects are different for each provider ?
Dear Yoann 🙂
Hope you are doing well.
Yes each provider has its own JWK & JWT objects that are auto-generated using the "Discovery" job.
Yes fine 🙂
Would be interesting to see what is autodiscovered. I made a quick test with :
- 2 OAUTH Server configured in JWT + Openid connect + autodiscovery on F5 with different Issuers
- 1 OAUTH Resource with the same policy as yours (with a provide list that include the 2 OAUTH Servers) and it seems to work 😕
Can you provide the 2 autodiscovery URLs used for Microsoft ?
I had a bit of time, so I reproduced this in a lab. This behaviour is mainly related to
- the 2 oAuth servers from Microsoft using the same jwt keys (same kid)
- F5 APM using the kid ot in the JWT Header to locate the JWK in the configuration, then the JWT including the issuer.
The scenario you are hitting is :
- you get your JWT from issuer https://sts.windows.net/.
- the header of this JWT contains kid : 123456
- APM locates amongs the JWKs the kid : 123456
- but somehow selects the JWK gathered from the Discovery of https://login.microsoftonline.com/v2.0
- the JWK is linked the the JWT in APM from issuer https://login.microsoftonline.com/v2.0
- this triggers the error as issuer of the received JWT does not match the one configured in the JWT object selected by APM during the matching 😕
If someone from F5 reads this : wouldn't it make sense to change the JWK matching to include criterias kid AND issuer ?
In the mean time :
- your workaround is great I think
- another one woud be to create a with 2 cascaded OAUTH Scopes, with on provider in each. The secon OAUTH scope being in the "fallback" branch of the first one.
Otherwise you might have to open a ticket, who knows, there might be a EngHF for that 🙂
Thank you for your time.
Absolutly agree with your analysis. It seems that F5 will only check the "KID" instead of checking "the Issuer AND the KID" to verify the signature of the JWT token.
Regarding the workaround you mentioned "cascaded of OAuth Scope" I did not mention it in my post because when I implement this solution it worked fine but in the logs it does not create the "subsession" correctly when it passes through the second "OAuth Scope".
As you can see below, when I have the following VPE for the Per-Request Policy:
=> logs in /var/log/apm shows:
- OAuth Scope: succeeded for jwt-provider-list '/Common/jwtprovider-azuread-v20'
The "cascaded OAuth Scope" workaround was my preferred one since it avoid using custom dev. with "irule event" + "irule" to parse the JWT and retrieve the issuer but unfortunatly it does not work as expected on APM side but HTTP side is OK.
So I guess it is another bug...