Closed MaikuMori closed 4 years ago
@MaikuMori Thank you for your query. We will investigate and update the thread.
The workaround that I found and documented here: https://github.com/coreos/go-oidc/issues/212#issuecomment-528805306 only works for the personal Microsoft account sign-in.
I still believe that the metadata server is not working according to OIDC spec and should never return issuer with value: https://login.microsoftonline.com/{tenantid}/v2.0
. It even looks like a bug.
Obviously changing the output is a breaking change. What if there was a UUID alias like the one for consumers
tenant, but instead for common
? Then we could use that as metadata endpoint and that endpoints could respond with correct issuer just like the https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0 does.
@MaikuMori Thank you for sharing your findings . We will engage with the content authors to get more clarity on this.
@rwike77 Could you please take a look at this issue and provide your thoughts on this ?
Thank you for looking into this!
I've also seen this issue prevent several OIDC compliant services from integrating with Microsoft. For example Amazon Cognito refuses to integrate because it correctly notices the iss
in the JWT token does not match the .../{tenantid}/v2.0
. issuer in Azure's .well-known endpoint and other auth services fail for the same reason.
This quirk makes Azure non-compliant with the OpenID Connect specification.
@hpsin , can you comment on this? Thanks.
Yes, this is unfortunately an inherent issue with the /common alias. By using /common, the app is indicating that they expect a user in any tenant (issuer) to be able to sign into the app. We reflect the ultimately chosen tenant in the issuer claim. This is especially important when there are tenant specific signing keys, where the app must know which jwks URI to visit in order to get the key used to sign the token.
@codeitcody - can you provide some other services that this has blocked? It would be helpful to understand who's using /common like this and encountering these issues.
Unfortunately there's no way at this time to make /common OIDC compliant - only our tenanted URLs (of which /consumers is one, as it's just an alias to the singleton MSA tenant) can be OIDC compliant. We can consider breaking tenant-specific signing keys (it's proprietary) and force those apps to build the jwks URI from scratch (s/common/$claims.tid/), or allow apps to opt-in to a /common issuer so that in the future they get expected values. I don't love the idea of making standards compliance opt-in though. We'll discuss internally on what's the least-bad way to address this, if possible.
I followed up with engineering, unfortunately it's not possible to make /common OIDC compliant right now. Closing this doc issue, feel free to reopen if necessary. #please-close
Is there any chance of this being fixed?
I happened upon this bug when I wanted to set up Microsoft SSO with Gitea. I can only allow auth to the consumers tenant thanks to this bug.
Unfortunately not, we have to rev the entire platform (v3) to change the issuer.
Is that in the roadmap?
What about having both V2
and V3
up? That way old code can still function and newer code can use the standards compliant version.
Not on the roadmap currently. We absolutely would have both supported concurrently (as well as v1) but making a radical change to the existing architecture is out of scope right now given our current workload.
Ok. I suppose it's not the end of the world - my Gitea instance is just for people to file issues against my own projects, so I don't need AAD support.
Thanks for the details, though!
How are we supposed to have use OIDC in multi-tenant apps with customers that use Azure as their identity provider?
issuer did not match the issuer returned by provider, expected "https://login.microsoftonline.com/common/v2.0" got "https://login.microsoftonline.com/{tenantid}/v2.0"
Do people hard-code an exception for the fact that Microsoft can't seem to implement OIDC properly?
Yes - they validate tokens based on the issuer claim, rather than the authority. Or validate the token based on the keys (static across tenants) and signature only. The common endpoint is not OIDC compliant - only tenanted endpoints can be.
Hey @hpsin, I was hoping to get some clarification regarding one of your earlier responses:
Yes, this is unfortunately an inherent issue with the /common alias. By using /common, the app is indicating that they expect a user in any tenant (issuer) to be able to sign into the app.
Are you referring to the common authorization endpoint?
I use my tenant-specific authorize endpoint https://login.microsoftonline.com/{tenat id}/oauth2/v2.0/authorize
to get an access code and then exchange that for a token from my tenant-specific token endpoint https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/token
and yet the issuer, as specified by the "iss" claim, is still https://sts.windows.net/{tenant id}/
Additionally, my token has a claim "ver": "1.0"
which I suspect is telling me I got a V1 token from the V2 endpoint based on this doc.
I also saw some discussion here that suggested editing my Azure AD registered application's manifest to set "accessTokenAcceptedVersion": 2
which I have done, but this does not seem to have any effect. I'm not msal.js (the subject of the linked issue) but the conversation here is relevant.
I've also found some info mentioning that the V2 endpoint may return a V1 token based on the scopes requested. I'm requesting scopes based on my registered app resource uri i.e. api://preprod.api.mycompany.com/.default
- is this V1 only?
Is this behaving as you'd expect? This causes problems for every api we have that is performing token validation as implemented by default in asp .net core jwt bearer middleware. Without some configuration to override the valid issuers, validation fails. We can work around this but ideally, we'd be working within the spec and getting the issuer value from the metadata doc and not having to manage separate configuration for this sts.windows.net issuer.
Additionally, we're linking federated external identities to B2C users. For external identities authenticating with Azure AD, the ideal solution for us would be to register a federated identity using the issuer and unique id from the identity provider, Azure AD in this case. However, the issuer does not match the issuer defined in the token when these external users log in so we will need some workaround here as well.
I've been doing a lot of experimenting and research and I'd really appreciate any info you can provide that might clarify the conditions that result in the V2 endpoint returning a V1 token.
Thanks
Are you referring to the common authorization endpoint? Yep - login.microsoftonline.com/common/oauth2/v2.0/*
The issuer for v1 tokens is indeed sts.window.net
.
Scopes and APIs are defined in a app registration - so e.g. your api://preprod.api.mycompany.com/
corresponds to some application registration. That app is the only app that should ever validate a token for the api://preprod.api.mycompany.com/
scopes.
The API entirely and completely owns the formatting of their tokens. It doesn't matter what a client application does, or how a token is requested - the format of that token will always be the same - it'll be what the API says it should be. This ensures that APIs can reliably validate their tokens, rather than worrying about how the token was requested.
api://preprod.api.mycompany.com/
needs to set the accessTokenAcceptedVersion to 2. Doing that on a client will do nothing.
For every single authentication, we do:
api://preprod.api.mycompany.com/
)This code runs on both the v1 and v2 endpoint, and makes no considerations about the client app when determining the shape of the token.
api://preprod.api.mycompany.com/ needs to set the accessTokenAcceptedVersion to 2. Doing that on a client will do nothing.
This made me realize where I went wrong. I had configured accessTokenAcceptedVersion
on the client application, not the api application which I've gotta admit makes perfect sense and I should have known better :man_facepalming:
This solved my problem! Thanks a million and thanks for the quick response @hpsin!
@ClairelyClaire mentioned that
AzureAD .well-known config is partially invalid, making OAuth2 registration with the "common" or "organizations" endpoints impossible go-gitea/gitea#12073
I also noticed the issue on organisations ( not common) endpoints,
getting errors like
oidc: issuer did not match the issuer returned by provider, expected "https://your-tenant-name.b2clogin.com/tfp/c5b28ff6-f360-405b-85d0-8a87b5783d3b/B2C_1A_signin/v2.0/" got "https://your-tenant-name.b2clogin.com/c5b28ff6-f360-405b-85d0-8a87b5783d3b/v2.0/“
The actual one has no policy name in the url.
Is any plans to make organisation endpoints oidc compliant?
In a possible v3, as mentioned above. We cannot break our existing apps.
Use of B2C here is out of scope - I believe B2C requires you to use the special B2C issuer and endpoints, no?
@hpsin what about another keyword like common-compliant, or something that allows the issuer to be what it is suppose to be. I would also argue a major version bump is allowed to break apps, but that is another discussion.
Good call - we usually think about this in terms of clients getting access tokens, and resources validating those access tokens, with no control over how the access token was requested (e.g. they're often requested from v1, even if you're running a v2 resource).
However, we could indeed fix this with an ID token issuer optional claim, or a new issuer for metadata.
Would you prefer to leave code as-is, and set an optional claim in the app config, or use a new issuer (common-compliant, e.g.) ?
@hpsin this is a good question, I would think a new issuer would have the most flexibility in the case that an app maybe uses multiple oidc libraries, web vs phone etc. Thank you for even considering this!
That makes sense - it's a run-time decision tightly coupled to the code, not the app registration. I'll get some other folks to give some input. Thank you for the idea and helping tease out the distinctions here.
I came across this issue adding OAuth2 to my application. What I'd like to do is allow any email of any organization to use my application by signing into Azure. All I really need is the authorized email account, then my application creates its own bearer token that is used throughout as only identity verification is required. I am okay if personal accounts are not used. I am using authlib
in Python and using the /common
endpoint appears to completely fail for any account, tenented or not. It's completely unusable with authlib
and it appears there's no non-hacky way of solving this at all short of forgoing issuer validation.
I can't use the tenented enpoint because I want ANY organization to be able to authenticate with ease.
Am I totally out of luck? Can I really only support my own organization authenticating? What do I have to do? Any pointers are appreciated.
Edit: I can use the /consumers
endpoint and properly support personal accounts, but is there really no way to support any teneted account? It seems a little crazy.
Is there already a fix for this so we can use commonv2 or something else
I need it to support work and personal accounts for Amazon cognito
This issue is affecting all services which require an OIDC compliant upstream service, including the largest Auth OSS ecosystem in the world: https://github.com/ory
We'd be happy to assist when v3 comes out, Ory Hydra is an excellent OIDC compliant authz server ;)
I'm running into this issue trying to test Azure AD as an openid provider for our software.
Using the endpoint https://login.microsoftonline.com/<my_tenant_id>/v2.0
obtained from the endpoints list on the web dashboard, all id tokens have an incorrect issuer claim of "iss": "https://sts.windows.net/<my_tenant_id>/"
.
I also tried the endpoint https://login.microsoftonline.com/organizations/v2.0
(also from the endpoints list, after switching the account types option), but this one has the {tenantid}
placeholder in its openid-configuration issuer url, so that won't work either.
Setting "accessTokenAcceptedVersion": 2
in my app's manifest didn't seem to change anything. Unsure how to proceed here.
@kralicky
I'm running into this issue trying to test Azure AD as an openid provider for our software. Using the endpoint
https://login.microsoftonline.com/<my_tenant_id>/v2.0
obtained from the endpoints list on the web dashboard, all id tokens have an incorrect issuer claim of"iss": "https://sts.windows.net/<my_tenant_id>/"
. I also tried the endpointhttps://login.microsoftonline.com/organizations/v2.0
(also from the endpoints list, after switching the account types option), but this one has the{tenantid}
placeholder in its openid-configuration issuer url, so that won't work either.Setting
"accessTokenAcceptedVersion": 2
in my app's manifest didn't seem to change anything. Unsure how to proceed here.
Hi, did you ever get to the bottom of this? My ID tokens have the correct tenanted issuer but the access tokens do not. Thanks
@jonathandavis5 Yep... unfortunately not much you can do here. Azure is simply not OIDC compliant. :-1:
It's been 4 years, is this seriously not resolved?
Firebase authentication is also refusing to work without a strict OpenID Connect implementation.
For now the only way around this issue is using custom policies, as documented here: https://docs.gitlab.com/ee/administration/auth/oidc.html#configure-microsoft-azure-active-directory-b2c
Can't wait for this issue to be fixed.
It's been 5 years now, is this seriously still not solved?
The discovery URL given for
common
endpoints is:But the metadata document itself returns:
The base part of these two should match according to the spec. This breaks OIDC Connect libraries which are rigid about the spec.
For example: https://github.com/coreos/go-oidc
See also https://github.com/coreos/go-oidc/issues/159 https://github.com/coreos/go-oidc/issues/212
If this is not the correct place where to file and issue let me know where I can do that.
Document Details
⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.