Skip to content
TDACorpIDENTITYSign in

Environments and the issuer

The issuer address, the discovery document and the signing keys, and how to configure a client so it never hard-codes an endpoint.

On this page

Every client of identity starts from one string: the issuer. It is an https address, and it is the only address you configure. Everything else, the authorization endpoint, the token endpoint, the signing keys, comes from the discovery document that the issuer publishes.

The issuer#

TDACorp Identity's issuer is:

https://identity.tdacorp.in

Three rules follow from what the issuer is.

  • It is an identifier before it is an address. Every ID token and access token carries it as iss, every authorization response carries it as iss, and you must compare it byte for byte. No trailing slash, no different case, no www. A token whose iss differs is not from identity.
  • It has no query or fragment, and it must be https. The SDK refuses anything else, with one exception for a loopback host during local development.
  • It is never taken from a request. Identity builds its metadata from a configured issuer, not from the Host header, and your code should do the same: put the issuer in your configuration, not in a value derived from an incoming request.

If TDACorp gives you a different issuer for testing, use it exactly the same way. Only the issuer and your client id change. A client is registered with one issuer, so ask for a separate registration for each.

Discovery#

The discovery document is JSON at a fixed path under the issuer:

GET https://identity.tdacorp.in/.well-known/openid-configuration

The same document is also served at /.well-known/oauth-authorization-server, for libraries that look for the OAuth name. Fetch it once, cache it, and read endpoints from it. An excerpt:

{  "issuer": "https://identity.tdacorp.in",  "authorization_endpoint": "https://identity.tdacorp.in/authorize",  "pushed_authorization_request_endpoint": "https://identity.tdacorp.in/par",  "token_endpoint": "https://identity.tdacorp.in/token",  "userinfo_endpoint": "https://identity.tdacorp.in/userinfo",  "revocation_endpoint": "https://identity.tdacorp.in/revoke",  "end_session_endpoint": "https://identity.tdacorp.in/logout",  "jwks_uri": "https://identity.tdacorp.in/.well-known/jwks.json",  "response_types_supported": ["code"],  "code_challenge_methods_supported": ["S256"],  "require_pushed_authorization_requests": true,  "dpop_signing_alg_values_supported": ["EdDSA", "ES256"],  "device_authorization_endpoint": null}

The members that change how you build a client:

MemberWhat it tells you
pushed_authorization_request_endpoint and require_pushed_authorization_requestsEvery sign-in begins with a pushed request. See Pushed authorization requests.
code_challenge_methods_supportedS256 only. A plain challenge is refused.
response_modes_supportedquery and form_post. A web client defaults to form_post when it does not say.
authorization_response_iss_parameter_supportedThe authorization response carries iss. Check it.
token_endpoint_auth_methods_supportedThe ways to authenticate to the token endpoint. See Client authentication.
dpop_signing_alg_values_supportedThe algorithms identity accepts for DPoP proofs. See DPoP.
scopes_supported and claims_supportedThe standard scopes and claims. See Scopes and consent.
resource_indicators_supportedA resource parameter is understood. See Resource indicators.
subject_types_supportedpublic and pairwise. A client registered pairwise sees a sub specific to its sector. See ID token.
backchannel_logout_supportedIdentity sends logout tokens. See Back-channel logout.
device_authorization_endpointAlways null: the device flow does not exist.

The document lists only what is reachable. A member appears when the thing it describes works, so a client can act on what it reads. The generated table of endpoints is in OIDC endpoints.

The SDK caches discovery for five minutes by default and requires every endpoint to be on the issuer's own origin.

Signing keys#

jwks_uri points to the JSON Web Key Set that verifies every token identity signs. Identity signs with EdDSA or ES256, and each key has a kid. Verify like this:

  1. Read the kid from the token header. Do not trust any other header member to choose a key.
  2. Look it up in the cached key set. If it is not there, fetch the set again, but not on every request: an attacker controls the kid of an unverified token, so refetch at most once in a cooldown period.
  3. Import the key for the algorithm you allow and verify the signature. Do not let the token pick the algorithm.

Keys rotate. A cached key set that is too old, or a kid you do not know, means you refetch, not that the token is bad. The SDK does this for you, and a resource server built with the SDK does it too.

What to configure#

SettingSource
IssuerYour configuration. One string.
Client idYour configuration. Public.
Client private key and kidYour secret manager.
DPoP private keyYour secret manager. See DPoP.
Redirect URIYour configuration. Must equal the registered address exactly.
Every endpointDiscovery. Never hard-coded.

Next: Choosing an integration if you have not decided on a client type, or the Quickstart.

Verified against commit 5d85077