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

Supporting several providers

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

Not every customer keeps photos with the photo service, and several have asked to sign in to the printer with their mail account instead. The printer adds a second button, Continue with your mail account. You happen to have both: your photo account, and the mailbox at the mail service that receives [email protected].

Adding a second provider

The mail service is an OpenID Provider with its own issuer, https://accounts.mail.example. The printing company registers the printer there as a separate client. The mail service issues its own client ID, the random-looking c2d7a915-4e8b-4f03-a6d2-7b19e5f80c4d, and its own client secret, and the printer gives this provider a return address of its own. Once discovery has filled in the rest, the printer's configuration holds two independent entries:

Photo service
  Issuer:             https://auth.photos.example
  Client ID:          photo-printer
  Return address:     https://printer.example/signin/callback
  Sends iss:          yes, and its metadata says so
  ID token algorithm: RS256

Mail service
  Issuer:             https://accounts.mail.example
  Client ID:          c2d7a915-4e8b-4f03-a6d2-7b19e5f80c4d
  Return address:     https://printer.example/signin/mail/callback
  Sends iss:          no
  ID token algorithm: RS256

Each entry has its own configuration document, fetched from its own issuer and checked against it, its own cached key set, and its own client secret. When an ID token arrives, the printer validates it entirely with the entry for the provider the attempt was started with. The issuer must be that provider's issuer, the key must come from that provider's key set, and the audience must contain the client ID that provider issued. An ID token from the mail service names c2d7a915-4e8b-4f03-a6d2-7b19e5f80c4d in aud, not photo-printer, because each provider knows the printer only by its own client ID.

The shortcut to avoid is merging the entries. A single combined list of trusted keys, for example, would let a key from the mail service's set verify a token that claims to come from the photo service. Key identifiers do not prevent that: each provider chooses its own, and two providers can easily publish keys with the same kid. The printer trusts the mail service to speak for mail service accounts and the photo service to speak for photo service accounts, and a merged configuration would let either speak for the other.

Keeping providers apart

A sign-in now begins with a choice, and the pending attempt records it. When you select Continue with your mail account, the printer's pending sign-in names https://accounts.mail.example as the expected issuer and https://printer.example/signin/mail/callback as the return address, along with the attempt's own state, nonce, and PKCE verifier.

With two providers, the printer is exposed to the attack that Authorization server mix-up followed through a compromised Pixel Vault, and current guidance requires a defense from the moment a client works with a second server.

In a sign-in, the stakes are higher than they were for a photo connection. Suppose the mail service were compromised. When you choose it, it sends your browser straight on to the photo service, using the printer's photo service client ID and return address, your attempt's state, and the nonce and PKCE challenge from a sign-in the attacker started in their own browser. You approve at the photo service, which you trust, and its genuine code returns to the printer. A printer that believed the mail service had answered would send that code to the mail service's token endpoint. The attacker could then inject it into their own waiting attempt, where the nonce and verifier match, and the printer would sign the attacker in as you.

The ID token cannot catch this, even though it names its issuer. In the code flow, the ID token arrives in the token response, after the printer has already chosen a token endpoint and sent the code there. The check has to happen at the callback, before the code goes anywhere, and the printer makes it in the way each provider supports:

  • The photo service sends iss on every authorization response and says so in its metadata. The printer compares the value exactly with the attempt's expected issuer, and rejects a response for a photo service attempt that arrives without it.
  • The mail service does not send iss. For its attempts, the printer relies on the separate return address: a response for a mail service attempt must arrive at https://printer.example/signin/mail/callback, and a response that arrives anywhere else ends the attempt.

In the attack above, the photo service's response arrived at the photo service's return address, carrying the photo service's issuer, for an attempt that expected the mail service. Either check stops it before any token request. Separate return addresses are the weaker of the two, because an attacker who can register a client of their own at an honest provider, using the address the printer gave another provider, can get around them. Current guidance therefore prefers iss wherever a provider offers it. Older integrations that receive an ID token directly in the callback can check that token's iss at the same point, as Understanding implicit and hybrid integrations will show, and Advanced OAuth's Authorization response issuer identification group covers the rules for iss in detail.

Put together, the printer's callback works in a fixed order:

  1. Find the pending attempt by state, and confirm that it belongs to this browser's session.
  2. Confirm that the response arrived at the attempt's return address, and that iss matches the expected issuer when that provider sends it.
  3. Exchange the code at the token endpoint from that provider's configuration, with the credential that provider issued.
  4. Validate the ID token with that provider's issuer, key set, and client ID, and with the attempt's nonce.

The same subject in two places

Suppose you sign in once with each button. After validation, the claims that identify you look like this, with the others left out:

Signed in with the photo service:
{
  "iss": "https://auth.photos.example",
  "sub": "user-2048",
  "aud": "photo-printer"
}

Signed in with the mail service:
{
  "iss": "https://accounts.mail.example",
  "sub": "a94f1c07e2",
  "aud": "c2d7a915-4e8b-4f03-a6d2-7b19e5f80c4d"
}

One person has two subjects, and nothing in either token says they belong together. Each provider chose its identifier for you independently, and neither knows about the other.

The reverse can happen too. A subject is unique only within its issuer. Nothing stops the mail service from giving the identifier user-2048 to someone else entirely, and that person's ID token would be just as valid as yours. If the printer looked customers up by sub alone, that stranger would arrive in your printer account. So the printer records each sign-in link as the pair of issuer and subject:

IssuerSubjectPrinter account
https://auth.photos.exampleuser-2048Your account
https://accounts.mail.examplea94f1c07e2Not linked yet

Whether your mail sign-in should open the same printer account as your photo sign-in is a question the subjects cannot answer. The obvious clue is an email address, since both providers can report [email protected]. Linking accounts explains why a matching address is not enough on its own, and Connecting a sign-in to an account shows how the printer stores the pair.

The subject tells the printer which account, at which provider, has signed in. Everything else the printer learns about you, such as your name, your email address, and whether the provider has checked that address, arrives as claims, and that is where the next lesson begins.

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 2You select Continue with your mail account. A response with that attempt's state arrives at https://printer.example/signin/callback, the photo service's return address, with iss naming the photo service. What should the printer do?

QUESTION 2 OF 2The mail service sends a valid ID token whose sub is user-2048, the same value as your photo account's subject. What should the printer conclude?

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