OAuth 2.0 and OpenID Connect (in plain English)

16 views
Skip to first unread message

Alan Karp

unread,
Mar 26, 2020, 8:39:21 PM3/26/20
to cap-...@googlegroups.com
If you've heard about these things but didn't want to spend the time to learn them, this video is a good intro to the basic concepts.  After watching, you might even be able  to form an opinion on whether or not an OAuth bearer token is a capability.

--------------
Alan Karp

Rob Markovic

unread,
Mar 27, 2020, 5:16:32 AM3/27/20
to cap-...@googlegroups.com
Apparently so.

Oauth should have been called OAuthz to avoid confusion. Moot now with the OID modification.

++ Rob


--
You received this message because you are subscribed to the Google Groups "cap-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cap-talk+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cap-talk/CANpA1Z3sg22Q%3DjfDZ7AeD__G4QLPNnJu7zoQ2tCgkgzYQGEH_g%40mail.gmail.com.

Baldur Jóhannsson

unread,
Mar 27, 2020, 11:33:38 PM3/27/20
to cap-talk
Damn this video cleared up a lot of confusion for me
regarding OAuth 2.0 (authorization) and reminded me on OpenID Connect.

Now, I am trying to recall if there was something
like OpenID message/post/comment signing.

That is an „OAuth scope“ and a „resource endpoint“ of message signing.
It would work by the web page or app sending the hash of the message to that endpoint
and getting back a json webtoken (jwt) that said
the OpenID Connect authenticated user "signed" that message. That jwt would be cryptographically signed
by the OpenID service in question. The signing request would have a direct hyperlink to the comment/message/post in it. This enables the user to see
what the hell they signed with that OpenID account
around the web. Not as strong as OpenPGP but stronger
than just a nick.

Regarding „OAuth scopes“: There seems to be the
assumption in the "allow" screen that granting of
access is all or nothing of the requested scopes.

Nor seems there be any obvious way for the authorization service to tell the „client“ in the
callback "here is the url endpoint of the contact list the user wants you to access" in the yelp example used in the video. The user could have been
asked at the "allow" screen which of her contact lists she wants that app access to. Could probably
specified in the access token returned though with
the „client“ none the wiser.
Basically I am saying there is lack of designation in
the authorization.

Then there is the lack of further delegation and
authority attenuation.
But I hold forth that functionality could be built on top. At least the attenuation part.
Possibly by an "unholy" combo of jwt and macaroons.
(a jwt caveat inside the macaroon)

Wash your hands thoroughly!
-Baldur


Alan Karp

unread,
Mar 28, 2020, 12:14:09 AM3/28/20
to cap-...@googlegroups.com
Comments inline.

--------------
Alan Karp


On Fri, Mar 27, 2020 at 8:33 PM Baldur Jóhannsson <zaru...@gmail.com> wrote:
Damn this video cleared up a lot of confusion for me
regarding OAuth 2.0 (authorization) and reminded me on OpenID Connect.

Now, I am trying to recall if there was something
like OpenID message/post/comment signing.

 I haven't heard of anything. 

Regarding „OAuth scopes“: There seems to be the
assumption in the "allow" screen that granting of
access is all or nothing of the requested scopes.

That's because clients are only supposed to ask for the scopes they actually need, and supposedly more people will say no if they ask for a lot.  Ha, Ha. There was also a discussion of a "step-up" flow where you could ask for more permissions later, but I don't think anything came of it 

Nor seems there be any obvious way for the authorization service to tell the „client“ in the
callback "here is the url endpoint of the contact list the user wants you to access" in the yelp example used in the video.

The client hits the resource URL, gets redirected to the authorization server, gets the grant followed by the token.  It then goes back to the original URL.  The client has to remember that URL.  The token would have been an ocap if they had put the URL in the token.
 
The user could have been
asked at the "allow" screen which of her contact lists she wants that app access to. Could probably
specified in the access token returned though with
the „client“ none the wiser.
Basically I am saying there is lack of designation in
the authorization.

 Lots of features were discussed, but it was decided to keep things really simple for the user.

Then there is the lack of further delegation and
authority attenuation.
 But I hold forth that functionality could be built on top. At least the attenuation part.
Possibly by an "unholy" combo of jwt and macaroons.
(a jwt caveat inside the macaroon)

That's the token exchange in RFC 8693.  It didn't exist when the video was made.

Wash your hands thoroughly!

And keep your distance!
 
-Baldur



--
You received this message because you are subscribed to the Google Groups "cap-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cap-talk+u...@googlegroups.com.

Neil Madden

unread,
Mar 28, 2020, 4:44:55 AM3/28/20
to cap-...@googlegroups.com

Comments inline too. 
On 28 Mar 2020, at 04:14, Alan Karp <alan...@gmail.com> wrote:


Comments inline.

--------------
Alan Karp


On Fri, Mar 27, 2020 at 8:33 PM Baldur Jóhannsson <zaru...@gmail.com> wrote:
Damn this video cleared up a lot of confusion for me
regarding OAuth 2.0 (authorization) and reminded me on OpenID Connect.

Now, I am trying to recall if there was something
like OpenID message/post/comment signing.

 I haven't heard of anything. 

Regarding „OAuth scopes“: There seems to be the
assumption in the "allow" screen that granting of
access is all or nothing of the requested scopes.

That's because clients are only supposed to ask for the scopes they actually need, and supposedly more people will say no if they ask for a lot.  Ha, Ha. There was also a discussion of a "step-up" flow where you could ask for more permissions later, but I don't think anything came of it 


It’s still active. I’m skeptical that it will be much used - developers tend to be resistant to anything that requires repeatedly sending the user to a consent screen. 

I also think its a bit of an anti-pattern. You can do this right now by just asking for a new access token with different scopes and then using different tokens for different operations. The incremental authz draft instead accumulates ever more authority into a single token. 


Nor seems there be any obvious way for the authorization service to tell the „client“ in the
callback "here is the url endpoint of the contact list the user wants you to access" in the yelp example used in the video.

The client hits the resource URL, gets redirected to the authorization server, gets the grant followed by the token.  It then goes back to the original URL.  The client has to remember that URL.  The token would have been an ocap if they had put the URL in the token.

Sort of. OAuth tokens tend to be usable for a wide range of URLs.

 
The user could have been
asked at the "allow" screen which of her contact lists she wants that app access to. Could probably
specified in the access token returned though with
the „client“ none the wiser.
Basically I am saying there is lack of designation in
the authorization.

 Lots of features were discussed, but it was decided to keep things really simple for the user.

There are proposals to adapt OAuth to allow fine-grained “transactional” authorization:


Both seem to keep the general model that the client knows what it wants to access and can describe it in detail up-front, rather than letting the user choose what the client should have access to. 

I really like the Dropbox Chooser and Saver APIs as an example of advantages of capabilities over OAuth (https://www.dropbox.com/developers/chooser). Dropbox have a comprehensive OAuth implementation but these APIs are much simpler and more secure for not using it. 


Then there is the lack of further delegation and
authority attenuation.
 But I hold forth that functionality could be built on top. At least the attenuation part.
Possibly by an "unholy" combo of jwt and macaroons.
(a jwt caveat inside the macaroon)

That's the token exchange in RFC 8693.  It didn't exist when the video was made.

Token exchange is ok, but again I’ve heard a lot of pushback against it in practice. People don’t like adding a bunch of extra network calls to exchange tokens because it adds too much latency and potential for failures. IMO it is only worth it when crossing organisational boundaries (eg handing off a patient from one healthcare provider to another is a big use-case I believe). 

The next version of my employer’s (ForgeRock) OAuth2 authorization server software supports issuing access tokens as macaroons partly for this reason. You can add caveats to reduce the scope, expiry, audience, etc. This is nice for adding contextual caveats before API calls, and it also nicely solves some issues in microservices. 

We opted to use a (unholy?) JSON syntax for (first-party) caveats based on JWT claims (many of which are already restrictions rather than claims), eg to reduce the expiry time you’d add a caveat of the form:

{ “exp”: 123456789 }

When you inspect the access token using the authorization server’s introspection endpoint it returns the most restrictive combination of the original token and any caveats attached to it:

- the scope is the intersection of the original token scope and any scope caveats
- the audience is the intersection too
- the expiry time in the minimum of the original expiry time and any caveats
Etc

Because this is done transparently through the existing standard token introspection, you can introduce macaroons really easily into an existing OAuth deployment. 

We’re also looking at incorporating some of the transactional auth stuff via 3rd-party caveats: a client has an initial access token that provides permission to initiate a transaction. This token has a third-party caveat attached to it pointing at a separate transaction authorization service which issues short-lived discharge macaroons to authorize individual transactions. This has some nice security properties and you can build the entire thing yourself in a few hours (on top of macaroons) rather than waiting for yet another OAuth RFC to be published. 

— Neil

Alan Karp

unread,
Mar 28, 2020, 1:05:30 PM3/28/20
to cap-...@googlegroups.com
Neil Madden <neil....@forgerock.com> wrote:

The next version of my employer’s (ForgeRock) OAuth2 authorization server software

It's good to have someone who really knows this stuff on cap-talk, rather than just a dilettante like me.

 When you inspect the access token using the authorization server’s introspection endpoint it returns the most restrictive combination of the original token and any caveats attached to it:

- the scope is the intersection of the original token scope and any scope caveats
- the audience is the intersection too

I think having multi-audience tokens is a mistake unless audience members are listed in the token.  Without that, you don't know who to tell that the token has been revoked.  Also, you don't know if you're sending the token to a valid end point, so you need further complications, such as client secret.  Is there a good reason to do multi-audience the way OAuth does it?


- the expiry time in the minimum of the original expiry time and any caveats
Etc

A question we wrestled with when doing the Zebra Copy work was whether or not to reject if any of the delegations was invalid even if the aggregate was OK.  We opted for the former.  It sounds like you decided on the latter.

Do you support revocation, or do you rely on expiration time only?  If you support revocation, who can revoke?  Zebra Copy allowed anyone on the delegation chain to revoke any subsequent delegation, but it might be better had we allowed revoking only the direct delegation.

--------------
Alan Karp

Neil Madden

unread,
Mar 28, 2020, 2:13:07 PM3/28/20
to cap-...@googlegroups.com

On 28 Mar 2020, at 17:05, Alan Karp <alan...@gmail.com> wrote:


Neil Madden <neil....@forgerock.com> wrote:

The next version of my employer’s (ForgeRock) OAuth2 authorization server software

It's good to have someone who really knows this stuff on cap-talk, rather than just a dilettante like me.

 When you inspect the access token using the authorization server’s introspection endpoint it returns the most restrictive combination of the original token and any caveats attached to it:

- the scope is the intersection of the original token scope and any scope caveats
- the audience is the intersection too

I think having multi-audience tokens is a mistake unless audience members are listed in the token.  Without that, you don't know who to tell that the token has been revoked.  Also, you don't know if you're sending the token to a valid end point, so you need further complications, such as client secret.  Is there a good reason to do multi-audience the way OAuth does it?

I don’t think so, but people do it anyway. I think there is a strong preference to avoid prompting users for consent multiple times (leading to “consent fatigue”), so developers try to get do-everything access tokens in one go that can be used for multiple APIs.

Ideally OAuth would support issuing multiple access tokens at once (with a URL saying where each can be used, perhaps combining the two...). Macaroons let you get one uber-token and then derive more specific tokens from it on-demand, which hopefully will guide developers back to a least-authority approach. 


- the expiry time in the minimum of the original expiry time and any caveats
Etc

A question we wrestled with when doing the Zebra Copy work was whether or not to reject if any of the delegations was invalid even if the aggregate was OK.  We opted for the former.  It sounds like you decided on the latter.

Yes. We do make an exception in one case: you can bind an access token to a TLS client certificate, and we only allow this to happen once. If you try to bind it to a different certificate then the token becomes invalid. 

(You could also say that we simply enforce both certificate bindings, which is impossible to satisfy in TLS as you can only authenticate with one certificate at a time). 


Do you support revocation, or do you rely on expiration time only?  If you support revocation, who can revoke?  Zebra Copy allowed anyone on the delegation chain to revoke any subsequent delegation, but it might be better had we allowed revoking only the direct delegation.

We support revocation in a few ways:
Firstly, users can go into their profile and revoke all access to a particular client (app/developer). This revokes all existing tokens issued to that client by that user. 
We also support RFC 7009 token revocation, which allows the client to revoke their own tokens. (They limited it to just the client apparently to rule out malicious revocation, but to my mind revoking a token you have somehow got hold off is the most responsible thing you could do with it). 
We also have a separate endpoint where an admin can revoke any token. 

In terms of how the revocation is implemented, we support a couple of models:
The token can be an opaque random string, in which case the resource server (RS) has to call our introspection endpoint to find out the token scope, owner etc. If the token is revoked this returns an error. Typically an RS will cache this introspection response for a short time, so the token won’t be revoked until the next time it checks. (Our own RS implementation can also receive instant revocation notifications by subscribing over a WebSocket channel but this is non-standard). 

Or the token can be a self-contained token like a JWT. In this case the RS typically has no way to know when it is revoked. We would recommend people use short-lived access tokens in this case and issue the client with a longer-lived refresh token to get a new access token: refresh stops working when the token is revoked. 

(There’s also something known as the “phantom token pattern” where a gateway receives an opaque access token from an external client, performs introspection to check it is valid, and then issues its own short-lived JWT version to be consumed by microservices behind the gateway. This is similar to caching the introspection response.)

Neil

Tristan Slominski

unread,
Mar 28, 2020, 2:56:12 PM3/28/20
to cap-...@googlegroups.com
I don’t think so, but people do it anyway. I think there is a strong preference to avoid prompting users for consent multiple times (leading to “consent fatigue”), so developers try to get do-everything access tokens in one go that can be used for multiple APIs.

Are there studies, papers, data sets documenting the consent fatigue phenomenon? I have at least one data point where it is a lobbying term https://www.beuc.eu/blog/tag/consent-fatigue/: "...In the European lobby city, Brussels, foes of strong e-Privacy rules have spread the term “consent fatigue”..."

--
You received this message because you are subscribed to the Google Groups "cap-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cap-talk+u...@googlegroups.com.

Alan Karp

unread,
Mar 28, 2020, 8:37:43 PM3/28/20
to cap-...@googlegroups.com
Neil Madden <neil....@forgerock.com> wrote:

Is there a good reason to do multi-audience the way OAuth does it?
I don’t think so, but people do it anyway. I think there is a strong preference to avoid prompting users for consent multiple times (leading to “consent fatigue”), so developers try to get do-everything access tokens in one go that can be used for multiple APIs.

Which is, of course, a POLA violation.  I would rather see a do-everything grant that can be turned into finer grained tokens.  I guess the token exchange RFC can serve the same purpose, but people might not use it.

Macaroons let you get one uber-token and then derive more specific tokens from it on-demand, which hopefully will guide developers back to a least-authority approach. 

If you can get developers to do that.  Since it's extra work on their part, I wonder if it will be as widely applied as it should be.

Why did you decide to accept even if an individual delegation in the chain was invalid?  We considered an invalid delegation to be a bug, which meant we couldn't know the delegator's intent.

We support revocation in a few ways:
Firstly, users can go into their profile and revoke all access to a particular client (app/developer). This revokes all existing tokens issued to that client by that user. 

Does that assume a client ID, or do you just tie it to the redirect URI?  I'm not a fan of the client ID/secret approach, because it requires a prior relationship between the client and RS.  Also, before token exchange, there was no way to re-delegate without sharing your client secret.


We also support RFC 7009 token revocation, which allows the client to revoke their own tokens. (They limited it to just the client apparently to rule out malicious revocation, but to my mind revoking a token you have somehow got hold off is the most responsible thing you could do with it). 

Stiegler and I went back and forth on this one for SCoopFS.  We ended up allowing anyone holding a capability to revoke it, because it was almost always what users wanted.  There was a potential denial of service, since anyone could revoke the whole delegation chain.  I think the right answer is to make the ability to revoke one of the scopes.   

Or the token can be a self-contained token like a JWT. In this case the RS typically has no way to know when it is revoked. We would recommend people use short-lived access tokens in this case and issue the client with a longer-lived refresh token to get a new access token: refresh stops working when the token is revoked. 

Since Zebra Copy did not have multi-audience tokens, we could just send the revocation request directly to the RS, which only needed to remember the GUID for each revoked certificate until it expired.

-------------
Alan Karp

Neil Madden

unread,
Mar 29, 2020, 4:27:26 AM3/29/20
to cap-...@googlegroups.com

On 29 Mar 2020, at 00:37, Alan Karp <alan...@gmail.com> wrote:


Neil Madden <neil....@forgerock.com> wrote:

Is there a good reason to do multi-audience the way OAuth does it?
I don’t think so, but people do it anyway. I think there is a strong preference to avoid prompting users for consent multiple times (leading to “consent fatigue”), so developers try to get do-everything access tokens in one go that can be used for multiple APIs.

Which is, of course, a POLA violation.  I would rather see a do-everything grant that can be turned into finer grained tokens.  I guess the token exchange RFC can serve the same purpose, but people might not use it.

Yes, and you can also do this already using refresh tokens: obtain a do-everything grant once then use the refresh token to obtain multiple access tokens with different subsets of the overall scope. I’ve heard this pattern discussed several times but never heard of anyone actually using it. 


Macaroons let you get one uber-token and then derive more specific tokens from it on-demand, which hopefully will guide developers back to a least-authority approach. 

If you can get developers to do that.  Since it's extra work on their part, I wonder if it will be as widely applied as it should be.

It’s true that it might not catch on. We’ve had positive responses when we’ve pitched it to customers, so I am hopeful for now. 


Why did you decide to accept even if an individual delegation in the chain was invalid?  We considered an invalid delegation to be a bug, which meant we couldn't know the delegator's intent.

The reason was to simplify some expected patterns of use. For example, suppose you have an AS that issues access tokens to internal apps used within your corporate firewall. You later decide to let some clients use these access tokens from outside the company network, but want to limit them to a maximum 1 hour expiry time. So you set up a proxy that those clients must go through. The proxy simply adds a caveat to all access tokens limiting the expiry to 1 hour in the future. 

In our current implementation this proxy can always blindly add the caveat. If adding an invalid caveat would cause the token to become invalid then the proxy would first have to check the token and any caveats on it to make sure it didn’t already have an expiry time less than 1 hour. 


We support revocation in a few ways:
Firstly, users can go into their profile and revoke all access to a particular client (app/developer). This revokes all existing tokens issued to that client by that user. 

Does that assume a client ID, or do you just tie it to the redirect URI?  I'm not a fan of the client ID/secret approach, because it requires a prior relationship between the client and RS.  Also, before token exchange, there was no way to re-delegate without sharing your client secret.

Yes, it requires a client ID. The client needs to have a relationship with the AS, not necessarily with the RS. 


We also support RFC 7009 token revocation, which allows the client to revoke their own tokens. (They limited it to just the client apparently to rule out malicious revocation, but to my mind revoking a token you have somehow got hold off is the most responsible thing you could do with it). 

Stiegler and I went back and forth on this one for SCoopFS.  We ended up allowing anyone holding a capability to revoke it, because it was almost always what users wanted.  There was a potential denial of service, since anyone could revoke the whole delegation chain.  I think the right answer is to make the ability to revoke one of the scopes.   

That’s an interesting possibility. 

One of the reasons I’d like RFC 7009 to allow revocation by anyone is to support the kind of thing GitHub currently does. They scan public git repos looking for things that look like access tokens, and if they find one they proactively revoke it and send the repository owner an email. This seems like a general good thing to do, but would be forbidden by 7009 as GitHub isn’t the client. So GH can only do this for their own access tokens and a few partner orgs I believe. 

(This would be easier to do if access tokens were capability URLs so you could discover the RS)


Or the token can be a self-contained token like a JWT. In this case the RS typically has no way to know when it is revoked. We would recommend people use short-lived access tokens in this case and issue the client with a longer-lived refresh token to get a new access token: refresh stops working when the token is revoked. 

Since Zebra Copy did not have multi-audience tokens, we could just send the revocation request directly to the RS, which only needed to remember the GUID for each revoked certificate until it expired.

Right. We did something similar for the BBC who (apparently) have upwards of 100 million tokens in circulation with an expiry time of 2 years. We use a replicated bloom filter as a quick first check on validity to try and cope with the volume of revoked tokens. This mostly works but is a bit of a Heath Robinson/Rube Goldberg contraption. 

— Neil

Jonathan S. Shapiro

unread,
Apr 11, 2021, 10:58:59 PM4/11/21
to cap-talk
Following up belatedly...

Alan wrote:


That's because clients are only supposed to ask for the scopes they actually need, and supposedly more people will say no if they ask for a lot.  Ha, Ha.

Well, yes, that's the theory. But having now implemented both an RP and a federated OpenID IDP/OP, I'd say that in practice the only scopes people ask for in 99% of applications are "openid profile email", which is about the minimum you can usefully get away with. Sometimes offline_access, but that's more rare. Authority creep isn't happening much in practice.

The bigger problem, from a practical standpoint, is that OIDC utterly relies on the browser redirect method, and is consequently a real PITA for desktop applications to use.

Jonathan S. Shapiro

unread,
Apr 11, 2021, 11:21:07 PM4/11/21
to cap-talk
This thread has sort of died down, but I've run across an issue with OIDC that I wanted to share.

Context: we're building a service where most customers are business entities. We'd like to support SSO for these clients, and it turns out that many already have an OIDC or SAML authentication service of some sort even if they don't realize it. If you are using Google Workspace (formerly GSuite) or you are signed up on Azure AD (including any of the onmicrosott.com domains), you already have an IdP/OP. And it would be really nice to be able to facilitate onboarding by having a way to automatically locate your provider. User sh...@buttonsmith.com shows up, and we'd like to know where to authenticate buttonsmith.com identities. For OIDC, there isn't a practical way, which is surprising in a system where SSO is touted as a feature.

The OpenID foundation currently recommends that "consuming" companies implement a protocol called WebFinger (RFC7033). The overwhelming majority of entities who use OpenID in a corporate context are tiny businesses who haven't the ability to stand that up. An awesome number of them run their primary domain off of Shopify or BigCommerce or some such hosted service, which means they really don't have the option to stand up a WebFinger server.

But...

There is something called OpenID Connect Discovery. Under OIDC Discovery, an OP/IdP publishes everything one needs to access the IdP/OP is published as a JSON document at http://host/.well-known/openid-configuration. Or rather, any path ending in that, though in practice everybody uses /.well-known on their sites. Since the endpoint resource names can be anything, this lets you find them with minimal hassle.

The small change here would be to let the web server for any domain publish this document, with the intended meaning that "if you are trying to authenticate a user in our domain, here's the information on the IdP/OP to use." The replying party works its way up the domain tree looking for the endpoint config. If I give my email as sh...@mumlble.buttonsmith.com, then mumble.buttonsmith.com is tried first and then buttonsmith.com is tried. To avoid update problems when the IdP/OP changes its endpoints, the version published at buttonsmith.com could simply be a redirect.

All of the major commerce sites can support this. Knowing who the IdP/OP is doesn't absolve the resource provider of needing to decide if they will trust it, but that's a much easier problem.

I find myself wondering how something so obvious and simple was neglected in favor of something so impractical (WebFinger).

Hardly the end of the world, but frustrating.

Jonathan

Alan Karp

unread,
Apr 12, 2021, 1:00:28 AM4/12/21
to cap-...@googlegroups.com
On Sun, Apr 11, 2021 at 7:59 PM Jonathan S. Shapiro <jonathan....@gmail.com> wrote:

The bigger problem, from a practical standpoint, is that OIDC utterly relies on the browser redirect method, and is consequently a real PITA for desktop applications to use.

The OAuth people recognize that problem as well as some others, e.g., client secret, and are working on a replacement called Grant Negotiation and Authorization Protocol (GNAP).  They have agreed that authorizations are capabilities.    

--------------
Alan Karp

Alan Karp

unread,
Apr 12, 2021, 1:05:55 AM4/12/21
to cap-...@googlegroups.com
I don't know the answer, but the people who do will be at IIW Tuesday through Thursday next week.

--------------
Alan Karp


--
You received this message because you are subscribed to the Google Groups "cap-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cap-talk+u...@googlegroups.com.

Neil Madden

unread,
Apr 12, 2021, 3:22:22 AM4/12/21
to cap-...@googlegroups.com
On 12 Apr 2021, at 04:21, Jonathan S. Shapiro <jonathan....@gmail.com> wrote:


This thread has sort of died down, but I've run across an issue with OIDC that I wanted to share.

Context: we're building a service where most customers are business entities. We'd like to support SSO for these clients, and it turns out that many already have an OIDC or SAML authentication service of some sort even if they don't realize it. If you are using Google Workspace (formerly GSuite) or you are signed up on Azure AD (including any of the onmicrosott.com domains), you already have an IdP/OP. And it would be really nice to be able to facilitate onboarding by having a way to automatically locate your provider. User sh...@buttonsmith.com shows up, and we'd like to know where to authenticate buttonsmith.com identities. For OIDC, there isn't a practical way, which is surprising in a system where SSO is touted as a feature.

The OpenID foundation currently recommends that "consuming" companies implement a protocol called WebFinger (RFC7033). The overwhelming majority of entities who use OpenID in a corporate context are tiny businesses who haven't the ability to stand that up. An awesome number of them run their primary domain off of Shopify or BigCommerce or some such hosted service, which means they really don't have the option to stand up a WebFinger server.

WebFinger is also account enumeration as a service. If you know someone’s email address you can often easily determine if they have an account somewhere using WebFinger. 


But...

There is something called OpenID Connect Discovery. Under OIDC Discovery, an OP/IdP publishes everything one needs to access the IdP/OP is published as a JSON document at http://host/.well-known/openid-configuration. Or rather, any path ending in that, though in practice everybody uses /.well-known on their sites. Since the endpoint resource names can be anything, this lets you find them with minimal hassle.

Well RFC 5785 explicitly only allow /.well-known at the top-level of the path (see https://tools.ietf.org/html/rfc5785#appendix-B). This was enforced when OIDC discovery was re-published by the IETF as RFC 8414 - in OIDC you simply concatenate /.well-known/... onto the end of an existing URI. In the OAuth RFC version it has to replace the path component. 


The small change here would be to let the web server for any domain publish this document, with the intended meaning that "if you are trying to authenticate a user in our domain, here's the information on the IdP/OP to use." The replying party works its way up the domain tree looking for the endpoint config. If I give my email as sh...@mumlble.buttonsmith.com, then mumble.buttonsmith.com is tried first and then buttonsmith.com is tried. To avoid update problems when the IdP/OP changes its endpoints, the version published at buttonsmith.com could simply be a redirect.

But how does the RP know when to stop going up the hierarchy? Presumably it shouldn’t look under .com or .co.uk? If the user’s site is at foobar.github.io should it also look under github.io? That crosses a security boundary because github.io is in the Public Suffix List (https://publicsuffix.org/). I may not want GitHub to handle logins for my own site. So does the RP need to consult the PSL? 


All of the major commerce sites can support this. Knowing who the IdP/OP is doesn't absolve the resource provider of needing to decide if they will trust it, but that's a much easier problem.

I find myself wondering how something so obvious and simple was neglected in favor of something so impractical (WebFinger).

Hardly the end of the world, but frustrating.

— Neil

ForgeRock values your Privacy

Jonathan S. Shapiro

unread,
Apr 12, 2021, 4:14:00 PM4/12/21
to cap-talk
On Mon, Apr 12, 2021 at 12:22 AM Neil Madden <neil....@forgerock.com> wrote:
WebFinger is also account enumeration as a service. If you know someone’s email address you can often easily determine if they have an account somewhere using WebFinger.

This reduces matters to a previously unsolved problem: determining which server's WebServer to contact when presented with a given domain name.

WebFinger definitely serves a role, but it is FAR too complicated for the majority of domain owners to implement. The solution needs to start from the assumption that the DNS records are handled one place, the website is hosted somewhere and is managed through a "friendly to naive users" sort of interface, and the person in charge of the domain doesn't understand much, if anything about the underpinnings of the internet.

Proceeding from these requirements, how does one reliably locate the WebFinger server associated with an arbitrary domain, say: buttonsmith.com?

Well RFC 5785 explicitly only allow /.well-known at the top-level of the path (see https://tools.ietf.org/html/rfc5785#appendix-B). This was enforced when OIDC discovery was re-published by the IETF as RFC 8414 - in OIDC you simply concatenate /.well-known/... onto the end of an existing URI. In the OAuth RFC version it has to replace the path component. 

That's actually a big help. Subsequent to my earlier email, I realized there is a conflict of meaning between "this is the set of endpoints I implement" (i.e. I am the IdP/OP), and "this is the set of endpoints to consult for my domain". So my slight revision is that .well-known/openid-provider can redirect to the provider's .well-known/openid-config.
  
But how does the RP know when to stop going up the hierarchy? Presumably it shouldn’t look under .com or .co.uk? If the user’s site is at foobar.github.io should it also look under github.io? That crosses a security boundary because github.io is in the Public Suffix List (https://publicsuffix.org/). I may not want GitHub to handle logins for my own site. So does the RP need to consult the PSL?

If you think about it, it's actually a non-issue. if x.y.z is under y.z, then y.z is already in complete control of the x.y.z domain, because they are in a position to re-point the DNS records entirely. In more practical terms, TLDs should not be checked. The RP stops at the first "enclosing" domain that publishes a .well-known/openid-provider JSON configuration. So, for example, "mumble.onmicrosoft.com" is almost certainly going to be served by an OP/IdP described at the onmicrosoft.com level of the hierarchy.

This does not guarantee that the OP/IdP will agree to perform authentication. Actually, that's never a guarantee, because the user may not exist. Rather, it is an assertion by the domain owner that the specified OP/IdP entries are viewed as authoritative by the domain holder.

If I'm being honest, I'd be happier handling this by adding a DNS CNAME record openid-provider.ENCLOSING-DOMAIN, because the set of people who can mess with DNS is generally much smaller than the set of people who can mess with the web site. Unfortunately there are two problems with this:
  • It sort of goes against the grain of the anointed uses of DNS, and
  • It's beyond the skills of many of the small- to mid-sized domain owners. This friction is one of the reasons that people rarely add independently obtained domains to (say) their Azure AD accounts.
In our case, for example, making it a domain issue adds Shopify and our entire marketing team to the set of trusted (or at least hackable) parties, while keeping it a DNS issue would keep it all inside Google. I think both mechanisms have valid use cases, though I think the DNS approach should be preferred if a palatable way can be found to do it. Is there some existing record type that would be more suitable for this and wouldn't consume a host name in the DNS space?


Jonathan
Reply all
Reply to author
Forward
0 new messages