Open agilezebra opened 6 years ago
Microsoft does weird things. AD FS does it differently than Azure AD for example. And Azure AD v1 API is different than v2 API. And all of them are mostly OAuth2 APIs that were hacked to do some OIDC too. ADFS is the best of the bunch...
The multi-tenant logic in Azure AD is broken in various ways. It works halfway ok for a single tenant, but Microsoft added a few extra quirks here and there to do multi-tenancy that simply don't fit with the OIDC model.
I'm not aware of a readymade solution to talk with Azure AD via pyoidc, but maybe @rohe knows something about it.
I am actually using pyoidc to work with Azure AD (v2), ADFS 2016, Keycloak and a few others, so it works in general for my small usecase, but needs some handholding like the one you made there. My local one did similar things in different ways.
I found i needed the following, if memory serves me right:
And so on.
Of course Microsoft are doing the wrong thing (as usual) but sadly they are largest provider of SSO in the corporate world. Given that I have to support Azure AD in order to service my clients, that means the Python OIDC library I use has to handle all their quirks.
@rohe What can be done to get the above logic into pyodic natively to homogenise Microsoft’s various representations of the same tenant id so that pyodic works with Azure?
22 aug. 2018 kl. 11:28 skrev agilezebra notifications@github.com:
Of course Microsoft are doing the wrong thing (as usual) but sadly they are largest provider of SSO in the corporate world. Given that I have to support Azure AD in order to service my clients, that means the Python OIDC library I use has to handle all their quirks.
@rohe What can be done to get the above logic into pyodic natively to homogenise Microsoft’s various representations of the same tenant id so that pyodic works with Azure?
Well, there is no short answer to that.
These last 6 month I’ve been working on a new OIDC RP library implementation. Sponsored by Google but now owned by the OpenID Foundation (OIDF). (There are 2 more libraries comming out from that project one in Java and one in JavaScript.)
Using it I only needed configuration to make it work aganist Azure AD in the single tenant case. That was using an UUID as identifier for the tenant.
As Microsoft is a founding member of the OIDF one would hope that they would be interested in getting OIDF's libraries to work with their services. But I’ve been in this game for a while so I wouldn’t bet on it :-(
But basically, I or someone else with knowledge of the library and access to instances of the service we want pyoidc/JWTConnect-Python to work with needs to have time allocated.
Michael listed a number of things that had to have special handling. He wasn’t sure it was exhaustive so the first thing we have to find out is what, if anything, he missed.
I might time to work on this but I’d love to have someone more knowledgeable on the MS side to help me out.
-- Roland "Education is the path from cocky ignorance to miserable uncertainty.” - Mark Twain
I see that this issue is closed but I presume that this library still isn’t truly compatible with Microsoft as an OpenID provider. Given that, I’m not really sure I understand the rational for closing the bug. I note comments from @rohe above about how he is able to make it work against Azure in a single tenant case. This unfortunately is not much help unless you are building an internal application for a given company. If you are providing a product to the general public (and by public, in my case, I mean some universe of typical business users) these users will not come from a single tenant id; they will come from all different companies and therefore different tenant ids. They will have no idea what a tenant id is and they just want to be able to sign in with their Microsoft account.
We continue to use this library as it is pretty much the only game in town for Python 3. However, it only works with Microsoft (who are, for better or worse, the latest provider of corporate accounts) if we monkey patch it as above. That’s a very precarious position to be in, given that any refactoring to the pyoidc library will break our software unless we pin the version.
Is there any way we can get the logic above to handle the equivalence of the 3 representations of tenant ids into the library proper? I’d prefer to not to contribute a fix myself as I really don’t understand the library well enough to ensure I don't break anything for others.
The rationale for closing the bug was simple - it was labelled as usage question and I was doing a cleanup of issues based on that.
Looking at the patch you have included earlier, this doesn't look like a very good idea to have in the library for following reasons:
1) It is very Microsoft specific, it wouldn't (and shouldn't) be used for anything else 1) It is bypassing security verifications in OpenID Connect protocol 1) It will be prone to be broken if something in the Microsoft implementation changes
So unless @schlenk and @rohe have different opinion I am for not implementing this.
Firstly, I wasn’t suggesting that the patch be used as as-is; rather, that it demonstrates that treating Microsoft’s 3 different representations of their tenant id as equivalent makes it work as needed.
It is very Microsoft specific, it wouldn't (and shouldn't) be used for anything else
It needn't be used for anything else except making pyoidc work with Microsoft. Whilst I appreciate the desire to keep the library free of cruft that is there only to deal with Microsoft's weirdness, if the pyoidc library doesn’t work fully with Microsoft’s implementation of OICD, it’s utility is severely limited. It’s no use saying “they are doing the wrong thing, they should change”; they won’t (we all know that) and we need a Python OIDC library that works with all the popular identity providers and this one currently doesn’t work with the provider that is most popular, in the most common usage scenario (i.e. not limited to a single tenant).
It is bypassing security verifications in OpenID Connect protocol
I can’t speak to that, but flags to disable strict checking of this or that are common and that's all it needs for those that need to use multi-tenancy. Indeed, there is already an issuer_mismatch flag present in the configuration.
It will be prone to be broken if something in the Microsoft implementation changes
Perhaps not, but it doesn’t work with Microsoft properly now so there isn’t much to lose.
I know that you weren't suggesting the patch as it is, but the different workarounds present in the patch show that the change might be quite complicated and it can possibly break other things. It will probably be quite complicated to test that properly.
I will wait for other opinion before we decide what to do with this issue.
For what it’s worth, and said with the best of intentions, we switched from pyoidc to authlib. It works perfectly out-of-the-box with all the main identity providers, like Azure. Working with real-world providers is more important to our business (and I suspect most applications) than sticking rigidly to the spec.
Would it be possible to define some compact interface that would allow implementing Microsoft (or any other non-conformant implementation) specific fixes in some external package?
We are attempting to use pyoidc with Microsoft as an OIDC provider, using various tenant ids as described in https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oidc . Has pyoidc been testing with Microsoft? It appears that the implementation as it stands isn't compatible with Microsoft's "interpretation" of the standard. In particular it looks as though MS mix and match whether they use the string
{tenant}
, an alias such ascommon
or a raw UUID such as2e4146d4-a7f8-45b2-9dd1-bbd74093bee5
, as well as mixing the domain ofsts.windows.net
andlogin.microsoftonline.com
for their issuer strings in various responses. The effect of this is that the pyoidc library is unable to find the correct keyjar when the keys are returned.Here is the config we are using:
We get this output:
We are however able to make pyoidc work if we do some horrendous monkey-patching using the module shown below, which we simply import before using pyoidc. This is obviously not ideal and far from future-proof.