OpenID Connect is a simple identity layer built on top of the OAuth 2.0 protocol. Login.gov supports version 1.0 of the specification and conforms to the iGov Profile.
Getting started
Choosing an authentication method
Login.gov supports two ways of authenticating clients: private_key_jwt and PKCE.
-
private_key_jwt (preferred for web apps)
The client sends a JSON Web Token, or JWT, signed with a private key (minimum length of 2048 bits) when requesting access tokens. The corresponding public key is registered with the IdP ahead of time, similar to SAML. -
PKCE (preferred for native mobile apps)
Short for Proof Key for Code Exchange by OAuth Public Clients and pronounced “pixy.” In this method, the client sends a public identifier as well as a hashed random value generated by the client.
Other implementations of OpenID Connect use the “implicit flow” or the client_secret param, but Login.gov does not support those methods. The implicit flow is not recommended by the OAuth group for security reasons. Similarly client_secret is not supported by Login.gov because of security reasons. It requires managing a shared secret in two places: the client and the server, where private_key_jwt flow involves only sharing public keys with the server and PKCE only has a one-time secret.
Auto-discovery
Consistent with the specification, Login.gov provides a JSON endpoint for OpenID Connect auto-discovery at /.well-known/openid-configuration. In our agency integration environment, this is available at https://idp.int.identitysandbox.gov/.well-known/openid-configuration
Authorization
The authorization endpoint handles authentication and authorization of a user. To present the Login.gov authorization page to a user, direct them to the /openid_connect/authorize.
View an example for…
https://idp.int.identitysandbox.gov/openid_connect/authorize?
acr_values=http%3A%2F%2Fidmanagement.gov%2Fns%2Fassurance%2Fial%2F1&
client_id=${CLIENT_ID}&
nonce=${NONCE}&
prompt=select_account&
redirect_uri=${REDIRECT_URI}&
response_type=code&
scope=openid+email&
state=abcdefghijklmnopabcdefghijklmnop
https://idp.int.identitysandbox.gov/openid_connect/authorize?
acr_values=http%3A%2F%2Fidmanagement.gov%2Fns%2Fassurance%2Fial%2F1&
client_id=${CLIENT_ID}&
code_challenge=${CODE_CHALLENGE}&
code_challenge_method=S256&
nonce=${NONCE}&
prompt=select_account&
redirect_uri=${REDIRECT_URI}&
response_type=code&
scope=openid+email&
state=abcdefghijklmnopabcdefghijklmnop
Request Parameters
-
acr_values
The Authentication Context Class Reference requests can be used to specify the type of identity verification1 or the AAL (Authentication Assurance Level) for the user. These and thescopedetermine which user attributes will be available in the user info response.Multiple values can be joined with a space (before being URI-escaped in the final URL)
Type of Identity Verification1
A type of identity verification must be specified.
http://idmanagement.gov/ns/assurance/ial/1
Basic identity assurance, does not require identity verification (this is the most common value).http://idmanagement.gov/ns/assurance/ial/2
Requires that the user has gone through identity verification1
AAL Values
We default to requiring a user to be authenticated with a second factor:
urn:gov:gsa:ac:classes:sp:PasswordProtectedTransport:duo
This specifies that a user has been authenticated with a second factor. This value will be returned in the user attributes by default. We do not allow strict AAL 1, because it implies that a user did not authenticate with a second factor. This setting requires users to reauthenticate with a separate second factor (i.e. not a session secret) once every 30 days at a minimum.
Stricter behavior can be specified by adding one of:
http://idmanagement.gov/ns/assurance/aal/2
This is the same as the default behavior except users must reauthenticate with a separate second factor (i.e. not a session secret) once every 12 hours.http://idmanagement.gov/ns/assurance/aal/2?phishing_resistant=true
This specifies that a user has been authenticated with a crytographically secure method, such as WebAuthn or using a PIV/CAC. Users must always authenticate with a second factor.http://idmanagement.gov/ns/assurance/aal/2?hspd12=true
This specifies that a user has been authenticated with an HSPD12 credential (requires PIV/CAC). Users must always authenticate with a second factor.
LOA Values
These are not recommended, and only for legacy compatibility.
http://idmanagement.gov/ns/assurance/loa/1
Equivalent to IAL1http://idmanagement.gov/ns/assurance/loa/3
Equivalent to identity verified account
-
client_id
The unique identifier for the client. This will be registered with the Login.gov IdP in advance. - code_challenge — required for PKCE
The RFC 4648 URL-safe Base64 encoding of the SHA256 digest of a random value generated by the client. The original random value is referred to as thecode_verifierand is later used with the token endpoint. Generating these values in Ruby might look like this, for example:code_verifier = SecureRandom.hex => "5787d673fb784c90f0e309883241803d" code_challenge = Digest::SHA256.digest(code_verifier) # binary data url_safe_code_challenge = Base64.urlsafe_encode64(code_challenge) # RFC 4648 URL-safe Base64 encoding replaces "+" with "-" and "/" with "_" and trims trailing "=" => "1BUpxy37SoIPmKw96wbd6MDcvayOYm3ptT-zbe6L_zM" Base64.encode64(code_challenge) # wrong and URL-unsafe encoding => "1BUpxy37SoIPmKw96wbd6MDcvayOYm3ptT+zbe6L/zM=" # wrong and URL-unsafe encoding -
code_challenge_method – required for PKCE
This must beS256, the only PKCE code challenge method supported. -
prompt – optional, requires administrator approval
To force a re-authorization event when a current IdP session is active, you will need to set thepromptattribute tologin, like this:prompt=login.Request permission for your application to do this by submitting a support request.
User experience
If prompt is not specified and the user has an active IdP session, they are given the choice to continue authenticating or login with another account.
-
response_type
This must becode. -
redirect_uri
The URI Login.gov will redirect to after a successful authorization. - scope
A space-separated string of the scopes being requested. The authorization page will display the list of attributes being requested from the user. Applications should aim to request the fewest user attributes and smallest scope needed. Possible values are:openidaddressemailall_emailsphoneprofile:birthdateprofile:nameprofile:verified_atprofilesocial_security_numberx509x509:issuerx509:presentedx509:subject
-
state
A unique value, at least 22 characters in length, used for maintaining state between the request and the callback. This value will be returned to the client on a successful authorization. -
nonce
A unique value, at least 22 characters in length, used to verify the integrity of theid_tokenand mitigate replay attacks. This value should include per-session state and be unguessable by attackers. This value will be present in theid_tokenof the token endpoint response, where clients will verify that the nonce claim value is equal to the value of the nonce parameter sent in the authentication request. Read more about nonce implementation in the spec. -
verified_within – optional, for identity verified requests only
Specifies how recently the user’s information must be verified. For example, if your application requires that the user’s data must have been verified within the last year, you can set the value toverified_within=1y, and customers whose data is older than that will go through the identity verification process again before continuing back to your application.Possible values
The shortest value allowed for this parameter is 30 days (
30d) because of the cost of identity verification, as well as the time it takes for backend verification sources to be updated.The format for this value is
xD, wherexis an integer number andDspecifies the duration.Dcan be:dfor number of days- Example:
45d
- Example:
wfor a number of weeks- Example:
8w(equivalent to56d)
- Example:
mfor a number of months (assumed to be 30-day months)- Example:
18m(equivalent to540d)
- Example:
yfor a number of years (assumed to be 365-day years)- Example:
2y(equivalent to730d)
- Example:
- locale – optional
If you know that a user would prefer one of our alternative language translations (currently Spanish or French), you can include thelocaleparameter to specify the language Login.gov should use (eitheresfor Spanish orfrfor French).
Authorization response
After an authorization, Login.gov will redirect to the provided redirect_uri.
In a successful authorization, the URI will contain the two parameters code and state:
- code — A unique authorization code the client can pass to the token endpoint.
- state — The
statevalue originally provided by the client.
For example:
https://agency.gov/response?
code=12345&
state=abcdefghijklmnopabcdefghijklmnop
In an unsuccessful authorization, the URI will contain the parameters error and state, and optionally error_description:
- error — The error type, either:
access_denied— The user has either cancelled or declined to authorize the client.invalid_request— The authorization request was invalid. See theerror_descriptionparameter for more details.
- error_description — A description of the error.
- state — The
statevalue originally provided by the client.
For example:
https://agency.gov/response?
error=access_denied&
state=abcdefghijklmnopabcdefghijklmnop
Token
Clients use the token endpoint to exchange the authorization code for an id_token and access_token. To request a token, send a HTTP POST request to the /api/openid_connect/token endpoint.
View example an for…
POST https://idp.int.identitysandbox.gov/api/openid_connect/token
client_assertion=${CLIENT_ASSERTION}&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
code=${CODE}&
grant_type=authorization_code
POST https://idp.int.identitysandbox.gov/api/openid_connect/token
code=${CODE}&
code_verifier=${CODE_VERIFIER}&
grant_type=authorization_code
Request Parameters
- client_assertion — required for private_key_jwt
A JWT signed with the client’s private key (minimum length of 2048 bits) using the RS256 algorithm and containing the following claims:- iss (string) — The issuer, which must be the
client_id. - sub (string) — The subject, which must also be the
client_id. - aud (string) — The audience, which should be (or, in the case of multiple audience values, include) the URL of the token endpoint, for example:
https://idp.int.identitysandbox.gov/api/openid_connect/token - jti (string) — The JWT ID, a unique identifier for the token which can be used to prevent reuse of the token. Should be an un-guessable, random string generated by the client.
- exp (number) — The expiration time for this token. Should be an integer timestamp (number of seconds since the Unix Epoch) and be a short period of time in the future (such as 5 minutes from now).
- iss (string) — The issuer, which must be the
-
client_assertion_type — required for private_key_jwt
When using private_key_jwt, must beurn:ietf:params:oauth:client-assertion-type:jwt-bearer -
code
The authorization code returned by the authorization response. -
code_verifier — required for PKCE
The original value (before the SHA256) generated for the authorization request for PKCE that corresponds to thecode_challenge. - grant_type
Must beauthorization_code
Token response
The token response will be a JSON object containing the following:
-
access_token (string)
An opaque token used to access the user info endpoint. -
token_type (string)
The type of access token, which will always beBearer. -
expires_in (number)
The number of seconds the access token will expire. -
id_token (string)
A signed JWT that contains basic attributes about the user and it is signed using theRS256algorithm. The public key used to verify this JWT is available from the certificates endpoint.
Here’s an example token response:
{
"access_token": "hhJES3wcgjI55jzjBvZpNQ",
"token_type": "Bearer",
"expires_in": 3600,
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJiMmQyZDExNS0xZDdlLTQ1NzktYjlkNi1mOGU4NGY0ZjU2Y2EiLCJpc3MiOiJodHRwczovL2lkcC5pbnQubG9naW4uZ292IiwiYWNyIjoiaHR0cDovL2lkbWFuYWdlbWVudC5nb3YvbnMvYXNzdXJhbmNlL2xvYS8xIiwibm9uY2UiOiJhYWQwYWE5NjljMTU2YjJkZmE2ODVmODg1ZmFjNzA4MyIsImF1ZCI6InVybjpnb3Y6Z3NhOm9wZW5pZGNvbm5lY3Q6ZGV2ZWxvcG1lbnQiLCJqdGkiOiJqQzdOblU4ZE5OVjVsaXNRQm0xanRBIiwiYXRfaGFzaCI6InRsTmJpcXIxTHIyWWNOUkdqendsSWciLCJjX2hhc2giOiJoWGpxN2tPcnRRS196YV82dE9OeGN3IiwiZXhwIjoxNDg5Njk0MTk2LCJpYXQiOjE0ODk2OTQxOTgsIm5iZiI6MTQ4OTY5NDE5OH0.pVbPF-2LJSG1fE9thn27PwmDlNdlc3mEm7fFxb8ZADdRvYmDMnDPuZ3TGHl0ttK78H8NH7rBpH85LZzRNtCcWjS7QcycXHMn00Cuq_Bpbn7NRdf3ktxkBrpqyzIArLezVJJVXn2EeykXMvzlO-fJ7CaDUaJMqkDhKOK6caRYePBLbZJFl0Ri25bqXugguAYTyX9HACaxMNFtQOwmUCVVr6WYL1AMV5WmaswZtdE8POxYdhzwj777rkgSg555GoBDZy3MetapbT0csSWqVJ13skWTXBRrOiQQ70wzHAu_3ktBDXNoLx4kG1fr1BiMEbHjKsHs14X8LCBcIMdt49hIZg"
}
The id_token contains the following claims:
- iss (string) — The issuer of the response, which will be the URL of the Login.gov IdP, for example:
https://idp.int.identitysandbox.gov - sub (string) — The subject identifier, the UUID of the Login.gov user (see user attributes).
- aud (string) — The audience, which will be the
client_id. - acr (string) — The Authentication Context Class Reference value of the returned claims, from the original authorization request.
- at_hash (string) — The access token hash, a URL-safe base-64 encoding of the left 128 bits of the SHA256 of the
access_tokenvalue. Provided so the client can verify theaccess_tokenvalue. - c_hash (string) — The code hash, a URL-safe base-64 encoding of the left 128 bits of the SHA256 of the authorization
codevalue. Provided so the client can verify thecodevalue. - exp (number) — The expiration time for this token, an integer timestamp representing the number of seconds since the Unix Epoch.
- iat (number) — Time at which the JWT was issued, an integer timestamp representing the number of seconds since the Unix Epoch.
- jti (string) — The JWT ID, a unique identifier for the token which can be used to prevent reuse of the token. Should be an un-guessable, random string generated by the client.
- nbf (number) — The “not before” value, an integer timestamp of when the token will start to be valid (number of seconds since the Unix Epoch).
- nonce (string) — The nonce value provided by the client in the authorization request.
Here’s an example decoded id_token:
{
"sub": "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca",
"iss": "https://idp.int.identitysandbox.gov",
"acr": "http://idmanagement.gov/ns/assurance/ial/1",
"nonce": "aad0aa969c156b2dfa685f885fac7083",
"aud": "urn:gov:gsa:openidconnect:development",
"jti": "jC7NnU8dNNV5lisQBm1jtA",
"at_hash": "tlNbiqr1Lr2YcNRGjzwlIg",
"c_hash": "hXjq7kOrtQK_za_6tONxcw",
"exp": 1489694196,
"iat": 1489694198,
"nbf": 1489694198
}
User info
The user info endpoint is used to retrieve user attributes. Clients use the access_token from the token response as a bearer token in the HTTP Authorization header. To request attributes, send an HTTP GET request to the /api/openid_connect/userinfo endpoint, for example:
GET https://idp.int.identitysandbox.gov/api/openid_connect/userinfo
Authorization: Bearer hhJES3wcgjI55jzjBvZpNQ
User info response
The user info response will be a JSON object containing user attributes. Login.gov supports some of the standard claims from OpenID Connect 1.0. In addition to the user attributes, the following information will also be present:
- iss (string)
The issuer of the response, which will be the URL of the Login.gov IdP, for example:https://idp.int.identitysandbox.gov- Requires
profileorprofile:namescopes.
- Requires
- email_verified (boolean)
Whether the email has been verified. Currently, Login.gov only supports verified emails.- Requires the
emailscope.
- Requires the
- phone_verified (boolean)
Whether the phone number has been verified. Currently, Login.gov only supports verified phones.- Requires the
phonescope and an identity verified account.
- Requires the
- verified_at (number, null)
When the user’s identity was last verified, as an integer timestamp representing the number of seconds since the Unix Epoch, ornullif the account has never been verified.- Requires the
profile:verified_atscope.
- Requires the
Here’s an example response:
{
"address": {
"formatted": "123 Main St Apt 123\nWashington, DC 20001",
"street_address": "123 Main St Apt 123",
"locality": "Washington",
"region": "DC",
"postal_code": "20001"
},
"birthdate": "1970-01-01",
"email": "test@example.com",
"email_verified": true,
"all_emails": ["test@example.com", "test2@example.com"],
"family_name": "Smith",
"given_name": "John",
"iss": "https://idp.int.identitysandbox.gov",
"phone": "+18881112222",
"phone_verified": true,
"social_security_number": "111223333",
"sub": "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca",
"verified_at": 1577854800
}
Certificates
Login.gov’s public key, used to verify signed JWTs (such as the id_token), is available in JWK format at the /api/openid_connect/certs endpoint. For example, the URL in the agency integration environment is at https://idp.int.identitysandbox.gov/api/openid_connect/certs
This public key is rotated periodically (on at least an annual basis). It is important to assume the /api/openid_connect/certs endpoint could contain multiple JWKs when rotating application signing keys. Be sure to use the JWK endpoint dynamically through auto-discovery rather than hardcoding the public key. This ensures that your application will not require manual intervention when the Login.gov public key is rotated.
Logout
Login.gov supports RP-Initiated Logout, allowing clients to log users out of their current Login.gov session and redirect them back to the Relying Party.
Login.gov does not support Single Logout (SLO). The logout action will terminate the user’s session at Login.gov but will not end any other potentially active sessions within service provider applications. For example, if a user signs in to applications A and B through Login.gov, a logout request from A will end their Login.gov session, but will not affect the session in application B.
Logout request
To log out a user, send them to the /openid_connect/logout endpoint with the following parameters:
-
client_id
The unique identifier for the client. This will be registered with the Login.gov IdP in advance. -
post_logout_redirect_uri
The URI Login.gov will redirect to after logout. This must also be registered with the Login.gov IdP in advance. -
state (optional)
A unique value at least 22 characters in length used for maintaining state between the request and the callback. This value will be returned to the client on a successful logout as a parameter ofstateadded to the redirect back to thepost_logout_redirect_uri.
Here’s an example logout request:
https://idp.int.identitysandbox.gov/openid_connect/logout?
client_id=${CLIENT_ID}&
post_logout_redirect_uri=${REDIRECT_URI}&
state=abcdefghijklmnopabcdefghijklmnop
Note that, as per the spec, Login.gov will display a Logout confirmation screen to users on logout; users will need to click a button to complete the logout process. This protects against forged logout request attacks. If the user does not click the button, they will not be redirected back to your application.
Logout response
In a successful logout, i.e. the request is valid and the user confirms that they want to log out, Login.gov will redirect the user to the provided post_logout_redirect_uri with the state parameter added to the URL. If the request is invalid, the user will be shown an error page. If the user declines to click the button on the confirmation page, they will not be redirected to the post_logout_redirect_uri and there will be no response to your application.
Here’s an example logout response:
https://agency.gov/response?
state=abcdefghijklmnopabcdefghijklmnop
Example application
The Login.gov team has created an example client to speed up your development, all open source in the public domain: identity-oidc-sinatra.