Open ID Connect (OIDC)
This document is an quick overview of the OpenID Connect protocol. It is not an integration guide, and using an already implemented client is already recomended.
1. Introduction
What is OpenID Connect (OIDC)?
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients1 (Relying Parties or RPs) to verify the identity of the End-User based on the authentication performed by an Authorization Server (this Identity Provider or IDP), as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
OIDC uses JSON Web Tokens (JWTs), specifically the ID Token, to convey identity information in a secure and verifiable way.
Purpose of this Document
This document provides technical guidance for developers and administrators who need to integrate their applications (Relying Parties) with Gataca Vouch using the OpenID Connect protocol and want to understand the protocol. It is meant to explain the different supported flows by this standard and the configuration options to design the most adequate integration for your use case.
It is not an integration guide, and using an already-implemented client is already recomended.
Target Audience
Application Developers integrating with Gataca Vouch,
System Administrators managing applications that rely on Gataca Vouch.
Administrators responsible for operating and maintaining Gataca Vouch.
Security professionals reviewing integrations.
Key Terminology
IDP (Identity Provider): This service, [Your IDP Name]. Authenticates users and provides identity information to RPs.
RP (Relying Party): Your application that requires user authentication and relies on the IDP.
End-User: The human user who wants to log in to the RP.
Authorization Server: The role the IDP plays in the OAuth2/OIDC context.
Client: The RP registered with the IDP.
ID Token: A JWT containing claims about the authentication event and the End-User.
Access Token: A token granting access to protected resources (like the UserInfo endpoint).
Refresh Token: A token used to obtain new Access Tokens and potentially new ID Tokens without re-authenticating the End-User.
Claims: Pieces of information asserted about an entity (e.g., the End-User's email).
Scopes: Define the permissions/data requested by the RP (e.g., openid, profile).
Endpoints: Specific URLs on the IDP used during the OIDC flow (e.g., Authorization, Token).
JWK (JSON Web Key): A JSON data structure representing a cryptographic key.
JWKS (JSON Web Key Set): A JSON data structure containing a set of JWKs. Used by RPs to get public keys for verifying ID Token signatures.
2. OIDC Protocol Details
OIDC Discovery
Discovery Endpoint (/.well-known/openid-configuration)
Gataca Vouch supports OIDC Discovery via a standard metadata endpoint. This allows RPs to automatically configure themselves.
Discovery URL: https://vouch.gataca.io/.well-known/openid-configuration
Content: This URL returns a JSON document listing endpoints, supported scopes, claims, signing algorithms, etc. RPs SHOULD use this endpoint for configuration where possible.
Supported OIDC Flows
Authorization Code Flow: (Recommended for Web Apps) Provides the best security by transmitting tokens directly from the IDP to the RP backend, not through the browser. Requires a client_secret or other client authentication method for confidential clients.
Authorization Code Flow + PKCE: (Recommended for SPAs and Native Apps) An extension to the Authorization Code flow that adds protection against authorization code interception attacks. Mandatory for public clients (which cannot keep a secret). Highly recommended even for confidential clients.
Implicit Flow: Supported, thought its use is strongly discouraged due to security risks like token leakage via browser history. It was designed to support full SPA applications where no credentials can be safely stored in the application code; alternatively relying on the possession of the domain for the browser redirections. The usage of authorization code flow + pkce is recommended instead.
Hybrid Flow: it combines aspects of the Implicit Flow and the Authorization Code Flow. It is meant to be used by Web Apps with SPAs, retrieving inmediately the user information in front and a more secure token on the backend. It deals with the same security risks as the implicit flow. The usage of authorization code flow + pkce is recommended instead.
Client Credentials Grant: Used for machine-to-machine (M2M) communication where no end-user is involved.
Endpoints
Discovery Document
Used for automatic OIDC discovery by OIDC clients
Authorization
Used to redirect the End-User for authentication and consent.
Token
Used by the RP to exchange an authorization code (or refresh token) for tokens. Requires authentication for confidential clients.
User Info
Protected resource that returns claims about the authenticated End-User when presented with a valid Access Token.
JWKS (public keys)
Provides the IDP's public keys (in JWK Set format) used to verify the signature of ID Tokens.
End Session Endpoint
Used for RP-initiated logout.
Scopes & Claims
Tokens
ID Token:
Format: Signed JWT.
Signing Algorithms: [List supported JWS algorithms, e.g., RS256, ES256. RS256 is RECOMMENDED]. RPs MUST verify the signature using keys from the JWKS URI.
Purpose: Carries identity information about the user and authentication event. Intended for the RP (Client).
Key Claims: iss, sub, aud, exp, iat, auth_time, nonce.
Access Token:
Format: [Specify format: JWT or Opaque String]. If JWT, specify signing algorithm and structure. If opaque, RPs cannot introspect it and must treat it as a string to be sent to resource servers (like the UserInfo endpoint).
Lifetime: [Specify the typical lifetime, e.g., 15 minutes, 1 hour]. Should be relatively short.
Purpose: Authorizes access to protected resources (e.g., UserInfo endpoint, potentially other APIs). Intended for the Resource Server.
Refresh Token:
Availability: [Specify if refresh tokens are issued, under what conditions (e.g., requires offline_access scope, only for confidential clients)].
Usage: Exchanged at the Token Endpoint for new Access Tokens (and potentially ID Tokens) without user interaction.
Lifetime: [Specify lifetime, e.g., 30 days, 90 days, until revoked]. Typically much longer than Access Tokens.
Security: Must be stored securely by the RP. May be one-time use or rotating. [Specify rotation behavior].
3. Integration Guide for Relying Parties (RPs)
This section expands on Getting Started and Gataca Vouch Integration with more detail
Client Registration In-Depth
Client Types:
Confidential: Clients capable of maintaining the confidentiality of their credentials (e.g., traditional web applications running on a server). Can use client_secret or other secure authentication methods at the token endpoint.
Public: Clients incapable of maintaining credential confidentiality (e.g., Single-Page Apps running in a browser, native mobile apps). MUST use PKCE. Cannot use client secrets.
Redirect URIs: Crucial for security. The IDP will only redirect users back to pre-registered URIs.
Must use HTTPS. [Specify if http://localhost is allowed for development].
Exact match is preferred. [Specify if wildcards or path-based validation are supported and the rules]. Multiple URIs can usually be registered.
Response Types: Defines the OIDC flow.
code: For Authorization Code Flow.
token, id_token, code token, code id_token, code id_token token: [If other flows like Implicit/Hybrid are supported].
Grant Types: Defines how the client exchanges credentials/codes for tokens.
authorization_code: Used with response_type=code.
refresh_token: Used to get new tokens using a refresh token.
client_credentials: [If supported for M2M].
Initiating Authentication (/authorize Request)
Construct a URL and redirect the user's browser to the Authorization Endpoint.
Method: GET
Parameters (Query String):
client_id: (Required) Your application's client ID.
redirect_uri: (Required) Must match one of the registered redirect URIs for this client.
scope: (Required) Include openid plus any other scopes needed (e.g., openid profile email). Space-separated.
response_type: (Required) e.g., code.
state: (Required) Opaque value used to maintain state between the request and callback. Helps prevent CSRF. The RP must generate a unique value and verify it matches upon callback.
nonce: (Required for Implicit/Hybrid flows returning ID Token in front-channel, Recommended for Auth Code flow) String value used to associate a Client session with an ID Token and mitigate replay attacks. Must be unique per request. The RP must generate it and verify it in the received ID Token.
prompt: (Optional) none (try to authenticate without interaction), login (force re-login), consent (force consent screen), select_account (allow user to choose account if multiple are logged in).
code_challenge: (Required if using PKCE) The code challenge derived from the code_verifier.
code_challenge_method: (Required if using PKCE) S256 (recommended) or plain (discouraged).
Handling the Authentication Response
The IDP redirects the user back to the specified redirect_uri.
Successful Response: The redirect URI will include parameters in the query string:
code: The authorization code (if response_type=code). Short-lived, single-use.
state: The value the RP sent in the initial request. The RP MUST verify this matches the original value.
Error Response: The redirect URI will include error parameters:
error: e.g., access_denied, invalid_request.
error_description: More details.
state: The original state value.
Exchanging the Code for Tokens (/token Request)
Make a POST request directly from the RP backend to the Token Endpoint. Never do this from the user's browser.
Method: POST
Headers:
Content-Type: application/x-www-form-urlencoded
Authorization: Basic Base64Encode(client_id:client_secret)
Body (x-www-form-urlencoded):
grant_type=authorization_code
code: The authorization code received from the /authorize response.
redirect_uri: The same redirect URI used in the initial /authorize request.
client_id: Required if client is not authenticating using the Authorization header (e.g., public clients).
client_secret: Required if using client_secret_post authentication method.
code_verifier: (Required if PKCE was used in the /authorize request) The original plain text code verifier.
Successful Response: 200 OK with JSON body:
Error Response: 4xx status code with JSON body:
Validating Tokens
This is a critical security step. Use a reliable OIDC/JWT library.
ID Token Validation:
(If encrypted) Decrypt the ID Token using the RP's private key.
Parse the JWT: Decode the header and payload. Do not trust payload claims yet.
Verify Signature:
Get the Key ID (kid) from the ID Token header.
Fetch the IDP's public keys from the JWKS URI ([Your JWKS URI]). Cache these keys based on HTTP caching headers but be prepared to refresh if a kid is not found.
Find the key in the JWKS matching the kid.
Using the public key and the algorithm specified in the header (alg), verify the signature against the signed content of the ID Token. Reject if verification fails.
Verify Standard Claims:
iss (Issuer): Must exactly match the IDP's Issuer identifier ([Your IDP Issuer URL]).
aud (Audience): Must contain your client_id. Can be an array or string.
exp (Expiration Time): Must be in the future (account for minor clock skew).
iat (Issued At): [Optional check] Should be in the past (account for clock skew).
nonce: (If nonce was sent in /authorize request) Must exactly match the nonce value sent. Reject if mismatch.
Only after all checks pass, trust the claims in the ID Token (especially sub).
Access Token Validation:
The Access Token is an Opaque String, the RP cannot validate it directly. It can only use it at the UserInfo endpoint and the resource server validates it.
Retrieving User Information (/userinfo Endpoint)
Method: GET
Authentication: Provide the Access Token in the Authorization header:
Authorization: Bearer [The Access Token]
Response: 200 OK with a JSON body containing user claims authorized by the scopes associated with the Access Token. The sub claim here MUST match the sub claim in the ID Token.
Handling Refresh Tokens
Storage: Store Refresh Tokens securely (e.g., encrypted database) as they allow long-term access.
Usage: When the Access Token expires, make a POST request to the Token Endpoint:
grant_type=refresh_token
refresh_token: The stored refresh token.
scope: (Optional) Request specific scopes (subset of originally granted).
client_id & Client Authentication (as required for the client type).
Response: Similar to the code exchange response, containing a new Access Token (and potentially a new ID Token and Refresh Token - check IDP's rotation policy).
Revocation: [Mention if refresh tokens can be revoked and how, e.g., via user action, admin action, or if they expire].
Logout / Ending the Session
Local Logout: The RP must clear its own application session for the user.
RP-Initiated Logout (via end_session_endpoint):
Redirect the user's browser to.
Parameters:
id_token_hint: (Recommended) The original ID Token received for the user. Helps IDP identify the session.
post_logout_redirect_uri: (Optional) URL to redirect the user back to after logout. Must be pre-registered with the client.
state: (Optional) RP state value to be included in the redirect back.
Result: User is logged out of the IDP session.
Single Logout (SLO): This is complex and requires careful implementation by RPs.
4. Security Considerations
HTTPS is Mandatory: All communication with IDP endpoints MUST use TLS (HTTPS).
State Parameter: Always use and validate the state parameter in the Authorization Code flow to prevent CSRF.
Nonce Parameter: Always use and validate the nonce parameter when receiving an ID Token to prevent replay attacks.
PKCE: Use PKCE (S256 method preferred) for all client types, especially public clients where it's mandatory.
Client Secret Security: Confidential clients MUST protect their client_secret. Do not embed it in client-side code. Use secure backend storage and consider private_key_jwt for higher security if supported.
Token Lifetimes: Keep Access Token lifetimes short. Balance Refresh Token lifetime with security and user experience.
ID Token Signing: Use strong asymmetric algorithms like RS256. Verify signatures diligently.
Key Rotation: Your IDP rotates signing keys periodically. RPs MUST fetch keys from the JWKS URI and handle unknown kid values by refreshing the JWKS data.
Audience Validation: Always ensure the aud claim in the ID Token contains your client_id.
Redirect URI Security: Use specific, HTTPS redirect URIs. Avoid overly broad wildcards.
IDP Security Features: For all wallet dependent scopes, user authentication relies on all the strong SSI authentication mechanisms described in this documentation, including but not only: passwordless authentication, wallet source authentication, credential integrity, credential issuer validation, or holder identity binding through biometrics.
5. User Experience
Consent Screen: Explain when users are prompted to grant consent for requested scopes/claims.
There are 2 templates of the consent screen, the most common one for all the scopes and a specific one if age estimation scopes are required.
Login Page: There is no login screen. There are no IDP accounts stored. The user is a user since he has an id wallet. All login would be performed in his wallet.
Account Recovery: There are no IDP's accounts, the user manage his information in his wallet. Account recovery would depend on the wallet recovery protocol set by his provider.
MFA/2FA: Strong biometric authentication is required on the wallet for signing operations.
6. API Reference
7. Troubleshooting & FAQs
Common Integration Issues:
Redirect URI Mismatch: Ensure the redirect_uri in requests exactly matches a registered one.
Invalid Grant (Token Endpoint): Code expired, already used, PKCE code_verifier incorrect, client authentication failed.
Signature Validation Failed: Clock skew too large, incorrect public key used (ensure JWKS URI is correct and keys refreshed).
Nonce Mismatch: Ensure nonce validation logic is correct.
.
FAQs:
Q: How long are authorization codes valid?
A: 10 minutes
Q: How often should I refresh JWKS keys?
A: Respect HTTP caching headers, but refresh immediately if signature validation fails for an unknown kid.
Q: Can I configure a localhost domain for development?
A: Yes
Q: Can I use HTTP for localhost development?
A: Yes
8. Support and Contact Information
Email: support@gataca.io
Sources
Last updated