Secure Response Types
This guide explains how to integrate with our OIDC UserInfo encryption and signatures, including how to create and provide a JSON Web Key (JWK) for encrypting responses to your application
1. Decide your delivery format
JSON (default): Plain JSON payload. No keys required.
JWS (RS256): Signed JWT. No client key required. Contact us to enable.
JWS then JWE: Signed then encrypted JWT. Requires your RSA public JWK so we can encrypt to you.
Work with your account team to set userinfo_delivery to your desired value. For JWE, you must provide a JWK as described below.
2. Generate an RSA keypair
You can use OpenSSL locally. We recommend 2048-bit RSA for production.
# Generate a private key (unencrypted PEM) openssl genrsa -out rp-private.pem 2048 # Extract the public key (PEM) openssl rsa -in rp-private.pem -pubout -out rp-public.pem
Keep rp-private.pem secret. You will only share the PUBLIC components via a JWK.
3. Create a JWK from your public key
A minimal RSA public JWK requires the base64url-encoded modulus n and exponent e.
- Extract raw RSA parameters:
# Print the public key details openssl rsa -in rp-private.pem -pubout | openssl pkey -pubin -text -noout
Alternatively, you can use libraries to produce JWK directly (recommended in code). Below is the required structure we accept for encryption:
{
"kty": "RSA",
"use": "enc",
"alg": "RSA-OAEP-256",
"kid": "<your-key-id>",
"n": "<base64url-modulus>",
"e": "<base64url-exponent>"
}
Notes:
kty: must be "RSA"
use: set to "enc" (used for encryption)
alg: set to "RSA-OAEP-256" (what we use for JWE key management)
kid: a stable identifier you choose; must be URL-safe. We use this to pick the correct key when you rotate keys.
n/e: base64url-encoded (no padding) big-endian unsigned integers. Ensure you strip any leading 0x00 byte before encoding.
Example JWK
{
"kty": "RSA",
"use": "enc",
"alg": "RSA-OAEP-256",
"kid": "my-key-2025-08-01",
"n": "s7w4V4...",
"e": "AQAB"
}
4. Provide your JWK to us
You have two options:
- Host a JWKS endpoint we can fetch, containing your public keys:
{
"keys": [
{
"kty": "RSA",
"use": "enc",
"alg": "RSA-OAEP-256",
"kid": "my-key-2025-08-01",
"n": "...",
"e": "AQAB"
}
]
}
Provide the HTTPS URL to your account team.
- Or send the single public JWK to us via a secure channel. We will provision it for your client.
5. Request encrypted UserInfo
Ensure your client configuration has
userinfo_deliveryset tojws_then_jwe.Call the UserInfo endpoint as normal with your access token.
We will:
Build a signed JWT (RS256)
Encrypt it to your JWK using RSA-OAEP-256 + A256GCM
Return a compact JWE string with content-type
application/jwe
6. Decrypting the response
Use a JOSE/JWT library that supports JWE (RSA-OAEP-256 / A256GCM). Configure it with your private key (rp-private.pem). After decryption, you’ll receive a nested JWS (RS256) which you can optionally verify against our public signing keys.
7. Key rotation
Publish a new JWK with a new
kid.Notify us (or update your JWKS) before rotating out the old key.
We will select the most recent active key by
kid.
8. Common pitfalls
Missing or truncated JWK: ensure the JSON you provide is complete and not cut off. If sending through systems with field limits, use a TEXT/JSON-capable field.
Wrong encoding for
n/e: must be base64url (no padding). Remove any leading 0x00 before encoding.Algorithm mismatch:
algshould beRSA-OAEP-256for encryption.No
kid: always include a stable, URL-safekidfor rotation.
9. Validation checklist
JWK validates in your JOSE library (constructing a JWK/JWKS object should succeed)
JWKS endpoint is HTTPS and returns valid JSON with
keys: []You can decrypt a sample JWE using your private key
10. Need help?
Contact your integration engineer with your JWKS URL or sample JWK. Include your desired kid and confirm your userinfo_delivery mode.