skip to content

In SAML 2.0, what does a party's entityID identify, and what does it not?

level: middleimportance: should knowfreq 44%

answer

  1. it names a party, not a person
  2. a name, not an address to fetch
  3. endpoints move, the name does not
  4. compared as an exact string
  5. changing it means re-registering everywhere

basics

~20 s

entityID is the unique name of a SAML party — an identity provider, a service provider or an attribute authority. It names an organisation or deployment, never a person, and although it is written as a URI it is compared as a string, not fetched.

solid answer

~50 s

`entityID` is the identifier a SAML party answers to. It appears as an attribute on that party's `<EntityDescriptor>`, and it is the string a message uses when it names who issued a statement or which party a statement is for. Three things it is not: it is not a person — the subject of an assertion is identified separately; it is not an endpoint, because delivery locations are their own values and can move while the name stays put; and it is not required to resolve, even though almost everyone writes it as an absolute URL by convention. Counterparties match it by **exact string comparison**, so case, a trailing slash or `http` versus `https` make it a different party. Changing it is not a rename — it is becoming a new party that every counterparty must register again.

code

xml · 9 lines
xml
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
                     entityID="https://idp.example.com/idp">
  <md:IDPSSODescriptor
      protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    <md:SingleSignOnService
        Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
        Location="https://idp.example.com/idp/sso"/>
  </md:IDPSSODescriptor>
</md:EntityDescriptor>

go deeper

for a junior

Remember that this identifier names an organisation or deployment, not a person, and that the person is identified separately inside the statement being exchanged.

for a middle

Explain that it is a URI used as an opaque name, matched by exact string comparison, and distinguish it from the endpoint locations, which can move while the name stays fixed.

for a senior

Diagnose from the symptom: a verified signature and a rejected sign-on usually means a name mismatch, not a key problem. Know why changing the identifier is a coordinated change across every counterparty.

for a principal

Set the naming policy before the first integration: a URI in a namespace the organisation will hold long term, decoupled from any hostname, and a documented dual-registration path for the day it must change.

## What an entityID is In SAML 2.0, `entityID` is the name a party answers to. It is carried as an attribute on that party's `<EntityDescriptor>`, and it is what every message means when it names a party rather than a person: the issuing party's `entityID` is what a message's `<Issuer>` element carries, and the intended party's `entityID` is what the element naming the assertion's intended consumer carries. It is defined as a URI. In practice deployments almost always use an absolute `https` URL, often the address where the party's own metadata document happens to be published — but that is a convention, not a rule the protocol enforces. ## What it is not Three confusions account for most of the trouble. - **Not a person.** `entityID` names an organisation, a tenant or a deployment. Who signed in is a different identifier entirely, carried in the assertion's subject. A stem or a log line that mixes the two is unreadable: one is stable for years and shared by everybody at that party, the other may be transient and is per-person. - **Not an endpoint.** The locations messages are sent to are separate values on the party's role descriptors. A party can move every endpoint it operates to a new hostname and keep the same `entityID` — and that is usually the right thing to do, because the name is what the counterparties registered. - **Not something you fetch.** The specification does not require a relying party to dereference an `entityID`, and a consumer that tries to fetch one in order to decide whom it is talking to has invented a trust mechanism the protocol does not have. Trust comes from the key a counterparty registered, not from whatever an HTTP GET to that URL returns today. ## How the comparison actually works Counterparties match `entityID` by **exact string comparison**. This is undramatic until it bites: - `https://sp.example.net/saml` and `https://sp.example.net/saml/` are two different parties; - `http://` and `https://` spellings of the same host are two different parties; - a difference in case in the path is a difference in party; - a party that regenerates its identifier during a platform migration has not migrated — it has appeared for the first time. The failure this produces is distinctive and worth recognising: sign-on fails at the consuming side even though the signature verifies, because the message named a party the consumer has no registration for, or was addressed to a spelling the consumer does not recognise as itself. ## Three identifiers in one login, and what each names | Value | Names | Changes when | |---|---|---| | `entityID` | the party — identity provider, service provider or attribute authority | essentially never; changing it means re-registering with every counterparty | | an endpoint location | where one kind of message is delivered at that party | the deployment moves, without the name changing | | the assertion's subject identifier | the person the statement is about | per person, and for some formats per session | ## Why a stable name matters more than it looks In a port community — a carrier, a terminal operator, a customs broker and a dozen hauliers exchanging the same consignment documents — every pair of parties has, at some point, registered each other by name and key. There is no central register that can rename you on everybody's behalf. So the name is the one value in the whole arrangement that is expensive to change: endpoints move with a configuration edit on your side, keys roll over with a planned overlap, but a new `entityID` is a coordinated change at every counterparty, each of which has its own change process and its own idea of how long that will take. The practical advice that follows: 1. choose a URI in a namespace you will still control in ten years, and do not tie it to a hostname you expect to retire; 2. write it once and copy it everywhere rather than retyping it, because the comparison is exact; 3. treat it as an opaque name in your own code — never parse it for a tenant name or a region, and never build a URL from it; 4. if you genuinely must change it, run both names in parallel as two registrations for the transition rather than flipping in one step. ## The one-line version `entityID` is the name of a party, matched as a string, owned for the long term. The subject identifier in an assertion names a person; the endpoint locations say where messages go. Keeping those three apart removes an entire class of confused integration tickets.

  • A service provider moves to a new hostname. Should its entityID change with it?
    No. The endpoint locations change and the counterparties pick those up, but the name stays. Changing `entityID` makes it a new party to every counterparty, each of which must register it afresh before sign-on works again — a coordinated change you should not spend on a hostname move.
  • Two parties have identical entityID values except for a trailing slash. What happens?
    They are two different parties. The comparison is exact, so a message naming one spelling will not match a registration under the other. The symptom is a rejection at the consuming side even though the signature verifies, which sends people hunting for a key problem that is not there.

saying these in an interview costs you the question

  • Thinks entityID identifies the user who signed in.
  • Assumes a counterparty fetches the entityID URL to obtain the signing key.
  • Treats entityID and the assertion delivery endpoint as the same value.
  • Compares entityID loosely, ignoring scheme, case or a trailing slash.
  • Regenerates the entityID during a platform move and calls it a rename.