Skip to content
KEDBYTE
How Identity Works
Chapter
43

Single Sign-On and Federation

Part IV · Identity Between Systems|13,340 words|about 58 min read|Volume 4

43.0 What this chapter gives you#

  1. You will be able to say exactly where single sign-on ends and federation begins, and name the boundary that separates them.
  2. You will be able to use the words identity provider, service provider and relying party correctly and consistently, and translate each of them between SAML, OpenID Connect and everyday speech.
  3. You will be able to describe how two organizations that have never met establish trust, including the one step in the process that is not technical at all and cannot be automated away.
  4. You will be able to design a home realm discovery mechanism, name the five common ways of doing it, and say which piece of the input an attacker controls.
  5. You will be able to explain the account linking problem, say why matching on an email address is a security decision and not a convenience decision, and give the correct matching key.
  6. You will be able to describe just-in-time provisioning, state precisely what it does not do, and calculate the orphan account population it leaves behind.
  7. You will be able to draw the identity provider mix-up attack step by step, say why neither state nor PKCE prevents it, and specify the fix from RFC 9207 field by field.
  8. You will be able to audit a multi-tenant application for the tenant-to-identity-provider binding flaws, and name at least three published incidents in that class with dates.
  9. You will be able to explain the difference between a mesh federation and a hub, do the arithmetic that motivates both, and describe what eduGAIN and its policy documents actually require of a member.
  10. You will be able to write a design that degrades sensibly when the identity provider is unreachable, with real outage durations from published incidents to size it against.

There is a moment in every large organization’s life when somebody says “we should just use single sign-on for that”. It sounds like a purchasing decision. It is not. What is actually being proposed is that one organization will start believing another organization’s statements about who a human being is, and will let those statements open doors, move money, read patient records and approve payments. The protocol that carries the statement is the easy part. The hard part is the sentence underneath it: on what basis, exactly, do we believe you, and what happens when you are wrong.

This chapter is about that sentence. Its thesis is that federation is one organization agreeing to believe another about who you are, and that the agreement is contractual before it is technical. Every federation that works at scale — the university federations, the government schemes, the enterprise arrangements behind the sign-in button on your work laptop — is a written agreement with a cryptographic mechanism attached, in that order. Every federation disaster of the last fifteen years happened where the mechanism was in place and the agreement was vague, absent, or misunderstood by one side.

We will keep two examples running the whole way through. The first is a company: Meridian Analytics, two thousand four hundred staff, with its own sign-in service at login.meridian.example, whose people need to use a hosted project tool called Cadence at cadence.example that Meridian does not own and cannot see inside. The second is a researcher, Dr Meera Iyer, at a university in one country trying to open a paper held by a library service in another country, where the two organizations have no contract with each other at all and are connected only by the federations they each belong to. Those two cases bracket the whole subject. Everything between them is detail.

The chapter before this one covered SAML, the XML protocol that carries a great deal of corporate login, and the chapter after this one covers directories, which in most large organizations are still where the truth about people lives. This chapter sits between them and is about the agreement, not the message format and not the database.

The plain version#

The card in your pocket is not the agreement#

Imagine you have a driving licence issued in your own country. You fly somewhere else, walk up to a car hire desk, and the person behind the counter looks at your licence, types your details in, and hands you a key.

Stop and think about what just happened. The person at the desk cannot verify your licence. They have never seen your country’s licensing office. They cannot telephone it, and if they did, nobody there would answer questions from a stranger about a customer. They have no way of checking the little photograph, no access to the register it came from, and no ability to detect a well-made forgery. And yet they hand over a car worth more money than they earn in a year.

They can do this because of something that happened long before you arrived, in a room you were not in. Governments sat down and wrote agreements with each other about whose licences they would honour, what a licence must contain, how long it stays good, and what happens when one is suspended. There is a real one signed at Geneva on 19 September 1949, and a later one signed at Vienna on 8 November 1968, and an earlier one agreed at Paris in 1926. Those documents are why the plastic card in your pocket means anything at the desk. The card is the easy part. The card is just a way of carrying a claim that has already been agreed to be believable.

That is the whole idea of this chapter, and it is worth saying in one sentence before anything else: the trust comes first, in writing, between organizations; the card, the message, the sign-in button are only the delivery mechanism for a decision that was made elsewhere.

Notice a few more things about the driving licence, because every one of them comes back later.

The desk does not check with your country in real time. It reads the card and decides. If your country cancelled your licence yesterday, the desk will very likely never know. The agreement had to decide in advance how long a stale card can be believed.

The agreement is between countries, not between you and the desk. You never signed anything, and neither did the clerk. Two organizations agreed, and you are both living inside their agreement without having read it.

The agreement is limited, and it covers failure. It says what the card is good for: a licence lets you drive a car, not fly a plane. And real treaties say what happens when a document turns out to be false, who is told, and who bears the loss. That last part is boring, nobody reads it, and it is the part that matters most on the worst day.

One building, one badge — and then the world outside#

Now bring it back to computers, still in plain words.

Inside one company there is usually one place that knows the staff. It knows their names, their start dates, which team they are in, and their passwords or their security keys. When you sit down at your desk and prove who you are once, and then all morning you open the email system, the holiday booking system and the expenses system without proving anything again, that is one organization believing itself. That is the easy case. Everything involved is owned by the same people, run by the same team, and covered by the same rules. There is nobody to negotiate with, because there is only one party.

The trade calls that single sign-on: sign in once, use many things, all inside one boundary of ownership and control.

Then someone buys a project tool from a supplier. The tool runs on the supplier’s computers. The supplier has never met your staff. Your staff must not be given new passwords for it, because passwords multiply, get reused, and end up on sticky notes. So you would like your staff to sign in with the company account they already have — and now you are exactly at the car hire desk, with an organization you do not own being asked to believe a claim made by an organization it does not own.

The trade calls that federation: one organization agreeing to believe another about who somebody is.

The difference between the two is not the technology. Very often it is literally the same software, the same messages and the same buttons. The difference is the boundary. On one side of the boundary, there is one authority, and if something is wrong you fix it yourself. On the other side, there are two authorities, and if something is wrong you have to ask somebody who does not work for you and might not answer.

The three parts, named once and used for the rest of the chapter#

Three parties are involved every time, and confusion between them causes more trouble than any protocol bug, so we will fix the names now and never wobble.

The first is the thing that knows who you are and is willing to say so. It holds your account, it checked your password or your fingerprint or your security key, and it writes the statement. Everyone calls this the identity provider. For Meridian Analytics, the identity provider lives at login.meridian.example.

The second is the thing you are trying to use: the project tool, the library, the expense system, the payroll site. It receives the statement, decides whether to believe it, and then decides what you are allowed to do. Historically it was called the service provider, and the newer specifications call it the relying party, meaning the party that relies on somebody else’s word. Both terms are in daily use and they mean the same role in this context. Cadence at cadence.example is the service provider, and it is the relying party.

The third is you, walking between them carrying the statement. You are the subject — the person the statement is about — and the browser doing the walking is called the user agent, because it acts on your behalf.

That is the cast. One writes, one reads, one carries. Every complication in the rest of this chapter is a complication about one of those three.

How the reader knows the writer’s handwriting#

If a stranger hands you a note claiming to be from your bank, you have a problem: you do not know what your bank’s handwriting looks like. Before any note can be believed, the reader must have obtained, from a trustworthy route, a sample of the writer’s handwriting and the writer’s name.

In federation this is done with a small document that each side publishes about itself. It contains a name for the organization’s system, the exact addresses that messages should be sent to, and the public half of the key it will use to sign its statements. Each side reads the other’s document and stores it. After that, a statement that does not carry the right signature is rejected without argument.

The important part is how the documents get from one side to the other. If the reader simply downloads the writer’s document from a web address that somebody typed into a form, then anyone who can control that download can install their own handwriting sample and afterwards forge anything they like. So there has to be a step that does not go through the same channel: a phone call to a person you know, a fingerprint of the key read aloud in a meeting, a document countersigned by an organization both sides already trust, or a signature over the whole collection of documents by a federation that both sides joined on paper.

That step — checking through a different route than the one carrying the data — is called out-of-band verification, and skipping it quietly turns the entire arrangement into decoration.

“Which country are you from?”#

At the car hire desk, the clerk does not have to guess which country’s rules apply. You hand over a card and the country is printed on it.

Online it is the other way round. You arrive at the project tool’s front page as an anonymous browser. The tool has no idea which organization you belong to, and it must find out before it can send you anywhere, because it needs to know which sign-in service to bounce you to. This sounds trivial and it is genuinely one of the ugliest problems in the field.

The tool can ask you to type your email address and use the part after the at-sign to look up your organization. It can show you a list of organizations and let you pick. It can remember, in a small note stored by your browser, which organization you chose last time. It can give each customer its own web address, so that arriving at one address already answers the question. Or it can be told the answer by whatever link you clicked to get there.

Every one of those methods works. Every one of them takes an answer from somebody who is not the identity provider, and often from the user, and occasionally from an attacker who put a link in front of the user. Remember that. It is the seed of a serious attack later in this chapter.

The trade calls this step home realm discovery: working out which home the visitor belongs to.

Making a file for you on the spot#

When Priya Nair from Meridian opens the project tool for the very first time, the tool has never heard of her. It has no row in its database with her name in it.

There are two ways to deal with that. The tidy way is that somebody at Meridian, in advance, told the tool about every member of staff, so a file was waiting. The quick way is that the tool reads her name, her email address and her team out of the statement she just handed over, and creates the file there and then, in the same second, without anybody being asked. That second way is called just-in-time provisioning, and it is why a new joiner at a large company can open eleven applications on their first morning and find themselves already in the right team in all of them.

It works beautifully in one direction and not at all in the other. Nothing in that arrangement ever deletes anything. When Priya leaves the company, her account at the identity provider is switched off, so she cannot get a statement any more, and everybody feels safe. But the file the project tool made for her is still sitting there, with her name on it, in the list of users the company pays for, holding whatever she uploaded, and it will sit there until a human being goes looking for it. Multiply by eleven applications and four years of staff turnover and you have the quiet mess that every large organization is carrying.

A worked morning, with real values#

Here is Priya’s first login, in plain words, with the values we will keep using.

It is Tuesday 4 August 2026. At 09:12 in the morning she clicks a link to the project tool. The tool sees a browser it does not recognize and asks the one question it must ask: who do you belong to. She types her work email, priya.nair@meridian.example. The tool looks at the part after the at-sign, finds that meridian.example is registered to the customer account it knows internally as tenant t_8841, and sees that this tenant has one sign-in service configured: login.meridian.example.

The tool sends her browser there with a request that says three things: I am Cadence, here is the exact address to send the answer back to, and here is a one-time unguessable value I have just invented so I can recognize my own request when it returns.

At login.meridian.example Priya is already signed in from earlier that morning, so nothing is asked of her. The sign-in service writes a statement: this person is 7f3a1c92, her email is priya.nair@meridian.example, she is in the group Analytics, the statement was written at 09:12:04, it is worthless after 09:17:04, it is addressed to Cadence and to nobody else, and here is my signature over all of it. The browser carries that back.

Cadence checks the signature against the key it stored when the two organizations set this up. It checks that the statement is addressed to Cadence. It checks the clock. It checks the one-time value it invented. Then it looks in its own database for a user belonging to tenant t_8841 whose identifier from login.meridian.example is 7f3a1c92, finds nothing, creates one, puts her in the Analytics team, and shows her the project board. Elapsed time, about half a second. Number of new passwords created, zero. Number of humans who approved this, zero.

That is the whole mechanism. Everything else in this chapter is about the ways each of those checks can be missing, and about the agreement between Meridian and the supplier of Cadence that made any of it reasonable.

When the home office is closed#

One last plain point, and it is the one that surprises people.

Before federation, if the project tool was working, staff could use it. Afterwards, if the sign-in service is unreachable, nobody can start using the project tool, even though the project tool itself is perfectly healthy. You have not removed a dependency. You have created a new one and pointed every application at it.

People who are already signed in usually keep working for a while, because the tool gave them a session that lasts hours. People arriving in the morning cannot get in at all. And systems that quietly ask the sign-in service for a fresh permission every hour stop being able to do their work even for users who are sitting right there with the screen open.

This is not a hypothetical. On 15 March 2021 a very large corporate identity service failed for roughly three hours because a signing key was deleted by an automated cleanup that ignored a flag telling it not to. On 25 February 2025 the same family of services lost about seventy-seven minutes to a mistaken change in the records that tell computers where to find things. The applications were fine both times. Nobody could get in.

That is the plain version. One organization believes another because they agreed to in writing; the agreement is delivered by a signed statement carried in a browser; a file gets made on arrival and never unmade; and the whole thing has one throat to choke.

Where the plain version stops being true#

The treaty is written for humans; the check is made by a machine that cannot read it#

The driving licence story has one enormous convenience in it: there is a person at the desk. A human clerk can notice that the card feels wrong, that the photograph does not look like you, that the story does not add up, and can refuse without being able to explain why. Treaties are written on the assumption that a person applies them.

In federation there is no clerk. There is a piece of code that runs in under a millisecond, and it can only apply the checks somebody wrote into it. The agreement between the two organizations may run to thirty pages and say that the identity provider will verify staff identity on hiring, will suspend accounts within four hours of a leaver notification, will use multi-factor authentication for privileged staff, and will notify the service provider of any incident within twenty-four hours. Not one word of that is visible to the code. The code sees a signature and some fields.

The honest version: the contract determines whether the trust is reasonable, and the protocol determines only whether the message is authentic. Those are different questions, and no amount of cryptography answers the first one. A perfectly signed statement from an identity provider that hands out accounts to anyone who fills in a web form is a perfectly authentic statement about nothing.

This is why the serious federations spend most of their documentation on obligations and almost none on message formats, and it is why an enterprise integration that consists of pasting a certificate into a form, with no agreement behind it, is a technical success and a governance vacuum.

“Trust” is four separate decisions wearing one word#

The plain version said the tool decides whether to believe the statement. That single verb is hiding four decisions that are genuinely independent, and real systems get some right and some wrong.

The first is authenticity: was this message really produced by the key I expect. That is cryptography and it is the one people concentrate on.

The second is authority: is this issuer entitled to make statements about this particular person. A signature from Meridian’s identity provider is authentic, but if it asserts that the subject is ceo@rival.example it is speaking about somebody it has no business speaking about. Authenticity says nothing about scope.

The third is accuracy: is what the issuer said actually true. That depends entirely on the issuer’s own processes, which live in the contract, not the message.

The fourth is freshness: is it still true now. The statement was written at 09:12:04. It is now 09:12:05 and it is probably still true. It is now 14:00 and Priya was dismissed at 11:30, and nothing in the message can tell you that.

Most federation failures are failures of the second and third decisions in systems that implemented the first one impeccably.

The identity provider does not know who you are either#

It is tempting to think of the identity provider as the place where the truth is. It is not. It is the place where an account is.

An account was created by some process — a human resources feed, an onboarding form, a self-service registration, a migration from an older system that nobody now understands. Whoever is holding the credentials for that account today will be described by the identity provider as the person the account was created for. If the account was created for the wrong person, if it was taken over, or if it is shared by a team, the identity provider will still make its statement in exactly the same confident language.

The honest version: an identity provider asserts continuity of an account, not identity of a human being. Everything downstream inherits whatever quality the original enrolment had, and no downstream system can improve on it. The assurance frameworks exist precisely because service providers wanted a way to ask “how carefully was this account created and how strongly was it authenticated” and get a machine-readable answer rather than a promise.

The email address is a label, not a key#

In the plain worked example, the tool matched Priya by an identifier, 7f3a1c92. Most real systems, at least at first, match by email address instead, because email is human-readable, is already in the database, and lets one person’s accounts be joined up neatly.

Matching by email address is a security decision disguised as a data-modelling convenience. It quietly asserts three things: that the identity provider verified the address, that the identity provider will not allow the address to be changed to someone else’s, and that no other identity provider is entitled to assert the same address. In practice, at least one of those three has been false in every large ecosystem where somebody bothered to check, and every time it was false the result was full account takeover rather than a minor bug. The technical version gives three named, dated cases.

The question “who is your provider?” is an input, and inputs can be attacker-supplied#

Home realm discovery looked like plumbing in the plain version. It is not plumbing. It is the step where the relying party decides which organization it is about to believe, and in most designs the decision is influenced by data that came from the browser.

If an attacker can steer that decision, then the relying party can be persuaded to start a login with one provider and finish it with another, or to send a secret intended for one provider to an endpoint controlled by another. That is not a theoretical worry; it is a named attack with a formal proof behind it and a standards-track fix, and it is one of the two or three most important things in this chapter.

Inside one company, “one trust domain” is a simplification too#

The plain version drew a clean line: inside the company, one authority; outside, two. Real organizations are not that tidy.

A group that has bought four companies has four staff directories, three sign-in services, and a merger project that has been running for two years. Two divisions of one legal entity may be forbidden by regulation from sharing staff data, and a subsidiary abroad may be a separate data controller under privacy law. In each case the internal arrangement is federation wearing an internal badge, with all the same problems and usually none of the same paperwork.

The honest version: the boundary that matters is not the company boundary. It is the boundary of a single administrative authority over the account store and the policy applied to it. Where two such authorities meet, you are federating, whatever the legal structure says.

The file made on arrival is not the only copy, and nothing reconciles them#

Just-in-time provisioning was described as making one file. In a real deployment the same login can create or update records in several places at once: the application’s user table, a per-customer directory inside it, a billing record counting licensed seats, an audit log, a search index, and a cache holding Priya’s group memberships for the next twelve hours.

When Priya’s group changes at Meridian, the next statement carries the new value and a well-built application updates itself. When Priya leaves, no statement is ever sent again, so nothing updates and every copy stops being touched in the “still valid” state, permanently. Deprovisioning is not the reverse of provisioning; it is a separate mechanism that has to be built on purpose, and chapter 45 is about that mechanism and the lifecycle around it.

You did not remove a dependency, you concentrated it#

The last simplification is the most comfortable one. Federation is usually sold as a resilience improvement: fewer passwords, fewer places to be breached, central control.

The control is real. The resilience is not, and it is worth being exact about the trade. Before federation, one application being unavailable affected one application. After federation, the identity provider is on the critical path of every first login to every application, and in many designs on the path of every hourly permission renewal as well. You have swapped many small independent failures for one large correlated one, and the correlated one is more likely to make the news.

That trade is usually worth taking. It is not free, and the design work it demands — session lengths, cached keys, break-glass accounts, and an honest answer to “how long can we survive without the identity provider” — is the part that gets skipped.

The technical version#

Single sign-on inside a trust domain, and where the domain ends#

A trust domain is the set of systems governed by one administrative authority over a single account store and a single policy applied to it. Inside it, authentication happens once and is re-presented; nobody negotiates, because there is nobody to negotiate with.

The mechanisms differ by era. On a Windows network the domain controller issues a ticket-granting ticket at logon and services accept tickets derived from it; that is Kerberos, and chapter 44 covers it properly along with the directory it depends on. On the web the equivalent is a session cookie held by an authentication service, so that a redirect to that service returns immediately without prompting. In a cloud tenant it is a primary refresh token or an equivalent long-lived artefact held by the operating system.

What matters is not the mechanism but what is assumed. Inside a trust domain, the identity provider and the applications share an account namespace, a policy authority, a clock discipline, an incident process and, crucially, a legal entity that can be held responsible. Federation is what you build when any one of those is no longer shared.

Property Inside one domain Across domains
Account namespace Shared Separate, mapped
Policy authority One Two, negotiated
Failure escalation Internal ticket Contract, contacts
Attribute meaning Assumed common Must be agreed
Revocation reach Immediate Delayed by design

The last row is the one to remember. Inside a domain you can disable an account and expect effects within seconds because you own everything that caches it. Across a federation, revocation travels at the speed of whatever the two sides agreed to, which in the common case is “when the current statement expires”, and that is a design decision that must be made explicitly rather than discovered during an incident.

The roles, named once and used consistently#

The same three roles appear in every protocol under different names, and mixed vocabulary is a real source of production bugs, because two engineers can agree in a meeting while meaning different things.

Role SAML name OIDC name
Asserts identity Identity provider OpenID provider
Consumes assertion Service provider Relying party
The human Subject, principal End-user
The browser User agent User agent

Three notes on usage that will save arguments. First, “relying party” is the more precise term for the consuming role, because it names the relationship rather than the software: the party that relies on somebody else’s assertion. It is the word used in OpenID Connect, in WebAuthn and in most trust framework documents, while “service provider” is the SAML word and the everyday word in enterprise procurement; here they mean the same role.

Second, an entity can hold both roles at once. A federation proxy is a service provider to the upstream identity providers and an identity provider to the downstream services, simultaneously, on the same box. That double role is what makes proxies powerful and their security analysis harder.

Third, “identity provider” is a role, not an organization. One organization may operate three of them for different populations — staff, students, external collaborators — each with its own entity identifier, keys and assurance profile. Contracts are with organizations; protocol trust is with entities; the mapping between them is many-to-many.

Establishing trust: metadata, keys, and the step that is not technical#

Two entities become able to talk when each has an authenticated copy of the other’s description. In SAML this description is a metadata document; in OpenID Connect it is the discovery document plus the key set it points to.

A minimal SAML identity provider description contains the entity identifier, the signing key, and the addresses:

<EntityDescriptor entityID="https://login.meridian.example/idp">
 <IDPSSODescriptor
  protocolSupportEnumeration=
    "urn:oasis:names:tc:SAML:2.0:protocol">
  <KeyDescriptor use="signing">
   <ds:KeyInfo><ds:X509Data><ds:X509Certificate>
     MIIDdzCCAl+gAwIBAgIEbG9naW4wDQYJKoZIhvcNAQELBQAw
     ... base64 continues, broken across lines ...
   </ds:X509Certificate></ds:X509Data></ds:KeyInfo>
  </KeyDescriptor>
  <SingleSignOnService
    Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
    Location="https://login.meridian.example/idp/sso"/>
 </IDPSSODescriptor>
</EntityDescriptor>

The OpenID Connect equivalent is fetched from the issuer’s .well-known/openid-configuration path and is a JSON document:

{
  "issuer": "https://login.meridian.example",
  "authorization_endpoint":
    "https://login.meridian.example/oauth2/authorize",
  "token_endpoint":
    "https://login.meridian.example/oauth2/token",
  "jwks_uri":
    "https://login.meridian.example/oauth2/keys",
  "authorization_response_iss_parameter_supported": true
}

Three properties of these documents decide whether the trust is real.

The first is the binding between the name and the key. The entity identifier and the issuer value are the names under which the entity will be trusted; the key is what proves a message came from it. A relying party must store the pair and check both. Accepting a signature from any key in a trusted collection, without checking that the key belongs to the entity named in the message, is one of the classic federation bugs and it is what makes several attacks in this chapter work.

The second is freshness. SAML metadata carries a validUntil attribute and optionally a cacheDuration; a document past its validUntil must be rejected. The eduGAIN SAML profile, version 0.5 of 3 April 2018, requires the aggregate’s root element to carry a validUntil no earlier than 120 hours and no later than 2304 hours — five days to twenty-eight days — after the creation instant, which bounds how stale a mirrored copy can be. OpenID Connect has no equivalent validity field on the discovery document, so freshness is governed by HTTP caching and by the key rotation behaviour of the JWKS endpoint, which chapter 41 covers.

The third, and the one that cannot be automated, is how the document arrived. If a service provider fetches metadata from a location an administrator typed into a form, over a channel with no independent verification, then whoever controls that location or that channel controls who the service provider will believe forever afterwards. The remedies are all forms of a second channel:

  1. A key fingerprint read out on a telephone call to a known contact, or exchanged in person.
  2. A metadata document signed by a key the relying party already holds, distributed independently of the document itself.
  3. A federation aggregate: one file containing every member’s metadata, signed by the federation operator, whose key both sides obtained when they joined on paper.
  4. A query service that returns one entity’s signed metadata on demand, so that a large aggregate does not have to be downloaded in full. The relevant specification, the Metadata Query Protocol by Ian Young, is still an individual Internet-Draft; as of August 2026 the current revision is draft-young-md-query-25 of 12 June 2026, and it has never been published as an RFC, though it is widely deployed in research and education federations under the name MDQ.
  5. In OpenID Federation 1.0, a signed chain of entity statements leading up to a trust anchor whose key was configured out of band, which mechanizes the paper step for everything below the anchor.

The eduGAIN SAML profile also fixes the cryptography rather than leaving it to taste: RSA keys of at least 2048 bits with at least 3072 recommended for new deployments, elliptic curve keys of at least 256 bits, digest algorithms at least as strong as SHA-256 with MD5 and SHA-1 excluded, and signature transforms limited to enveloped signatures with exclusive canonicalization. Certificate rollover mechanics are a SAML topic and chapter 42 handles them.

The contract layer, which is the actual subject of this chapter#

Everything above is machinery. The reason a service provider is willing to configure that machinery for an identity provider it has never met is a document, and it is worth looking at real ones rather than describing the idea abstractly.

Take eduGAIN, the interfederation service that connects national research and education federations. Its governing document is the eduGAIN Policy Framework Constitution. Version 1.0 was approved on 21 March 2011, version 2.0 on 19 April 2013, version 3.0 on 1 May 2017, and version 4.0 on 1 January 2024. The Policy Framework consists of that constitution, the technology profiles that supplement it, and the eduGAIN Policy Declaration, which a federation’s representative signs to join.

Read the joining process as a sequence, because it is the thesis of this chapter in five steps:

  1. A representative of the applicant federation signs the eduGAIN Policy Declaration and presents it to the eduGAIN Secretariat.
  2. The Secretariat confirms the applicant meets the membership requirements.
  3. The Secretariat prepares a membership proposal for the executive committee to review.
  4. The eduGAIN Assembly votes to approve or reject.
  5. Only then does the service team register the federation technically.

Four signatures and a vote come before the first byte of metadata is exchanged. The constitution’s requirements on a member federation are similarly non-technical: primarily serve education and research, provide a technical point of contact for members, provide processes for handling complaints and incidents involving members, meet the requirements of the Policy Declaration, and have an agreement defining membership between the federation and its members. Amending the constitution requires a two-thirds affirmative vote of federations on the voting list, and a change takes effect three months after written notice.

Inside a national federation the same pattern repeats one level down. InCommon, the United States research and education federation operated by Internet2, applies a document called Baseline Expectations for Trust in Federation. The expectations of an identity provider include that it is operated with organizational-level authority, that it is trusted enough to be used to access the organization’s own systems, that generally accepted security practices are applied to it, that it complies with the REFEDS Security Incident Response Trust Framework for Federated Identity, known as Sirtfi, that its endpoints use current transport layer encryption, that its published metadata is accurate and complete including technical, administrative and security contacts and user interface information, and that its metadata includes a current error URL. Service providers carry a parallel list, including that controls are in place to reasonably secure information and maintain user privacy and that their metadata is likewise accurate and complete with contacts and a privacy policy URL.

Two features of that list deserve attention. Almost none of it is enforceable by a protocol check. And it is enforced anyway — by a community dispute resolution process run by the Community Trust and Assurance Board. InCommon moved to the second version of Baseline Expectations from spring 2021, adopting it in December 2021; the dispute resolution process concluded in December 2022 with the removal of thirty non-compliant entities from InCommon metadata; and by January 2023 more than 98 per cent of registered entities met the requirements, with 99 per cent of identity providers and 98 per cent of service providers compliant.

Removal from metadata is the sanction, and it is the correct one, because it is the only sanction that operates at the speed of software. That is what a federation is: a contract whose enforcement mechanism is deletion from a signed file.

Figure Value As of
eduGAIN member federations 84 17 Aug 2026
Candidate federations 8 17 Aug 2026
Identity providers 6,539 17 Aug 2026
Service providers 4,040 17 Aug 2026

The eduGAIN technical site also reported 2 standalone attribute authorities and a headline total of 10,559 entities on that date; the components sum to 10,581, a difference of a few dozen that reflects an aggregate rebuilt continuously rather than an error worth chasing. The largest single contributor was InCommon with 2,495 entities. InCommon itself describes the federation as connecting over 1,000 institutions, companies and federal agencies to more than 6,000 services, as its site stated in August 2026.

Home realm discovery, five ways, and where each leaks#

Home realm discovery is the step where a relying party works out which identity provider to send an unauthenticated visitor to. There are five families of solution in production use.

Method Nature Weak point
Email domain mapping Convention Domain not proven
Explicit picker or WAYF Convention User error, phishing
Common domain cookie Standard Needs shared domain
Per-tenant URL Implementation Link can be supplied
Hint parameter Standard or vendor Attacker-supplied

Email domain mapping asks for an address and maps the part after the at-sign to a configured identity provider. It is a convention, not a standard. Its weak point is that the mapping table is populated by whoever administers the tenant, and if that person can claim a domain without proving control of it, the discovery step becomes an account takeover primitive; the multi-tenant section below is entirely about that failure.

An explicit picker, called a Where Are You From service or discovery service in research federations, shows a searchable list. There is a real specification for it: the OASIS committee specification Identity Provider Discovery Service Protocol and Profile, Committee Specification 01 of 27 March 2008. The service provider sends the user’s browser to the discovery service with parameters:

GET /ds?entityID=https%3A%2F%2Fcadence.example%2Fsp
       &return=https%3A%2F%2Fcadence.example%2Fdsreturn
       &returnIDParam=idp

entityID is required and identifies the requesting service provider. return is optional and may itself carry a query string. returnIDParam names the parameter used to hand back the chosen identity provider and defaults to entityID if omitted. policy selects processing behaviour, defaulting to the URI ending idp-discovery-protocol:single, and isPassive is a boolean controlling whether the service may interact with the user visibly. The discovery service redirects the browser back to the return address carrying the selected identity provider identifier, or carrying no parameter at all if discovery failed.

The critical implementation rule is that the return value must be validated against the service provider’s registered metadata before being used. A discovery service that redirects to any supplied return address is an open redirector inside the authentication path.

The common domain cookie is the standardized browser-memory approach, defined in the SAML 2.0 profiles specification as the Identity Provider Discovery Profile in section 4.3. The cookie name must be _saml_idp. Its value is a set of one or more base-64 encoded URI values separated by a single space, URL-encoded as a whole. The writing service appends the identity provider’s identifier to the list and may remove and re-append an identifier already present, with the intent that the most recently established session is last in the list. The cookie’s domain must be set to a leading period followed by the common domain agreed for the deployment. Its practical limitation is in the name: it needs a domain common to all participants, which a global federation of independent organizations does not have, and browser restrictions on third-party cookies have made this progressively less usable over the last decade.

Per-tenant URLs sidestep discovery by encoding the answer in the address: a customer reaches a dedicated hostname or path and the tenant, and therefore the identity provider, is known before any user input. It is the cleanest option and it is an implementation choice rather than a standard.

Hints pass the answer as a parameter. OpenID Connect defines login_hint in section 3.1.2.1 of Core 1.0 as a hint to the provider about the identifier the user might use. Vendors add their own: Google defines hd for a hosted domain, Microsoft defines domain_hint, and WS-Federation defines whr for the home realm. All of these are supplied by whoever constructed the link, which means all of them are attacker-supplied whenever a user can be persuaded to click something.

In the research and education world the discovery problem was significant enough to produce its own programme. The RA21 project, a joint initiative of STM and NISO, produced NISO RP-27-2019, “Recommended Practices for Improved Access to Institutionally-Provided Information Resources”, published on 21 June 2019, and the SeamlessAccess service that followed it provides a shared discovery experience so that Dr Iyer sees the same “find your institution” interface at every publisher rather than a different one at each.

Account linking, and the key you must match on#

When a statement arrives, the relying party has to decide which local record it refers to. This is the account linking problem, and it has exactly one safe answer and several popular unsafe ones.

The safe answer is that the identity of a federated user is the pair (issuer, subject). The issuer is the identity provider’s own name — the iss claim in an OpenID Connect ID token, the Issuer element in a SAML assertion. The subject is that provider’s opaque identifier for the account — the sub claim, or the NameID. Neither half is sufficient alone. A subject value is only unique within an issuer, so storing sub without iss means two providers can collide, deliberately or accidentally. An issuer without a subject identifies an organization, not a person.

create table federated_identity (
  tenant_id    text not null,
  issuer       text not null,
  subject      text not null,
  user_id      text not null,
  linked_at    timestamptz not null,
  link_method  text not null,   -- 'admin', 'verified', 'jit'
  primary key (tenant_id, issuer, subject)
);

Two design points are encoded in that table. The primary key is the triple, so no two federated identities can map to the same local user by accident. And link_method is recorded, because six months later, during an incident, the only question that matters is how a given link came to exist and whether a human or a proof was involved.

The popular unsafe answer is to match on the email address in the statement. It is unsafe because it silently assumes three things: that the issuer verified the address, that the issuer prevents an account holder from setting it to somebody else’s address, and that no other issuer may assert the same address. Each of those has failed in public.

The nOAuth issue, disclosed jointly by Descope and Microsoft on 20 June 2023, is the cleanest example. In Microsoft’s directory the email attribute of a user could be set to an arbitrary value, including a domain the tenant did not own, and the resulting email claim was therefore both mutable and unverified. Any multi-tenant application that used the email claim as the user’s unique identifier could be entered as any victim by an attacker who created their own tenant and set the attribute to the victim’s address. The timeline is short and worth keeping:

Date Event
11 Apr 2023 Descope reports to Microsoft
18 Apr 2023 Microsoft updates claims docs
20 Jun 2023 Joint disclosure, fixes issued

Microsoft’s response was to stop emitting an email claim by default for unverified addresses in newly registered applications and to provide an optional claim, xms_edov, indicating whether the email address is domain-verified, alongside stronger written guidance that email, upn and preferred_username must not be used for authentication or authorization decisions and that the subject claim is the identifier to use.

The second public case is about the other assumption: that a verified domain stays with the same organization. On 13 January 2025 Truffle Security published research showing that buying the domain of a defunct company allowed the buyer to recreate mailboxes for former employees and then sign in to software-as-a-service products that had keyed accounts on the Google hd (hosted domain) and email claims. The researcher estimated over 100,000 defunct startup domains available for purchase and, on an assumption of ten employees and ten services each, more than ten million potentially reachable accounts. Google had closed the original report as “won’t fix” on 2 October 2024, reopened it on 19 December 2024 after a conference talk was accepted, and paid a bounty of 1,337 US dollars.

That case also contains a live disagreement worth stating fairly, because it bears directly on the advice in this chapter. Truffle Security argued that the subject claim is not reliable in practice, reporting that it changed in about 0.04 per cent of their logins with Google, and asked for new immutable user and workspace identifiers. Google’s position is that the subject claim is the immutable identifier and that developers should use it rather than email. As of August 2026 the standards-side advice is unchanged — match on issuer and subject — and the practical advice is to monitor for subject changes rather than assume they cannot happen, and to have a supported process for re-linking when one occurs.

The third failure mode is not about the identity provider at all but about the order of events, and it was measured. In “Pre-hijacked accounts: An Empirical Study of Security Failures in User Account Creation on the Web”, presented by Avinash Sudhodanan and Andrew Paverd of the Microsoft Security Response Center at the 31st USENIX Security Symposium in August 2022, the authors define five attack classes in which the attacker acts before the victim ever creates an account. Two of them are federation-specific. In the Classic-Federated Merge attack, the attacker creates a password account using the victim’s email address, the victim later signs in through federation, the service merges the two, and both parties end up with access. In the Non-Verifying Identity Provider attack, the attacker creates an account at an identity provider that does not verify email addresses, uses it to create the account at the target service, and waits for the victim to arrive. Of 75 popular services tested, at least 35 were vulnerable to at least one class; 13 to Classic-Federated Merge, 19 to unexpired sessions surviving a password reset, 12 to trojan identifiers, 11 to unexpired email change, and 1 to the non-verifying provider attack.

The rule that falls out of all three cases is short. Link on issuer and subject. Treat an email address in a statement as a display attribute, not a key. If you must merge a federated login with an existing local account that shares an address, interrupt the flow and prove control of the address or require the existing password; never merge silently. And when a link is created, record how.

Just-in-time provisioning, and the orphans it leaves#

Just-in-time provisioning means creating or updating the local account from the contents of the statement at the moment of login. In SAML the source is the AttributeStatement; in OpenID Connect it is the claims in the ID token or from the UserInfo endpoint. A typical mapping for Cadence looks like this:

assertion attribute        ->  local field
-------------------------      -----------
NameID (persistent)        ->  subject
mail                       ->  display_email
displayName                ->  full_name
eduPersonAffiliation       ->  role_hint
memberOf / groups          ->  team membership

The attraction is obvious and real: no pre-population, no separate feed to maintain, new staff productive immediately, and attribute changes carried on every login without a synchronization job. The problem is equally simple and is usually discovered years later.

Just-in-time gives you It does not give you
Create on first login Delete on last day
Update on each login Update when absent
Group changes at login Group removal after leaving
Zero setup per user Any licence reconciliation
Attributes at that moment A record of who has access

Every row on the right is a consequence of the same fact: the mechanism is driven by the user’s presence. A user who is never coming back never triggers anything, so the account is left in the state it was in on the last successful login, which is “active”.

Put numbers on it with Meridian. These are our worked assumptions, not industry measurements: 2,400 staff, 11 applications reached by federation with just-in-time provisioning enabled, an annual staff turnover of 14 per cent, and an average leaver having actually signed in to 6 of the 11 applications.

Quantity Calculation Result
Leavers per year 2,400 x 0.14 336
Orphan records/year 336 x 6 2,016
After four years 2,016 x 4 8,064

Eight thousand active-looking accounts, on other people’s computers, belonging to people who no longer work at Meridian. None of them can be used through federation, because the identity provider will not issue a statement for a disabled account. That is the reassurance everyone offers, and it is true only for the federated path. Each of those records may still be reachable by a local password if one was ever set, by an application-specific token or API key created while the person worked there, by a personal access token in a code repository, or by an invitation link that was never expired. Each of them may also still be counted, and paid for, as a licensed seat.

The correct fix is a provisioning protocol that carries deletions as well as creations, which in practice means SCIM; chapter 45 covers the joiner-mover-leaver lifecycle and the SCIM specifications in full. The partial fixes worth knowing are short session lifetimes so that access dies quickly when statements stop arriving, back-channel logout so that the identity provider can push a session termination, and a scheduled reconciliation that lists every account in every application and compares it with the current staff list. The reconciliation is unglamorous and it is the only one of the three that finds the account nobody remembers creating.

Identity provider mix-up, precisely#

The mix-up attack is the reason this chapter exists as a separate chapter rather than a section of the OAuth one. It is an attack on the relying party’s belief about which identity provider it is talking to, which is exactly the belief federation is built on.

It was found by formal analysis. Daniel Fett, Ralf Küsters and Guido Schmitz published “A Comprehensive Formal Security Analysis of OAuth 2.0” as an arXiv preprint on 6 January 2016, with an abridged version at the ACM Conference on Computer and Communications Security in 2016. They analysed all four grant types in an expressive web model and found four previously unknown attacks, of which two matter here: the IdP mix-up attack and the 307 redirect attack. They reported them to the OAuth and OpenID Connect working groups, which confirmed them.

The paper states three preconditions for the mix-up attack: the presence of a network attacker who can manipulate the request in which the user sends her identity to the relying party and the corresponding response; a relying party that allows users to log in with identities from both an honest provider and an attacker-controlled provider; and a relying party that uses explicit user intention tracking and issues the same redirection URI to all providers.

Read the second and third conditions again, because they are not exotic. Supporting more than one provider is what federation is. Using one redirect address for all of them is what almost every library does by default. And the first condition is weaker than “network attacker” sounds: anything that influences the discovery step will do, including a link in an email.

Here it is with our values. Meridian’s honest provider is login.meridian.example. The attacker operates idp.freetrial.example, which anybody may register with Cadence because Cadence, like most products, lets a customer configure their own provider.

 1. Priya starts login at Cadence, choosing Meridian.
 2. Attacker alters the discovery answer: Cadence now
    believes the chosen provider is idp.freetrial.example.
 3. Cadence redirects the browser to the AUTHORIZATION
    endpoint the attacker declared, which is in fact
    login.meridian.example/oauth2/authorize, with the
    attacker's client_id.
 4. Priya sees the genuine Meridian login page, at the
    genuine address, and approves. Nothing looks wrong.
 5. Meridian redirects back to Cadence with a code.
 6. Cadence believes the flow belongs to
    idp.freetrial.example, so it sends the code, and its
    client secret, to the ATTACKER's token endpoint.
 7. The attacker now holds a code issued by Meridian for
    Priya, and redeems it at Meridian.

The elegance, and the horror, is at step 4: the user is at the right identity provider, looking at the right domain in the address bar, typing the right password. Nothing the user can see is wrong. The confusion is entirely inside the relying party, which has two providers in its head and has attached the response to the wrong one.

Neither of the two controls people reach for first prevents this. The state parameter is checked and matches, because the flow really was initiated by this browser for this session; state defends against a callback the client did not start, and this callback was started legitimately. Proof Key for Code Exchange does not help either, because the relying party sends the code verifier to the token endpoint it believes is correct, which is the attacker’s; the attacker receives code and verifier together and presents both to the honest provider. Storing the provider’s authorization endpoint is not enough, because a hostile provider is free to declare an honest provider’s authorization endpoint as its own while keeping its token endpoint under its control.

The fix is to make the response say who produced it, and to check it. RFC 9207, “OAuth 2.0 Authorization Server Issuer Identification”, by Karsten Meyer zu Selhausen of Hackmanit and Daniel Fett of yes.com, was published in March 2022 on the standards track. Section 2 defines the iss parameter in the authorization response: its value is the issuer identifier of the authorization server that created the response, and it must be a URL using the https scheme with no query or fragment component. An authorization server supporting the specification must include it in authorization responses, including error responses.

HTTP/1.1 302 Found
Location: https://cadence.example/callback
  ?code=SplxlOBeZQQYbYS6WxSbIA
  &state=af0ifjsldkj
  &iss=https%3A%2F%2Flogin.meridian.example

Section 2.4 states the client’s obligation: clients supporting the specification must extract the iss value from the authorization response and compare it to the issuer identifier of the authorization server the request was sent to. Section 3 defines the metadata field authorization_response_iss_parameter_supported, a boolean by which a server advertises the behaviour. Section 4 adds the rule that makes the whole thing sound: clients must validate iss precisely as described and must not allow multiple authorization servers to use the same issuer identifier.

The validation is four lines, and its correctness depends entirely on what was recorded when the request went out:

  # at request time, bound to the user agent session:
  session["expected_iss"] = chosen_issuer

  # on the callback:
  if params.get("iss") != session["expected_iss"]:
      abort(400, "issuer mismatch")

RFC 9700, “Best Current Practice for OAuth 2.0 Security”, published in January 2025 as BCP 240 by Torsten Lodderstedt, John Bradley, Andrey Labunets and Daniel Fett, folds this into general advice: clients interacting with multiple authorization servers should use the iss parameter as a countermeasure according to RFC 9207, or an alternative countermeasure based on an issuer value in the authorization response; using distinct redirection URIs per authorization server is permitted as an alternative but should only be used if other options are not available. An earlier attempt, the “OAuth 2.0 Mix-Up Mitigation” Internet-Draft by Michael Jones, John Bradley and Nat Sakimura, was never completed and expired.

Defence Stops mix-up? Source
state parameter No RFC 6749 s4.1.1
PKCE No RFC 7636
iss in response Yes RFC 9207 s2.4
Per-provider redirect URI Yes RFC 9700 s2.1

SAML has the same problem in different clothing, and the same shape of fix. A service provider that accepts assertions from several identity providers must check that the Issuer element of the response matches the entity whose key verified the signature, that the key is the one registered for that entity rather than merely a trusted key from the federation aggregate, and that the assertion arrived at an endpoint associated with the provider the request went to. The strongest structural version is a distinct assertion consumer service URL per identity provider, which is the SAML equivalent of a per-provider redirect URI.

Multi-tenant software and the tenant-to-provider binding#

Everything so far assumed one relying party and one or more providers. Commercial software adds a dimension that generates its own vulnerability class: one relying party serving thousands of customer organizations, each of which has its own users and may bring its own identity provider.

The data model has three layers, and the bugs live between them.

  tenant  (t_8841 "Meridian Analytics")
     |
     +-- verified domains: meridian.example
     |
     +-- identity provider binding:
     |      issuer  = https://login.meridian.example
     |      keys    = <signing key>
     |
     +-- users: (tenant_id, issuer, subject) -> user_id

Five failure modes recur, and each has produced real incidents.

The first is a global user lookup. The application resolves the incoming statement to a user by searching all tenants rather than within the tenant bound to the issuer. Any customer’s identity provider can then produce a statement that lands on any other customer’s user. The fix is that the tenant is determined by the issuer, and the user lookup is scoped to that tenant.

The second is unverified domain claiming. A tenant administrator types a domain into the settings page and the application begins routing that domain’s users to that tenant’s provider. If ownership is not proved, one customer can capture another customer’s users. Domain proof by DNS TXT record or by a file served at a well-known path is the standard remedy, and re-verification matters as much as first verification, because domains change hands; that is precisely the Truffle Security finding applied to a tenant boundary.

The third is trusting an issuer-supplied email or domain to select the tenant. This is nOAuth in its multi-tenant form: the statement is authentic, it comes from a genuine identity provider, and the attribute used to route it is one the attacker controls.

The fourth is identity-provider-initiated flows that carry no request context. An assertion arrives unsolicited at the application’s endpoint; there is no stored expectation to compare it against, so the application must derive everything from the assertion itself. If it derives the tenant from an attribute rather than from the issuer, the tenant boundary is decided by the attacker’s own document.

The fifth is administrative reach across the boundary. GitLab’s CVE-2022-1680, published on 6 June 2022 and affecting Enterprise Edition versions 11.10 through 14.9.4, 14.10.0 through 14.10.3 and 15.0.0, is the textbook case. Where group SAML single sign-on was enabled, an owner of a Premium group could invite arbitrary users by username and email and then change those users’ email addresses through the SCIM provisioning interface to an attacker-controlled address, taking over accounts that did not have two-factor authentication, and could also alter the target’s display name and username. It was scored 8.8 by NIST and 9.9 by GitLab on CVSS version 3.1. The lesson is not about SCIM. It is that a tenant administrator is an untrusted party with respect to every other tenant, and any path by which their configuration can affect a user outside their tenant is a vulnerability whatever the protocol.

The audit questions are short enough to memorize. Is the tenant selected by the issuer, or by an attribute? Is the user key scoped by tenant? Is every domain proved, and re-proved? Can a tenant administrator affect any record outside their own tenant? And when single sign-on is enforced for a tenant, are the local password, the invitation link and the long-lived API token disabled too, or is there still a way in that the identity provider knows nothing about?

Hubs, proxies, and multilateral federations#

Bilateral trust does not scale, and the arithmetic is brutal. On the eduGAIN figures for 17 August 2026 — 6,539 identity providers and 4,040 service providers — the number of possible provider-to-service pairs is 6,539 multiplied by 4,040, which is 26,417,560. Nobody is going to negotiate twenty-six million agreements. At the federation level the same problem is smaller but still real: 84 federations connected pairwise would need 84 times 83 divided by 2, which is 3,486 agreements, instead of 84 signatures on one Policy Declaration.

Two structures solve it, and they are genuinely different.

  MESH (InCommon, eduGAIN)      HUB / PROXY (a campus or
                                 infrastructure proxy)
  IdP --\      /-- SP           IdP --\
  IdP ---+----+--- SP           IdP ---+-- PROXY --- SP
  IdP --/      \-- SP           IdP --/      |    \-- SP
       signed metadata                    sees all
       aggregate; each pair              traffic; one
       still talks directly              entity to SPs

In a mesh, the federation operator publishes a signed aggregate of everyone’s metadata, and each identity provider still speaks directly to each service provider. Trust is transitive through the operator’s signature, but traffic is not: the federation operator never sees a login. That is the eduGAIN and InCommon model, with each entity carrying a registration authority naming the federation that registered it.

In a hub, one entity sits in the middle and is a service provider to everything above it and an identity provider to everything below. Downstream services integrate once, with the proxy, and never learn that fifty universities exist behind it. Attribute release policy, consent, assurance harmonization and group information can all be applied in one place. The cost is real: the proxy sees every login for everybody, it becomes an extremely attractive target, and it is a single point of failure for the whole community it serves.

The reference design for the hub pattern in research infrastructures is the AARC Blueprint Architecture. The 2019 edition defines five layers — user identity, community attribute services, access protocol translation, authorization, and end services — with the proxy sitting in the translation layer as the administrative and technical boundary between the outside world and the infrastructure’s own services. Supporting guidelines cover how a proxy should express home institution affiliation, how it should construct user identifiers, how assurance information should be passed on, and how discovery should be simplified and routed. As of August 2026 a 2025 edition exists under the AARC TREE project but is still in consultation rather than endorsed.

The newest development in this area is the attempt to automate the contract layer itself. OpenID Federation 1.0 reached Final status in a version dated 17 February 2026. It replaces the signed flat aggregate with signed entity statements: every entity publishes an entity configuration at the path .well-known/openid-federation naming its keys, its metadata and its authority hints, and trust is established by building a chain of subordinate statements from that entity up to a trust anchor whose key the relying party already holds. It adds metadata policies, so an anchor can constrain what its subordinates may claim, and trust marks, so accreditation can be asserted in-band. It is the first design that lets two parties who have never met establish trust automatically without either a bilateral exchange or a full aggregate download. It does not remove the paper; it moves the paper to the trust anchor, which is exactly where this chapter’s thesis says it belongs.

Designing for the day the identity provider is down#

Federation makes the identity provider a hard dependency for every first login. That dependency has to be sized and designed for, and the honest way to do it is with real numbers from real outages.

Failure What it breaks Real example
Signing key removed All token validation Azure AD, 15 Mar 2021
Name resolution fails Reaching the provider Entra ID, 25 Feb 2025
Backend code defect All authentication Azure AD, 28 Sep 2020
Metadata expired Assertions rejected validUntil elapsed
Provider compromised Trust itself Okta support, Oct 2023

The 15 March 2021 incident is the instructive one for federation specifically. Microsoft’s preliminary review described an error in the rotation of keys used for Azure Active Directory’s OpenID and other identity protocols: a key had been marked “retain” for longer than normal to support a cross-cloud migration, and the automation that removes keys no longer in use ignored the retain state and removed it, after which applications stopped trusting tokens signed with it. Impact ran from roughly 19:15 to 22:10 UTC. The applications were healthy throughout. On 25 February 2025 a DNS configuration change during an IPv6 cleanup removed records needed to reach a seamless sign-on endpoint, and authentication failed globally from 17:18 to 18:35 UTC, about seventy-seven minutes.

The October 2023 Okta case is a different failure entirely and belongs in the same table because it is the one federation is least able to absorb. Okta disclosed on 19 October 2023 that a threat actor had accessed files in its customer support case management system between 28 September and 17 October 2023, affecting 134 customers, less than one per cent of its base; some of those files were HTTP archive files containing session tokens usable for session hijacking. Nothing was down. The question a relying party has to answer is what it would do if the organization it agreed to believe stopped being believable, and the answer has to exist before the day it is needed.

Now size it for Meridian, on stated assumptions rather than measurements. Take a seventy-seven-minute outage between 09:00 and 10:17 on a working day. Application sessions last 8 hours; access tokens last 60 minutes and are refreshed at the identity provider.

Population Basis Affected
Arrive during window 18% of 2,400 432
Already signed in Session valid 0 blocked
Needing token refresh All active users about 1,900

The middle row is the comforting one that people quote. The bottom row is the one that decides whether the outage is an inconvenience or a stoppage: with a sixty-minute token lifetime, every active user crosses a refresh boundary inside a seventy-seven-minute window, so an application that treats a failed refresh as an immediate logout will empty itself of users who were working perfectly well a minute earlier.

That gives the design rules, in order of value.

  1. Separate the session from the token. A failed refresh should degrade the application, not end the session; keep the user signed in, keep read paths working, and retry.
  2. Cache the provider’s keys and serve them stale on error. A JWKS or metadata document that cannot be fetched should not invalidate keys already known to be good and not yet expired.
  3. Watch validUntil. Metadata that expires during an outage converts a recoverable event into a manual reconfiguration; alert on remaining validity, not on expiry.
  4. Keep break-glass local accounts, excluded from federation, with strong unique credentials held offline, monitored so that any use raises an alarm, and tested on a schedule. Every organization that has lived through this has them; the ones that have not, do not.
  5. Publish and accept more than one signing key during rotation, so that removing one key cannot be a global outage.
  6. Decide the revocation-versus-availability trade openly. Long sessions survive outages and also survive dismissals; short sessions do the reverse. Write down which risk you chose and why, because somebody will ask during a review.
  7. Measure the dependency. Count, per hour, how many operations require the identity provider to be reachable. That number, not an architecture diagram, tells you what an outage costs.

43.98 Common wrong ideas#

Wrong: Single sign-on and federation are two words for the same thing. Right: Single sign-on is authenticating once inside one trust domain, where one authority owns the accounts, the policy and the incident process; federation is two such authorities agreeing that one will believe the other, which requires an agreement, a defined attribute vocabulary, and a decision about how fast revocation travels.

Wrong: If the signature on the assertion verifies, the assertion can be believed. Right: A valid signature answers only whether the message is authentic; it says nothing about whether that issuer is entitled to speak about this subject, whether the issuer’s enrolment process is any good, or whether the statement is still true, and those three questions are settled in the federation agreement rather than in the cryptography.

Wrong: Matching a federated login to a local account by email address is a reasonable default. Right: The email address is a mutable display attribute that at least one major provider allowed users to set to unverified values, that changes hands when a domain is sold, and that different providers may assert simultaneously; the identity is the pair of issuer and subject, and any merge on email must be gated by proof of control.

Wrong: The state parameter and PKCE together defend the redirect flow against everything. Right: They defend against cross-site request forgery on the callback and against code theft or injection, but neither tells the client which authorization server produced the response, which is why RFC 9207 of March 2022 adds the iss parameter and RFC 9700 of January 2025 tells multi-provider clients to use it or to give each provider a distinct redirect URI.

Wrong: Just-in-time provisioning removes the need for lifecycle management. Right: It is driven entirely by the user turning up, so it creates and updates but can never delete; the account of somebody who has left is simply never touched again and remains in the active state, along with any local password, API token or invitation link attached to it, until a reconciliation process finds it.

Wrong: Being listed in the same federation metadata means two entities trust each other. Right: Registration by a member federation means somebody vouched that the entity meets baseline requirements and can be reached; whether to accept a given identity provider, and what attributes to release to a given service provider, remains a decision each side makes and records, which is why entity categories and assurance profiles exist.

Wrong: If the identity provider goes down, only people who are not yet signed in are affected. Right: Anything that renews a short-lived token at the provider fails too, so with sixty-minute access tokens a seventy-seven-minute outage reaches essentially every active user, and whether they notice depends on whether the application treats a failed refresh as a degraded state or as an immediate logout.

Wrong: Putting a proxy or hub in the middle simplifies the security problem. Right: It simplifies integration, because downstream services connect once instead of many times, but it concentrates the security problem into one component that sees every login for every user in the community, is a single point of failure for all of them, and must therefore be operated to a higher standard than any of the entities behind it.

43.99 Chapter summary in 20 lines#

  1. Federation is one organization agreeing to believe another organization’s statements about who a person is.
  2. That agreement is contractual before it is technical, and the protocol only delivers a decision that was made elsewhere.
  3. Single sign-on operates inside one trust domain, where a single authority owns the account store, the policy and the incident process.
  4. The moment two authorities are involved, you are federating, even if both are inside the same legal entity.
  5. The three roles are the identity provider that asserts, the service provider or relying party that consumes, and the subject the statement is about.
  6. Trust is established by exchanging metadata that binds a name to a key, and the exchange is only sound if some step in it happens out of band.
  7. SAML metadata carries a validUntil attribute, and the eduGAIN SAML profile of 3 April 2018 requires it to fall between 120 and 2304 hours after creation.
  8. The Metadata Query Protocol used to fetch single entities on demand remains an individual Internet-Draft, at revision 25 of 12 June 2026, and has never become an RFC.
  9. Real federations spend their documentation on obligations, and eduGAIN’s constitution, at version 4.0 of 1 January 2024, requires a signed Policy Declaration and an assembly vote before any technical registration.
  10. InCommon enforces Baseline Expectations through a community dispute resolution process that removed thirty non-compliant entities from its metadata in December 2022.
  11. Home realm discovery decides which provider a visitor is sent to, and in every implementation some part of that decision comes from an untrusted input.
  12. The OASIS Identity Provider Discovery Service Protocol and Profile of 27 March 2008 defines the entityID, return, returnIDParam, policy and isPassive parameters, and the return address must be validated against registered metadata.
  13. The SAML common domain cookie, named _saml_idp in section 4.3 of the profiles specification, holds base-64 encoded provider identifiers with the most recent last.
  14. Account linking must key on the pair of issuer and subject, because a subject value is unique only within an issuer and an email address is neither immutable nor exclusively held.
  15. The nOAuth disclosure of 20 June 2023 and the Truffle Security research of 13 January 2025 are the two clearest published demonstrations of what email-based linking costs.
  16. Just-in-time provisioning creates and updates accounts from the statement at login, and leaves an orphan for every leaver in every application they ever used.
  17. The identity provider mix-up attack, published by Fett, Küsters and Schmitz in 2016, confuses the relying party about which provider produced a response, and neither state nor PKCE prevents it.
  18. RFC 9207 of March 2022 fixes it with an iss parameter in the authorization response that the client must compare against the issuer it sent the request to.
  19. In multi-tenant software the tenant must be selected by the issuer and never by an attribute, every claimed domain must be proved and re-proved, and a tenant administrator must have no reach outside their own tenant.
  20. Design for the identity provider being unreachable by separating sessions from token refresh, serving cached keys stale on error, keeping tested break-glass accounts, and measuring how many operations per hour actually need the provider.

Chapter sources: RFC 9207, “OAuth 2.0 Authorization Server Issuer Identification”, K. Meyer zu Selhausen and D. Fett, March 2022, sections 2, 2.4, 3 and 4; RFC 9700, “Best Current Practice for OAuth 2.0 Security”, T. Lodderstedt, J. Bradley, A. Labunets and D. Fett, January 2025, BCP 240, section 2.1; RFC 6749 section 4.1.1 and RFC 7636 for state and PKCE; the expired Internet-Draft “OAuth 2.0 Mix-Up Mitigation” by M. Jones, J. Bradley and N. Sakimura; D. Fett, R. Küsters and G. Schmitz, “A Comprehensive Formal Security Analysis of OAuth 2.0”, arXiv preprint of 6 January 2016 and ACM Conference on Computer and Communications Security 2016, for the IdP mix-up and 307 redirect attacks and their three stated preconditions; A. Sudhodanan and A. Paverd, “Pre-hijacked accounts: An Empirical Study of Security Failures in User Account Creation on the Web”, 31st USENIX Security Symposium, August 2022, for the five pre-hijacking classes and the figures of 75 services tested and at least 35 vulnerable; OASIS “Identity Provider Discovery Service Protocol and Profile”, Committee Specification 01, 27 March 2008; OASIS SAML 2.0 profiles specification section 4.3 for the _saml_idp common domain cookie; OpenID Connect Core 1.0 section 3.1.2.1 for login_hint; OpenID Federation 1.0, Final, version dated 17 February 2026; the eduGAIN Policy Framework Constitution version 4.0 of 1 January 2024 with its version history from 1.0 of 21 March 2011; the eduGAIN SAML Profile version 0.5 of 3 April 2018 for metadata validity of 120 to 2304 hours and its key and digest requirements; eduGAIN technical service statistics as published on 17 August 2026; InCommon “Baseline Expectations for Trust in Federation” and its published compliance and dispute resolution results of December 2022 and January 2023; the REFEDS Security Incident Response Trust Framework for Federated Identity (Sirtfi); the AARC Blueprint Architecture 2019 and the 2025 edition in consultation; NISO RP-27-2019 of 21 June 2019 from the RA21 project; Descope and Microsoft Security Response Center disclosures of nOAuth on 20 June 2023 with the reporting timeline from 11 April 2023; Truffle Security, “Millions of Accounts Vulnerable due to Google’s OAuth Flaw”, 13 January 2025; CVE-2022-1680 as published on 6 June 2022; Microsoft’s preliminary post-incident review of the Azure Active Directory outage of 15 March 2021 and reporting of the Entra ID incident of 25 February 2025; Okta security disclosures of 19 October and 3 November 2023 concerning its customer support case management system; and the United Nations Convention on Road Traffic signed at Geneva on 19 September 1949 and the Convention on Road Traffic signed at Vienna on 8 November 1968, used for the opening analogy.