Mapping out my understanding of (web-based) single sign-on systems

December 7, 2023

Suppose, not entirely hypothetically, that you want to use some systems (perhaps external systems) that wants you to have a 'single sign on' (SSO) system that it can use to authenticate you and your users. There are a number of good reasons for both sides to want this; you get better control and the outside system gets to outsource all of the hassles of managing authentication to you. To create this SSO setup, there are a number of pieces, and here is how I currently understand them.

The thing you want to end up with is an Identity Provider (IdP). Typical IdPs have two roles; they challenge users to authenticate (generally through a web browser) and perhaps approve giving this authentication information to other systems, and they provide authenticated identity information to other systems. They typically do their single sign on trick by putting a cookie in the browser to mark you as already authenticated, so when a system sends you to the IdP to get authenticated you just bounce right through without getting challenged. A garden variety IdP does all of this with HTTP(S) transactions, some of them from people's web browsers and some of them from systems to API endpoints (or from the IdP to other people's API endpoints).

An IdP needs to speak some protocol to systems that are getting authentication information from it. Two common protocols are SAML and OIDC (OpenID Connect) (also). Different IdP implementations speak different protocols; for example, SimpleSAMLphp primarily speaks SAML (as you might expect from the name), although now I look it can apparently also speak OIDC through an OIDC module. By contrast, Dex is purely an OIDC and OAuth2 IdP, while Keycloak will support all of SAML, OIDC, and OAuth2.

Naturally people have built bridges that do protocol translation between SAML and OIDC, so that if you have a SAML IdP already, you can provide OIDC to people (and perhaps vice versa). You can also 'bridge' between the same protocol, so (for example) Dex can use another OIDC IdP for authentication. I believe one reason to do this in general is to filter and winnow down the upstream IdP's list of users. Dex's documentation suggests another reason is to reformat the answers that the upstream OIDC IdP returns to something more useful to the systems using your IdP, and I'm sure there are other reasons.

(One obvious one is that if your IdP is basically an OIDC proxy for you, you don't have to register all of the systems and applications using your IdP with the upstream IdP. You register your IdP and then everything hides behind it. Your upstream IdP may or may not consider this a feature.)

An OIDC or SAML IdP needs to find out what users you have (and perhaps what administrative groups they're part of), and also authenticate them somehow. Often one or both can be outsourced to what Dex calls connectors. A popular source of both user information and user authentication is a LDAP server, which you may already have sitting around for other reasons. An IdP can also supplement outsourced authentication with additional authentication; for example, it might do password authentication against LDAP or Active Directory and then have an additional per-user MFA challenge that it manages in some database of its own.

(Some IdPs can manage users and their authentication entirely internally, but then you have to maintain, update, and protect their user and authentication database. If you already have an existing source of this, you might as well use it.)

OIDC also has a discovery protocol that is intended to let you find the OIDC IdP URLs for any particular user on any particular domain, so that a user can tell some system that they're 'me@example.org' and the system can find the right OIDC IdP from there. This discovery protocol is part of WebFinger, which means that to really run an OIDC IdP, you need something to answer WebFinger requests and provide the necessary data from RFC 7033. WebFinger isn't specific to OIDC (it's used on the Fediverse, for example) and some of the data people may want you to provide for them is user specific, like their avatar.

(I believe that OIDC IdPs usually or always require clients to be registered and assigned a client secret, so this discoverability has some limits to what you can use it for.)

PS: It's possible to set up a very janky testing OIDC IdP, but there are ways that are almost as easy and somewhat more industrial and workable.

(I'm trying to understand this whole area for work reasons.)

Written on 07 December 2023.
« Understanding another piece of per-cgroup memory usage accounting
A possible path to reliable name constraints on internal TLS CAs »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Thu Dec 7 23:03:16 2023
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.