OIDC Claims Distribution — Distributed and Aggregated Claims Explained
In this tutorial, you will learn about OIDC Claims Distribution. We cover key concepts, practical examples, and best practices to help you master this topic.
Distributed and aggregated claims in Openid Connect allow an identity provider to include claims sourced from external services, enabling scenarios where user attributes are spread across multiple trusted providers.
What You'll Learn
- What distributed claims are and when to use them
- What aggregated claims are and how they differ from distributed
- How to resolve external claim sources securely
Why It Matters
User attributes often come from multiple sources. A primary identity provider knows your email and name, but a partner service knows your shipping address or subscription level. OIDC claims distribution lets providers include these external attributes in a single OIDC response without the user logging into each service separately.
Real-World Use
DodaTech employees authenticate via the corporate OIDC provider (Azure AD). The provider includes an aggregated claim for the employee's security clearance level from a separate HR system. Instead of fetching clearance data separately, the ID token contains it directly through claims aggregation.
flowchart LR
A["OIDC Provider"] -->|"Claims include\n_source or _claim_sources"| B["Your App"]
C["External Service 1"] -->|"Distributed Claims"| A
D["External Service 2"] -->|"Aggregated Claims"| A
style A fill:#dbeafe,stroke:#2563eb
style C fill:#fef3c7,stroke:#d97706
style D fill:#bbf7d0,stroke:#16a34a
Distributed Claims
Distributed claims reference an external endpoint that returns the claim value. The ID token includes a _claim_names and _claim_sources structure pointing to the external source:
{
"sub": "user123",
"name": "Jane Doe",
"_claim_names": {
"shipping_address": "src1",
"loyalty_tier": "src2"
},
"_claim_sources": {
"src1": {
"endpoint": "https://shipping.example.com/claims/jane",
"access_token": "eyJhbGci..."
},
"src2": {
"endpoint": "https://loyalty.example.com/tier/jane",
"access_token": "eyJhbGci..."
}
}
}
Aggregated Claims
Aggregated claims embed a complete JWT from an external source directly in the _claim_sources field. The external claims are pre-packaged as a signed JWT that your application can verify independently:
{
"sub": "user123",
"name": "Jane Doe",
"_claim_names": {
"hr_data": "src_hr"
},
"_claim_sources": {
"src_hr": {
"JWT": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwiZGVwYXJ0bWVudCI6IkVuZ2luZWVyaW5nIiwicm9sZSI6IkFkbWluIiwiaXNzIjoiaHJAc3lzdGVtLmV4YW1wbGUuY29tIn0.signature"
}
}
}
Resolving Distributed Claims
import requests
import jwt
def resolve_distributed_claims(token_payload):
claims_to_resolve = token_payload.get("_claim_names", {})
claim_sources = token_payload.get("_claim_sources", {})
resolved = {}
for claim_name, source_key in claims_to_resolve.items():
source = claim_sources.get(source_key)
if not source:
continue
endpoint = source.get("endpoint")
access_token = source.get("access_token")
if not endpoint:
continue
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {access_token}"}
)
if response.status_code == 200:
resolved[claim_name] = response.json()
return resolved
Verifying Aggregated Claims
import jwt
import requests
def verify_aggregated_claim(aggregated_jwt, trusted_issuer):
# Fetch the external provider's JWKS
jwks_uri = f"{trusted_issuer}/.well-known/jwks.json"
jwks = requests.get(jwks_uri).json()
header = jwt.get_unverified_header(aggregated_jwt)
key = next(k for k in jwks["keys"] if k["kid"] == header["kid"])
payload = jwt.decode(
aggregated_jwt,
key,
algorithms=["RS256"],
issuer=trusted_issuer
)
return payload
Common Mistakes
1. Not Verifying External JWT Signatures
Aggregated claims come as signed JWTs. Always verify the signature against the external provider's JWKS, not the main provider's keys.
2. Trusting Distributed Claims Without Access Token Validation
Distributed claim endpoints require an access token. Verify this token has the correct scope before accepting the claims.
3. Cacheing Claims Indefinitely
Distributed and aggregated claims can change. Implement TTL-based Caching and re-fetch when stale.
4. Ignoring the Source JWT Issuer
When resolving aggregated claims, always check the iss field matches the expected external provider. An attacker could embed a JWT from an untrusted source.
5. Mixing Distributed and Aggregated Access Tokens
Distributed claims use access tokens for the external endpoint. These are different from the main OIDC access token. Do not reuse them.
Practice Questions
- What is the difference between distributed and aggregated claims?
- How does the
_claim_namesfield work? - Why would you use aggregated claims instead of distributed?
- How do you verify an aggregated claim JWT?
- What security checks are needed for distributed claims?
Answers
- Distributed claims reference an external endpoint; aggregated claims embed a signed JWT. 2. It maps claim names to source keys in
_claim_sources. 3. Aggregated claims work offline since the JWT is self-contained. 4. Verify the JWT signature against the external provider's JWKS. 5. Validate the access token and endpoint URL.
Challenge
Build a claims resolver that takes an ID token payload with both distributed and aggregated claims, fetches and verifies each source, merges them into a flat claims dictionary, and caches results with a configurable TTL.
FAQ
Mini Project
Build a claims distribution server that acts as an external claim source for an OIDC provider. The server should accept access tokens, return claims in the distributed format, sign aggregated claim JWTs for offline verification, and include proper error responses.
What's Next
- Explore pairwise identifiers for anonymous yet consistent user identification
- Learn about dynamic client registration for automated provider setup
- Continue to OIDC client types for web, mobile, and SPA applications
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro