Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

From delegated access to sign-in

All domains, identifiers, and tokens in these examples are fictional.

The printing application has a problem that has nothing to do with photos. Every new customer has to create a printer account before ordering a book: choose an email address, invent a password, confirm the address. Plenty of people give up halfway. Most of them already have a photo account, and many have just connected it to the printer.

A new button

The printing company would like to add a button to its sign-in page: Continue with your photo account. You would select it, prove who you are to the photo service the way you always do, and arrive back at the printer signed in. There would be no new password for you to remember, and none for the printer to store.

This is a different request from the one the OAuth lessons followed. There, from The problem OAuth solves onward, the printer wanted access: permission to read your photos. Now it wants to know who you are. More precisely, it wants a trustworthy answer to one question. Has the person in this browser just authenticated at the photo service, and if so, as which photo account?

The printer already knows how to send your browser to the photo service and get something back. It is tempting to reuse that exchange exactly as it is.

Why an access token is not a sign-in

Here is the shortcut. The printer runs the authorization code flow, receives an access token, and calls an endpoint on the photo API that describes the account behind the token:

GET /me HTTP/1.1
Host: api.photos.example
Authorization: Bearer demo-access-token-12

HTTP/1.1 200 OK
Content-Type: application/json

{ "id": "user-2048", "name": "Robin Park" }

The printer then signs in whoever owns user-2048. It works in a demonstration, and it answers the wrong question.

An access token tells the photo API that some client may read some photos. It was written for the API, and the printer only carries it. Nothing in the token, or in the API's answer, tells the printer that this token was issued to the printer, for this sign-in attempt, a moment ago.

That gap matters as soon as a token can reach the printer from somewhere other than its own token request. Suppose the printer's phone app runs the flow itself and sends the access token it receives to the printer's backend, which signs in the account behind it. Now suppose you once connected a collage app to your photo account. The collage app holds a valid access token for your photos. Its operator, or anyone who copies that token, can send it to the printer's backend in place of a token from the printer's own app. The backend calls /me, receives user-2048, and signs that person in as you. The token is genuine. It was simply never meant for the printer. This is the access token injection that The implicit grant described, arriving by a different route.

The collage app holds a valid access token for your photos that the photo service issued to the collage app. Someone with that token sends it to the printer's backend as if it came from the printer's own phone app. The backend calls the photo API's /me endpoint with it, receives user-2048, and signs the sender in as you. Nothing in the token or the API's answer shows that it was issued to a different app. The collage app holds a valid access token for your photos that the photo service issued to the collage app. Someone with that token sends it to the printer's backend as if it came from the printer's own phone app. The backend calls the photo API's /me endpoint with it, receives user-2048, and signs the sender in as you. Nothing in the token or the API's answer shows that it was issued to a different app.
The photo API correctly accepts a token issued to another app. The printer cannot tell from the API's answer that the token was never meant for its sign-in.

Time is a second problem. An access token can be issued long after you last authenticated. In The refresh token grant, the printer obtained new access tokens every December without you being present. A token like that shows that an authorization still exists, not that anyone has signed in recently.

The third problem is practical. Every service that offered a /me endpoint designed its own, with its own field names and its own idea of what an identifier was. A printer that wanted to support several services had to learn each one, and it still could not tell from any of them when or how you had authenticated.

Many early "sign in with" integrations were built this way. Their problems are the reason a separate standard exists.

What OpenID Connect adds

OpenID Connect, often shortened to OIDC, adds an identity layer to OAuth 2.0. It keeps the authorization code flow you already know, with the same endpoints, state, PKCE, and code exchange, and adds a small number of things on top.

The printer asks for sign-in by including the scope value openid in its request. When the exchange succeeds, the token response contains an ID token alongside the access token. An ID token is a signed statement from the photo service, addressed to the printer by its client ID, saying which account authenticated, when, and in answer to which request.

Each of those details closes one of the gaps above. Because the token is addressed to the printer, a token issued to the collage app would name the collage app, and the printer would refuse it. Because it carries a value the printer chose for this attempt, a token from an earlier sign-in does not fit a new one. Because it records when you authenticated, the printer can tell a sign-in from this morning apart from one last spring.

OIDC also standardizes the surroundings: names for common profile information such as a name and email address, called claims; a UserInfo endpoint where a client can ask for them; a discovery document that tells a client where to find a provider's endpoints and keys; and ways to coordinate signing out. A printer that understands these can work with any provider that follows the specification, rather than learning a new /me endpoint each time.

The access token keeps its job. If the printer also wants to read your photos, it can ask for both in the same request, and it will receive an ID token for signing you in and an access token for the photo API. Signing in alone does not give the printer your photos.

Before following a sign-in message by message, it helps to name the participants the way OpenID Connect does, because their responsibilities have shifted slightly from the OAuth roles you know.

Try it in the Lab

PUT IT INTO PRACTICE

Check your understanding

Try these questions before moving on. If an answer isn't right, use the feedback and try again.

0 of 2 answered correctly

Enable JavaScript to answer these questions and save progress in this browser.

QUESTION 1 OF 2The printer's backend receives an access token from a phone app, calls the photo API's /me endpoint, and gets user-2048. Why is signing in user-2048 unsafe?

QUESTION 2 OF 2What does adding openid to the scope of the printer's request change?

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

Learn identity