Internet-Draft | IDA Profile for OIDC | July 2025 |
Bermon & Parecki | Expires 8 January 2026 | [Page] |
This document defines an Identity Assurance Profile for OpenID Connect that establishes security requirements and best practices for a relying party to generate an identity verification request and receive identity assurance from an OpenID provider.¶
The profile builds upon OpenID Connect Core 1.0 and specifies additional constraints, mandatory features, and security considerations necessary for identity assurance use cases where verified identity attributes are required. This specification leverages OpenID Connect for Identity Assurance (OIDC4IA) mechanisms to enable standardized communication of identity verification requirements and assurance levels between relying parties and identity providers. An extension to the Verified Claims to support fuzzy matching of verified claims is also defined to accommodate minor discrepancies in user-provided data.¶
This note is to be removed before publishing as an RFC.¶
The latest revision of this draft can be found at https://oktadev.github.io/openid-ida-oidc-security-profile/draft-openid-ida-security-profile.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-openid-ida-security-profile/.¶
Discussion of this document takes place on the eKYC-IDA Working Group mailing list (mailto:openid-specs-ekyc-ida@lists.openid.net), which is archived at https://openid.net/wg/ekyc-ida/.¶
Source for this draft and an issue tracker can be found at https://github.com/oktadev/openid-ida-oidc-security-profile.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 8 January 2026.¶
Copyright (c) 2025 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document.¶
In today's digital ecosystem, organizations increasingly rely on third-party identity verification providers to establish trust and comply with regulatory requirements. However, the broad integration requirements for identity verification providers have created significant challenges for both relying parties and identity providers. Each provider often implements proprietary interfaces, varying data formats, and inconsistent assurance level indicators, leading to complex integration efforts and limited interoperability.¶
This specification defines an Identity Assurance Profile for OpenID Connect. The profile establishes common patterns for requesting identity verification services, communicating assurance requirements, and evaluating resulting identity assurance claims. It builds upon the OpenID Connect framework to enable integration across identity verification providers while maintaining security and privacy for identity assurance use cases.¶
The profile specification is intended to benefit both relying parties and identity providers by reducing integration complexity, improving interoperability, and establishing clear expectations for identity verification processes across different organizational boundaries and regulatory jurisdictions.¶
Relying Parties (RPs) require a standardized, interoperable way to request and receive verified identity information from OpenID Providers (OPs). In many regulated or high-assurance environments, RPs must ensure that user attributes—such as name, date of birth, or address—have been verified to a specific level of assurance and with acceptable evidence.¶
Through this profile, RPs can more easily obtain the verified identity information they need, with confidence in the assurance level and verification process, while minimizing integration overhead and improving interoperability.¶
Upon receiving a valid PAR request, the identity provider generates a unique request_uri
that:¶
References the stored authorization request parameters¶
Has a limited lifetime as specified in the PAR response¶
Can be used in subsequent authorization requests without exposing sensitive parameters in URL query strings¶
The use of PAR ensures that sensitive identity verification requirements are transmitted securely and are not exposed in browser history, server logs, or other potential information leakage vectors that could occur with traditional authorization request methods.¶
``` HTTP/1.1 201 Created Content-Type: application/json Cache-Control: no-cache, no-store¶
{ "request_uri": "urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c", "expires_in": 60 } ```¶
If during the PAR request and error occurs, then the error response should follow specification OAuth 2.0 Pushed Authorization Requests RFC 9126¶
For example if the PAR request cannot be completed due to an invalid or missing parameter, then the error response would result in:¶
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-cache, no-store
{
"error": "invalid_request",
"error_description":
"The redirect_uri is not valid for the given client"
}
¶
After the user completes the identity verification process at the OpenID Provider, the OP redirects the user back to the relying party's redirect_uri
with an authorization code. The relying party then exchanges this authorization code for an ID token that contains the results of the identity verification flow.¶
This token exchange represents the final phase of the identity verification profile, where the relying party receives the verified claims and assurance level information that was processed during the user's verification session with the OP.¶
The relying party makes a POST request to the OP's token endpoint to exchange the authorization code for tokens. The token request MUST include the following parameters:¶
grant_type
REQUIRED. MUST be set to authorization_code
.¶
code
REQUIRED. The authorization code received from the authorization endpoint callback.¶
client_id
REQUIRED. The client identifier registered with the OP.¶
client_secret
REQUIRED. The client secret associated with the client_id for client authentication.¶
redirect_uri
REQUIRED. MUST exactly match the redirect_uri used in the original PAR request.¶
code_verifier
REQUIRED if PKCE was used in the authorization request. The code verifier that corresponds to the code_challenge sent in the PAR request.¶
The relying party exchanges the authorization code for tokens containing the identity verification results:¶
``` POST /oauth/token HTTP/1.1 Host: idv-vendor.com Content-Type: application/x-www-form-urlencoded¶
grant_type=authorization_code &code=SplxlOBeZQQYbYS6WxSbIA &client_id=aB3kL9mQ &client_secret=xP8nM2kQ7sR4 &redirect_uri=https://relyingparty.com/idp/identity-verification/callback &code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk ```¶
The OP responds with an ID token that contains the results of the identity verification process. The ID token includes verified claims structured according to the OIDC4IA specification with the extensions defined in this profile:¶
``` HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-cache, no-store¶
{ "token_type": "Bearer", "expires_in": 3600, "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2lkdi12ZW5kb3IuY29tIiwic3ViIjoidXNlcl9LYThtTjJwUTN4UjciLCJhdWQiOiJhQjNrTDltUSIsImV4cCI6MTY0MjU1NzYwMCwiaWF0IjoxNjQyNTU0MDAwLCJub25jZSI6Im5vbmNlVmFsdWUiLCJ2ZXJpZmllZF9jbGFpbXMiOlt7InZlcmlmaWNhdGlvbiI6eyJ0cnVzdF9mcmFtZXdvcmsiOiJJRFYtREVMRUdBVEVEIiwiYXNzdXJhbmNlX2xldmVsIjoiVkVSSUZJRUQiLCJ2ZXJpZmljYXRpb25fcHJvY2VzcyI6IjEyMzQ1Njc4LWFiY2QtZWZnaC1oaWprLWxtbm9wcXJzdHV2dyIsInRpbWUiOiIyMDI0LTAxLTE1VDEwOjAwOjAwWiIsImV2aWRlbmNlIjpbeyJ0eXBlIjoiZG9jdW1lbnQiLCJtZXRob2QiOiJhdXRvbWF0ZWQiLCJkb2N1bWVudCI6eyJ0eXBlIjoiZHJpdmluZ19saWNlbnNlIiwiaXNzdWVyIjp7Im5hbWUiOiJDQSBETVYiLCJjb3VudHJ5IjoiVVMifX19XX0sImNsYWltcyI6eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiYmlydGhkYXRlIjoiMTk5Mi0wMS0wMSJ9fV19" } ```¶
The id_token
is a signed JWT (JSON Web Token) that contains the identity verification results. When decoded, the JWT payload reveals the complete structure of the verified claims and all required OpenID Connect attributes.¶
When the id_token
JWT is decoded and verified, the payload contains the following structure with all required attributes and verified claims results:¶
json
{
"iss": "https://idv-vendor.com",
"sub": "user_Ka8mN2pQ3xR7",
"aud": "aB3kL9mQ",
"exp": 1642557600,
"iat": 1642554000,
"auth_time": 1642553800,
"nonce": "nonceValue",
"acr": "urn:mace:incommon:iap:silver",
"amr": ["pwd", "otp"],
"azp": "aB3kL9mQ",
"verified_claims": [
{
"verification": {
"trust_framework": "IDV_DELEGATED",
"assurance_level": "VERIFIED",
"verification_process": "12345678-abcd-efgh-hijk-lmnopqrstuvw",
"time": "2024-01-15T10:00:00Z",
"evidence": [
{
"type": "document",
"method": "automated",
"document": {
"type": "driving_license",
"issuer": {
"name": "CA DMV",
"country": "US"
},
"number": "D1234567",
"date_of_issuance": "2020-01-15",
"date_of_expiry": "2028-01-15"
}
}
]
},
"claims": {
"given_name": "John",
"family_name": "Doe",
"birthdate": "1992-01-01"
}
}
]
}
¶
The ID token contains verified claims with the following structure that reflects the results of the identity verification process:¶
verification: Contains metadata about the verification process including:¶
trust_framework
: Set to IDV_DELEGATED
indicating the verification was delegated¶
assurance_level
: Either VERIFIED
or FAILED
based on the verification outcome¶
verification_process
: Unique identifier for the verification session¶
time
: Timestamp when the verification was completed¶
evidence
: Array of evidence types used in the verification process¶
claims: Contains the verified identity attributes with their verified values, reflecting any fuzzy matching that was applied during the verification process¶
The relying party can parse this ID token to extract the verified claims and determine whether the identity verification was successful based on the assurance_level
value. This completes the identity verification flow, providing the relying party with the verified identity information needed for their use case.¶
When identity verification cannot be completed successfully, the OpenID Provider returns an ID token with assurance_level
set to FAILED
. In these cases, the verified_claims
structure must clearly indicate which claims could not be verified and provide appropriate failure information.¶
According to the OpenID Connect for Identity Assurance specification, unverified claims can be represented in two ways:¶
When verification fails, the decoded JWT payload would contain a null
value for the claim (or claims) that could not be verified:¶
json
{
"iss": "https://idv-vendor.com",
"sub": "user_Ka8mN2pQ3xR7",
"aud": "aB3kL9mQ",
"exp": 1642557600,
"iat": 1642554000,
"auth_time": 1642553800,
"nonce": "nonceValue",
"verified_claims": [
{
"verification": {
"trust_framework": "IDV_DELEGATED",
"assurance_level": "FAILED",
"verification_process": "12345678-abcd-efgh-hijk-lmnopqrstuvw",
"time": "2024-01-15T10:00:00Z",
"evidence": [
{
"type": "document",
"method": "automated",
"document": {
"type": "driving_license",
"issuer": {
"name": "CA DMV",
"country": "US"
}
}
}
]
},
"claims": {
"given_name": "John",
"family_name": "Doe",
"birthdate": null
}
}
]
}
¶
Alternatively, with omission approach, exclude the claim (or claims) that could not be verified¶
json
{
"iss": "https://idv-vendor.com",
"sub": "user_Ka8mN2pQ3xR7",
"aud": "aB3kL9mQ",
"exp": 1642557600,
"iat": 1642554000,
"auth_time": 1642553800,
"nonce": "nonceValue",
"verified_claims": [
{
"verification": {
"trust_framework": "IDV_DELEGATED",
"assurance_level": "FAILED",
"verification_process": "12345678-abcd-efgh-hijk-lmnopqrstuvw",
"time": "2024-01-15T10:00:00Z",
"evidence": [
{
"type": "document",
"method": "automated",
"document": {
"type": "driving_license",
"issuer": {
"name": "CA DMV",
"country": "US"
}
}
}
]
},
"claims": {}
}
]
}
¶
When processing failed verification results, relying parties should:¶
Check assurance_level: Always verify that assurance_level
is FAILED
¶
Handle missing claims: Be prepared to handle both null values and omitted claims¶
Examine evidence: Review the evidence object to understand what verification was attempted¶
Process verification_process: Use the verification process ID for audit trails and debugging¶
Implement fallback logic: Have appropriate fallback mechanisms for cases where verification cannot be completed¶
The presence of evidence information even in failed cases allows relying parties to understand what verification methods were attempted and can inform decisions about retry strategies or alternative verification approaches.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
TODO Security¶
This document has no IANA actions.¶
TODO acknowledge.¶