SIOPv2: Self-Issued OpenID Provider
Self-Issued OpenID Provider v2 (SIOPv2) enables decentralized authentication by allowing users to act as their own identity provider. Instead of relying on Google, Facebook, or enterprise identity providers, users authenticate using cryptographic keys they control.
Traditional vs Self-Issued Identity
Traditional OIDC
- Identity provider controls user data
- Provider can track user activity across sites
- Single point of failure/compromise
- Provider can deny access
SIOPv2
- User controls their own identity
- No central tracking possible
- Resilient to provider outages
- Portable across wallets and devices
Authentication Flow
SIOPv2 follows the standard OpenID Connect authorization code flow, but the wallet acts as both the identity provider and the user agent.
Example Authorization Request
// SIOPv2 Authorization Request
openid://?
scope=openid
&response_type=id_token
&client_id=https://rp.example.com
&redirect_uri=https://rp.example.com/callback
&response_mode=fragment
&nonce=n-0S6_WzA2Mj
®istration={
"subject_syntax_types_supported": ["did:key", "did:web"],
"id_token_signing_alg_values_supported": ["ES256", "EdDSA"]
}Self-Issued ID Token
The ID Token is a JWT signed by the user's private key. The relying party verifies the signature by resolving the DID to retrieve the public key.
ID Token Claims
| Property | Type | Required | Description |
|---|---|---|---|
| Required | Self-issued identifier (DID or https://self-issued.me/v2) | ||
| Required | Subject identifier (DID or JWK thumbprint) | ||
| Required | Relying party client_id | ||
| Required | Expiration time (short-lived, typically minutes) | ||
| Required | Issued at time | ||
| Required | Nonce from authorization request (replay prevention) | ||
| Optional | Public key for subject (if sub is JWK thumbprint) | ||
| Optional | Reference to VP Token in combined flow |
RequiredSelf-issued identifier (DID or https://self-issued.me/v2)
RequiredSubject identifier (DID or JWK thumbprint)
RequiredRelying party client_id
RequiredExpiration time (short-lived, typically minutes)
RequiredIssued at time
RequiredNonce from authorization request (replay prevention)
OptionalPublic key for subject (if sub is JWK thumbprint)
OptionalReference to VP Token in combined flow
Subject Identifier Types
| Property | Type | Required | Description |
|---|---|---|---|
| DID | Optional | Decentralized identifier resolved to DID document | |
| JWK Thumbprint | Optional | Hash of public key (ephemeral identity) | |
| Self-Issued URL | Optional | Generic self-issued issuer (legacy) |
OptionalDIDDecentralized identifier resolved to DID document
OptionalJWK ThumbprintHash of public key (ephemeral identity)
OptionalSelf-Issued URLGeneric self-issued issuer (legacy)
Example ID Token
// Self-Issued ID Token (decoded)
{
"iss": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"sub": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"aud": "https://rp.example.com",
"nonce": "n-0S6_WzA2Mj",
"iat": 1704067200,
"exp": 1704067500,
"auth_time": 1704067200
}
// Header
{
"alg": "EdDSA",
"typ": "JWT",
"kid": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
}Combined SIOPv2 + OID4VP
SIOPv2 and OID4VP can be combined in a single request to achieve both authentication (proving identity) and authorization (presenting credentials). This is common in scenarios requiring verified attributes.
Holder Binding
The combined flow enables holder binding verification: the relying party can confirm that the same entity (DID) that authenticated via SIOPv2 is the legitimate holder of the presented credentials.
Combined Request
// Combined SIOPv2 + OID4VP Request
openid4vp://?
scope=openid
&response_type=id_token vp_token
&client_id=https://rp.example.com
&response_mode=direct_post
&response_uri=https://rp.example.com/callback
&nonce=n-0S6_WzA2Mj
&presentation_definition={
"id": "age-verification",
"input_descriptors": [{
"id": "age_cred",
"constraints": {
"fields": [{
"path": ["$.credentialSubject.ageOver21"]
}]
}
}]
}
®istration={
"subject_syntax_types_supported": ["did:key"]
}Combined Response
// Combined Response
POST /callback HTTP/1.1
Content-Type: application/x-www-form-urlencoded
id_token=eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...
&vp_token=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...
&presentation_submission={
"id": "submission-1",
"definition_id": "age-verification",
"descriptor_map": [{
"id": "age_cred",
"format": "jwt_vp_json",
"path": "$"
}]
}DID Methods for SIOPv2
Different DID methods offer different tradeoffs for self-issued identity:
did:key
Self-certifying, no resolution needed. Public key encoded directly in DID. Ideal for ephemeral or privacy-preserving identities.
did:web
DID document hosted at web domain. Good for organizations with established web presence. Easy verification via HTTPS.
did:ion / did:ethr
Blockchain-anchored DIDs. Provides decentralized key rotation and recovery. Higher assurance for long-lived identities.
Security Considerations
ID Token Security
Relying Party Security
Privacy Considerations
Use Cases
Passwordless Login
Web3 Applications
Users authenticate to web applications using their wallet's DID, eliminating passwords and centralized identity providers.
Age-Verified Access
Entertainment Venues
Combined SIOPv2 + OID4VP for venues requiring both identity verification and proof of age from a trusted credential.