Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with Microsoft Entra ID (former Azure AD) authentication #379

Open
GrzegorzHejman opened this issue Feb 13, 2024 · 26 comments
Open

Comments

@GrzegorzHejman
Copy link

Has anyone tried to use Microsoft Entra ID (former Azure AD) as an OIDC IDP? When I try to configure it, it seems to work ok (Tapir gets the correct token), except I get the token verification error:

ERROR [io.qua.oid.run.CodeAuthenticationMechanism] (vert.x-eventloop-thread-1) ID token verification has failed: JWT rejected due to invalid signature.

I've found this information related to the same or very similar issue:

quarkusio/quarkus#32701

And it seems that this PR enables verification customization to work with Azure AD tokens:

quarkusio/quarkus#33319

@PacoVK
Copy link
Owner

PacoVK commented Feb 23, 2024

thanks for bringing this up. I think i need some time to investigate here. If you found a solution meanwhile i am eager to here about it :)

@GrzegorzHejman
Copy link
Author

Unfortunately, I'm not so familiar with quarkus and Java, but I understand that for Entra ID (AAD) tokens a customized token verification process needs to be used. The PR I mentioned before contains code that allows for such customization.

@PacoVK
Copy link
Owner

PacoVK commented Mar 4, 2024

All good, it's cool that you brought that up.I am still a bit short in time currently, but i will try to investigate as soon as i find time :)

@PacoVK
Copy link
Owner

PacoVK commented Mar 14, 2024

@GrzegorzHejman after researching a bit, i have a follow-up question. Did you set AUTH_PROVIDER to microsoft? This should then include the TokenCustomizer for Azure already (that one you linked in the second PR). I coul also reproduce your issue if i do not set AUTH_PROVIDER to microsoft.

@GrzegorzHejman
Copy link
Author

@PacoVK I was unable to make it work with AUTH_PROVIDER, but I used the environmental variable QUARKUS_OIDC_TOKEN_CUSTOMIZER_NAME='azure-access-token-customizer', which seems to have resolved the issue.

@PacoVK
Copy link
Owner

PacoVK commented Apr 12, 2024

Awesome, that you were able to fix this. I'll make sure to make it a bit more convinient for future use.

@cedricbraekevelt
Copy link

@PacoVK can I find any information on how to set this up using Entra ID auth? I tried the following parameters but doesn't seem to work:
AUTH_PROVIDER microsoft
AUTH_ENDPOINT https://login.microsoftonline.com/{tenant}/v2.0
AUTH_CLIENT_ID {clientid}
AUTH_CLIENT_SECRET {clientsecret}

I want to change the redirect URI of Quarkus in Tapir.
By default it redirects to HTTP (my environment is hosted on Azure Container Apps), but I can only use HTTPS for redirection to a App Registration callback URI.

@PacoVK
Copy link
Owner

PacoVK commented Apr 30, 2024

Hey @cedricbraekevelt i think you need to follow #379 (comment) and set QUARKUS_OIDC_TOKEN_CUSTOMIZER_NAME='azure-access-token-customizer' i did not yet make it to fix this in a more convinient way. Seems like setting AUTH_PROVIDER=microsoft does not exactly what i thought it would do...

@cedricbraekevelt
Copy link

Hi @PacoVK ,

Thanks for the answer, however the issue i'm experiencing is I can't seem to figure out how to set the callback URL in Tapir for the App Registration. The callback URL in my App registration is: https://tapir.{DOMAIN}.com/.auth/login/aad/callback. However when I go to the application, it tries to redirect me to http://tapir.{DOMAIN}.com/. HTTP is not allowed on App registrations (except for localhost but since this is is running in Azure Container Apps I'm guessing this is not a solution?

PS: tried setting both AUTH_TOKEN_PATH and AUTH_PATH but didn't seem to make a difference in the callback URL.

@GrzegorzHejman
Copy link
Author

@cedricbraekevelt, to configure redirection you can try: QUARKUS_OIDC_AUTHENTICATION_FORCE_REDIRECT_HTTPS_SCHEME='true'

Please also try to remove AUTH_PROVIDER and use:
QUARKUS_OIDC_TOKEN_CUSTOMIZER_NAME='azure-access-token-customizer'

With those two changes I was able to get the token. The problem I faced then was that the token was issued from the STS endpoint, not the expected one. I didn't have time to test it more, but it's related to the app registration and token configuration on Entra ID side. Generally, it needs to be configured to issue v2 tokens , but I haven't figured out that part yet.

@cedricbraekevelt
Copy link

cedricbraekevelt commented Apr 30, 2024

@GrzegorzHejman @PacoVK Thanks, I've come further however the next error I'm receiving:

ID token verification has failed: Token issued to client {CLIENTID} can not be introspected because the introspection endpoint address is unknown - please check if your OpenId Connect Provider supports the token introspection

Sorry for being so helpless but this is unknown terrain for me :) However I'd really like a Terraform registry

@GrzegorzHejman
Copy link
Author

@cedricbraekevelt, I'm not sure if this helps, but please try to add "/" to the end of the AUTH_ENDPOINT:
AUTH_ENDPOINT https://login.microsoftonline.com/{tenant}/v2.0/

@cedricbraekevelt
Copy link

@GrzegorzHejman I already changed the AUTH_ENDPOINT to https://sts.windows.net/{TENANT}/ because I got another error related to the issuer not matching. However the extra "/" doesn't seem to matter for the introspection error

@cedricbraekevelt
Copy link

@PacoVK would it be possible to provide a reference config of the auth parameters / specific App Registration settings to get this to work? :-)

@cedricbraekevelt
Copy link

Hi @PacoVK , @GrzegorzHejman

I made it work by using these settings:
QUARKUS_OIDC_AUTHENTICATION_FORCE_REDIRECT_HTTPS_SCHEME='true'
QUARKUS_OIDC_TOKEN_CUSTOMIZER_NAME='azure-access-token-customizer'
QUARKUS_OIDC_PROVIDER='microsoft'
QUARKUS_OIDC_AUTHENTICATION_VERIFY_ACCESS_TOKEN='false'

However the thing that I can't get to work is how to become "admin".
I've read in the docs you need to add the "admin" role in the token.
I've tried adding an app role to my app registration with key "role" and value "admin", and key "admin" and value "admin" but none seem to work. Care to elaborate?

@TomBeckett
Copy link
Contributor

Just to add my voice to @cedricbraekevelt .

I'm also trying to get SSO working on Azure. I'm using the same settings a the previous reply and I've also tried the same role + admin combo.

On my end users correctly authenticate but are landing with no admin role.

@cedricbraekevelt
Copy link

Hi @TomBeckett , @PacoVK,

I've found the following guide which according to your code does what should be required:
https://www.kantega.no/blogg/role-based-access-control-with-quarkus-and-microsoft-azure-active-directory
However, I still get no admin permission with alles these settings enabled.
The last thing I can do is enable the trace logging but that's for another day.

@PacoVK
Copy link
Owner

PacoVK commented May 15, 2024

Thanks @cedricbraekevelt for your time on investigation. I need a bit time but I will take a look at this soon. Could you please do me a favor and let me know how an example token issued by Azure looks like? I already have a guess what the solution could be. Please ensure to not paste a valid token 😊

@cedricbraekevelt
Copy link

cedricbraekevelt commented May 15, 2024

Hi @PacoVK , @TomBeckett,

Today I've been able to find out some more:
Improve logging with: QUARKUS_LOG_CATEGORY__IO_QUARKUS_OIDC__LEVEL = trace

QUARKUS_OIDC_ROLES_ROLE_CLAIM_PATH = roles because by default Quarkus looks for groups in keycloak
QUARKUS_OIDC_TOKEN_AUDIENCE = any otherwise i get an error that the audience of the token isn't correct (only when using the authentication scopes property below)
QUARKUS_OIDC_AUTHENTICATION_SCOPES = api://{clientid}/.default profile email

However this last entry changes break tapir and I'm unable to login anymore. This results in the following JWT token:

{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "{x5t}",
  "kid": "{kid}"
}.{
  "aud": "api://{clientid}",
  "iss": "https://sts.windows.net/{tenantid}/",
  "iat": 1715797615,
  "nbf": 1715797615,
  "exp": 1715802685,
  "acr": "1",
  "aio": "{aio}",
  "amr": [
    "pwd",
    "mfa"
  ],
  "appid": "{clientid}",
  "appidacr": "1",
  "family_name": "{familyname}",
  "given_name": "{givenname}",
  "ipaddr": "{publicip}",
  "name": "{name}",
  "oid": "{oid}",
  "rh": "{rh}",
  "roles": [
    "admin"
  ],
  "scp": "admins",
  "sub": "{sub}",
  "tid": "{tid}",
  "unique_name": "{uniquename}",
  "upn": "{upn}",
  "uti": "{uti}",
  "ver": "1.0"
}.[Signature]

The reason according to logs in azure container apps that the page fails to load with this token is the following:

2024-05-15T18:43:59.805375838Z 2024-05-15 18:43:59,805 ERROR [io.qua.oid.run.OidcProviderClient] (vert.x-eventloop-thread-1) Request https://graph.microsoft.com/oidc/userinfo has failed: status: 401, error message: {"error":{"code":"InvalidAuthenticationToken","message":"Access token validation failure. Invalid audience.","innerError":{"date":"2024-05-15T18:43:59","request-id":"{rid}","client-request-id":"{crid}"}}}
2024-05-15T18:43:59.805989373Z 2024-05-15 18:43:59,805 ERROR [io.qua.oid.run.CodeAuthenticationMechanism] (vert.x-eventloop-thread-1) ID token verification has failed: {"error":{"code":"InvalidAuthenticationToken","message":"Access token validation failure. Invalid audience.","innerError":{"date":"2024-05-15T18:43:59","request-id":"{rid}","client-request-id":"{crid}"}}}

without the QUARKUS_OIDC_AUTHENTICATION_SCOPES setting I get the following JWT token:

{
  "typ": "JWT",
  "nonce": "{nonce}",
  "alg": "RS256",
  "x5t": "{x5t}",
  "kid": "{kid}"
}.{
  "aud": "00000003-0000-0000-c000-000000000000",
  "iss": "https://sts.windows.net/{tenantid}/",
  "iat": 1715797866,
  "nbf": 1715797866,
  "exp": 1715802994,
  "acct": 0,
  "acr": "1",
  "aio": "{aio}",
  "amr": [
    "pwd",
    "mfa"
  ],
  "app_displayname": "tapir",
  "appid": "{clientid}",
  "appidacr": "1",
  "family_name": "{familyname}",
  "given_name": "{givenname}",
  "idtyp": "user",
  "ipaddr": "{publicip}",
  "name": "{name}",
  "oid": "{oid}",
  "platf": "3",
  "puid": "{puid}",
  "rh": "{rh}",
  "scp": "email openid profile User.Read User.Read.All",
  "signin_state": [
    "kmsi"
  ],
  "sub": "{sub}",
  "tid": "{tid}",
  "tenant_region_scope": "EU",
  "unique_name": "{uniquename}",
  "upn": "{upn}",
  "uti": "{uti}",
  "ver": "1.0",
  "wids": [
    "{wid1}",
    "{wid2}"
  ],
  "xms_st": {
    "sub": "{sub}"
  },
  "xms_tcdt": {tcdt},
  "xms_tdbr": "EU"
}.[Signature]

Things that I find interesting:

  • Token has another audience api://{clientid} vs 00000003-0000-0000-c000-000000000000 (which is Microsoft Graph)
  • The token generated by the Microsoft Graph Enterprise app doesn't contain the roles whereas mine does.
  • To get the roles into the token I had to change the following settings in the app registration:
    • Add an approle (mine is called admins) with a value "admin"
    • Add a scope via "expose an API" called admins which has as consent display name admin
      -Add Application Admin Consent for the admins scope and Delegated Admin Consent for the admin app role.
      (not sure if all above steps are necessary)

Hope this helps you further :-)

PS: still using 7.0.0 because docker hub latest refers to 7.0.0 i think :p

@TomBeckett
Copy link
Contributor

TomBeckett commented May 16, 2024

We've managed to get Tapir working using the following settings:

env {
  name  = "QUARKUS_OIDC_PROVIDER"
  value = "microsoft"
}

env {
  name  = "QUARKUS_OIDC_TOKEN_CUSTOMIZER_NAME"
  value = "azure-access-token-customizer"
}

env {
  name  = "QUARKUS_OIDC_ROLES_ROLE_CLAIM_PATH"
  value = "roles"
}

env {
  name  = "QUARKUS_OIDC_ROLES_SOURCE"
  value = "idtoken"
}

env {
  name  = "QUARKUS_OIDC_AUTHENTICATION_FORCE_REDIRECT_HTTPS_SCHEME"
  value = true
}

env {
  name  = "QUARKUS_HTTP_CORS_ORIGINS"
  value = "*" // INJECT NAME
}

env {
  name  = "AUTH_ENDPOINT"
  value = var.auth_endpoint
}

env {
  name  = "AUTH_CLIENT_ID"
  value = var.auth_client_id
}

env {
  name = "AUTH_CLIENT_SECRET"
  secret_name = var.auth_client_secret_vault_name
}

I should also mention we've had to roll back to 0.7.0 as we get 404 errors on 0.7.1.

EDIT: I raised a separate issue and PR for the 404 mentioned above.

@cedricbraekevelt
Copy link

cedricbraekevelt commented May 16, 2024

I can confirm the above settings work, I also have the same issue with 0.7.1 and am using 0.7.0 now. Thanks for the solution @TomBeckett. Looking forward to an update to fix 0.7.1 :)

PS: I'm having an issue when creating any type of deploy key
image
No errors are shown in the logs (running on Azure Container Apps)

@finkinfridom
Copy link

I tried all the above suggestions/fixes but still getting errors.
I tried to access my "tapir" instance at https://tapir.mydomain.com. I'm asked to log in and then I'm redirected to a 502 page.
I added the trace key for log level and I can see a bunch of logs in my application but no warns nor errors.

Any suggestion?
At first I was getting a 401 response from Tapir but after configuring the token I just receive 502 without any additional info.

@PacoVK
Copy link
Owner

PacoVK commented Jun 7, 2024

@all-contributors please add @GrzegorzHejman for bug

Copy link
Contributor

@PacoVK

I've put up a pull request to add @GrzegorzHejman! 🎉

@PacoVK
Copy link
Owner

PacoVK commented Jun 7, 2024

@all-contributors please add @cedricbraekevelt for bug

Copy link
Contributor

@PacoVK

I've put up a pull request to add @cedricbraekevelt! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants