PacoVK / tapir

A Private Terraform Registry
https://pascal.euhus.dev/tapir/
Apache License 2.0
193 stars 14 forks source link

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

Open GrzegorzHejman opened 7 months ago

GrzegorzHejman commented 7 months ago

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:

https://github.com/quarkusio/quarkus/issues/32701

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

https://github.com/quarkusio/quarkus/pull/33319

PacoVK commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

@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 commented 5 months ago

@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 commented 5 months ago

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

cedricbraekevelt commented 4 months ago

@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 commented 4 months ago

Hey @cedricbraekevelt i think you need to follow https://github.com/PacoVK/tapir/issues/379#issuecomment-2049375967 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 commented 4 months ago

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 commented 4 months ago

@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 commented 4 months ago

@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 commented 4 months ago

@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 commented 4 months ago

@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 commented 4 months ago

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

cedricbraekevelt commented 4 months ago

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 commented 4 months ago

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 commented 4 months ago

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 commented 4 months ago

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 commented 4 months ago

Hi @PacoVK , @TomBeckett,

Today I've been able to find out some more: Improve logging with: QUARKUS_LOG_CATEGORYIO_QUARKUS_OIDCLEVEL = 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:

Hope this helps you further :-)

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

TomBeckett commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

@all-contributors please add @GrzegorzHejman for bug

allcontributors[bot] commented 3 months ago

@PacoVK

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

PacoVK commented 3 months ago

@all-contributors please add @cedricbraekevelt for bug

allcontributors[bot] commented 3 months ago

@PacoVK

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