OpenID Connect Discovery 1.0 Deep Dive: OP's 'Self-Introduction' and Dynamic Configuration Retrieval

Published: (March 7, 2026 at 03:50 AM EST)
8 min read
Source: Dev.to

Source: Dev.to

Introduction

You probably use OIDC (OpenAI Connect) every day to integrate Google Login or other authentication flows into your applications.
When doing so, have you ever experienced simply setting

issuer: "https://accounts.google.com"

in your library initialization code, and it automatically resolves the Authorization Endpoint, Token Endpoint, and even the location of the public keys (JWKS)?

  • “Why does just providing the Issuer URL reveal all the endpoints?”
  • “How can it follow public‑key (JWKS) rotation without any downtime?”
  • “In the first place, how does it identify the provider to authenticate with from an email‑like ID such as alice@example.com?”

The answer to these questions is OpenID Connect Discovery 1.0.

In the past OAuth 2.0 world, developers often read the documentation and hard‑coded the URLs of each endpoint (e.g., /authorize, /token) of the Authorization Server into the client.
That approach required client‑side changes whenever the provider altered URLs or rotated public keys—clearly not scalable.

OIDC Discovery 1.0 is a standardized mechanism for a client to dynamically discover and retrieve the configuration information (metadata) of an OpenID Provider (OP).

In this article, based on the specification, we will dive deep into the two phases of OIDC Discovery:

PhaseGoal
Issuer Discovery (Phase 1)Discover who the OpenID Provider (Issuer) is that should authenticate the user, based on an identifier supplied by the user (e.g., an email address). This step is optional and is skipped when the Issuer is already known (e.g., clicking “Login with Google”).
Provider Configuration (Phase 2)Query the identified Issuer for its configuration metadata – “Where is your Authorization Endpoint?” “Where are your public keys (JWKS)?”

When is Issuer Discovery needed?

If your app is dedicated to Google Login, the Issuer is obviously https://accounts.google.com.
But consider an enterprise SaaS that must dynamically switch the destination IdP based on the user’s email domain (@company.com).
That’s where RFC 7033 WebFinger comes into play.

Normalizing the User‑Supplied Identifier

The value entered by the user can be:

  • an email address like alice@example.com
  • a URL like https://example.com/alice

OIDC Discovery defines strict Normalization Steps to uniquely determine:

  • Host – the server to contact
  • Resource – the identifier to query via WebFinger

Normalization Rules

ConditionNormalized Form
No scheme and contains @ (e.g., joe@example.com)Interpreted as the acct: scheme → acct:joe@example.com
No scheme and does not contain @ (e.g., example.com or example.com:8080)Interpreted as https://https://example.com
Explicit scheme (https://, acct:, …)Used as‑is, no further changes
Fragment present (#…)Remove the fragment entirely

Phase 1 – Issuer Discovery via WebFinger

Assume the user entered joe@example.com, which normalizes to acct:joe@example.com.

  1. Identify the Host – Extract the authority part (example.com).
  2. Specify the Resource – Use the full normalized URI (acct:joe@example.com) as the resource query parameter.
  3. Call the WebFinger endpoint – Perform an HTTP GET against /.well-known/webfinger on the extracted host.
GET /.well-known/webfinger?resource=acct%3Ajoe%40example.com&rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer HTTP/1.1
Host: example.com
  • resource – URL‑encoded identifier to be queried.
  • rel – Fixed value http://openid.net/specs/connect/1.0/issuer, meaning “I am asking for OIDC Issuer information”.

Example Response (JRD – JSON Resource Descriptor)

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

{
  "subject": "acct:joe@example.com",
  "links": [
    {
      "rel": "http://openid.net/specs/connect/1.0/issuer",
      "href": "https://server.example.com"
    }
  ]
}

The href value (https://server.example.com) is the Issuer URL that the client will use for the next phase.

Phase 2 – Provider Configuration

With the Issuer known, the client retrieves the OP’s metadata.
OIDC Discovery mandates that the OP exposes JSON metadata at a path formed by appending /.well-known/openid-configuration to the Issuer URL.

GET /.well-known/openid-configuration HTTP/1.1
Host: server.example.com

⚠️ Common Pitfall – Issuer Contains a Path

If the Issuer includes a path (e.g., https://example.com/tenant-1):

  1. Remove any trailing slash.
  2. Append /.well-known/openid-configuration directly after the path.

Resulting URL:

https://example.com/tenant-1/.well-known/openid-configuration

Do not mistakenly place the configuration file at the domain root (https://example.com/.well-known/openid-configuration), as many implementations do.

Example OP Metadata Response

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

{
  "issuer": "https://server.example.com",
  "authorization_endpoint": "https://server.example.com/oauth2/v1/authorize",
  "token_endpoint": "https://server.example.com/oauth2/v1/token",
  "userinfo_endpoint": "https://server.example.com/oauth2/v1/userinfo",
  "jwks_uri": "https://server.example.com/oauth2/v1/keys",
  "registration_endpoint": "https://server.example.com/oauth2/v1/register",
  "scopes_supported": ["openid", "profile", "email"],
  "response_types_supported": ["code", "id_token", "token id_token"],
  "grant_types_supported": ["authorization_code", "refresh_token", "client_credentials"],
  "subject_types_supported": ["public", "pairwise"],
  "id_token_signing_alg_values_supported": ["RS256"],
  "claims_supported": ["sub", "iss", "aud", "exp", "iat", "email", "email_verified", "name"]
}

The JSON object (OP Metadata) lists:

  • Endpoints (authorization_endpoint, token_endpoint, userinfo_endpoint, jwks_uri, …)
  • Supported features (scopes_supported, grant_types_supported, claims_supported, etc.)

With this metadata, client libraries can automatically:

  • Direct users to the correct Authorization Endpoint
  • Exchange codes at the proper Token Endpoint
  • Retrieve public keys from the JWKS URI (handling rotation transparently)

Recap

  1. Issuer Discovery (optional) – Use WebFinger to turn a user‑supplied identifier (email, URL, etc.) into an Issuer URL.
  2. Provider Configuration – Fetch the Issuer’s /.well-known/openid-configuration document to obtain all required endpoints and capabilities.

This two‑phase discovery process eliminates hard‑coding, supports multi‑tenant scenarios, and ensures seamless key rotation—all without any downtime.

OpenID Connect Provider Configuration (Discovery)

{
  "authorization_endpoint": "https://server.example.com/connect/authorize",
  "token_endpoint": "https://server.example.com/connect/token",
  "userinfo_endpoint": "https://server.example.com/connect/userinfo",
  "jwks_uri": "https://server.example.com/jwks.json",
  "response_types_supported": [
    "code",
    "id_token",
    "id_token token"
  ],
  "subject_types_supported": [
    "public",
    "pairwise"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256",
    "ES256"
  ],
  "token_endpoint_auth_methods_supported": [
    "client_secret_basic",
    "private_key_jwt"
  ],
  "scopes_supported": [
    "openid",
    "profile",
    "email"
  ],
  "claims_supported": [
    "sub",
    "iss",
    "name",
    "email"
  ],
  "registration_endpoint": "https://server.example.com/connect/register"
}

Parameter Overview

Parameter NameRequired / OptionalDescription
issuerREQUIREDThe OP’s Issuer Identifier. Used for TLS checks and validation of the iss claim in the ID Token.
authorization_endpointREQUIREDThe endpoint to which the user is redirected for authentication.
token_endpointREQUIRED*The endpoint used to exchange an authorization code for tokens. Except for OPs that only support the Implicit Flow.
jwks_uriREQUIREDURL where the public keys (JWK Set) for verifying the ID Token’s signature are located.
response_types_supportedREQUIREDThe OIDC authentication flows supported by the OP (e.g., code, id_token, id_token token).
subject_types_supportedREQUIREDTypes of sub identifiers supported – public (same across all RPs) or pairwise (unique per RP).
id_token_signing_alg_values_supportedREQUIREDSignature algorithms the OP can use for ID Tokens. RS256 MUST be included.
token_endpoint_auth_methods_supportedOPTIONALClient authentication methods accepted at the token endpoint (e.g., client_secret_basic, private_key_jwt).
scopes_supportedRECOMMENDEDList of scopes the OP supports. The openid scope SHOULD be present.
claims_supportedRECOMMENDEDList of claims the OP can return (e.g., name, email, sub, iss).
registration_endpointRECOMMENDEDEndpoint for Dynamic Client Registration.

Deep‑Dive: jwks_uri

  • Why it matters – The jwks_uri is the single source of truth for the OP’s public keys. By fetching this URL, a Relying Party (RP) can verify the signature of every ID Token it receives.
  • Key rotation – An RP should inspect the kid (Key ID) header of an incoming ID Token. If the corresponding key is missing from the local cache, the RP must re‑fetch the JWKS from jwks_uri. This enables seamless key rotation without downtime.
  • Security considerations
    • Impersonation attacks: If an attacker can make the RP download a malicious JWKS, forged ID Tokens become possible.

    • The Discovery spec enforces strict checks:

      “The issuer value returned MUST be identical to the Issuer URL that was used as the prefix to /.well-known/openid-configuration.” (OIDC Discovery §4.3)

      “Implementations MUST support TLS.” (OIDC Discovery §7.1)

    • All communication (WebFinger and Provider Configuration) must occur over HTTPS, and the RP must verify the server’s TLS certificate (RFC 6125). Plain‑text transport would allow a MITM to rewrite jwks_uri to an attacker‑controlled server.

Key take‑aways from OIDC Discovery 1.0

  1. No hard‑coded URLs – Using /.well-known/openid-configuration lets RPs discover the OP’s endpoints and capabilities at runtime.
  2. WebFinger integration – An identifier such as a user’s email can be resolved to the correct Issuer (Discovery Phase 1).
  3. Automated key rotation – Dynamic retrieval of the JWKS enables robust, seamless security operations.

When you next use an OIDC library, picture the hidden request to /.well-known/openid-configuration that powers all of the above.

References

  • OpenID Connect Discovery 1.0 – Core specification for provider metadata.
  • RFC 7033 – WebFinger – Mechanism for discovering information about a resource (e.g., an email address).
  • RFC 5785 – Well‑Known URIs – Defines the /.well-known/ namespace used for discovery endpoints.
0 views
Back to Blog

Related posts

Read more »

AI, Humanity, and the Loops We Break

🌅 Echoes of Experience — Standing in the Horizon There was a time when chaos shaped me. But the moment I chose myself—truly chose myself—everything shifted. I...