OpenID Connect (OIDC)
Integrate with Propper's OpenID Connect implementation for user authentication.
Discovery Document
The OIDC discovery document contains all endpoints and capabilities:
curl "https://auth.propper.ai/.well-known/openid-configuration"
Response:
{
"issuer": "https://auth.propper.ai",
"authorization_endpoint": "https://auth.propper.ai/oauth2/authorize",
"token_endpoint": "https://auth.propper.ai/oauth2/token",
"userinfo_endpoint": "https://auth.propper.ai/oauth2/userinfo",
"jwks_uri": "https://auth.propper.ai/.well-known/jwks.json",
"scopes_supported": ["openid", "profile", "email"],
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "client_credentials", "refresh_token"],
"code_challenge_methods_supported": ["S256"]
}
ID Tokens
When requesting the openid scope, you receive an ID token containing user identity claims.
Requesting an ID Token
Include openid in your scope:
https://auth.propper.ai/oauth2/authorize?
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://yourapp.com/callback&
scope=openid profile email&
state=random_state&
code_challenge=YOUR_CHALLENGE&
code_challenge_method=S256
ID Token Claims
{
"iss": "https://auth.propper.ai",
"sub": "user_123",
"aud": "your_client_id",
"exp": 1704067200,
"iat": 1704063600,
"nonce": "your_nonce_value",
"email": "user@example.com",
"name": "John Doe"
}
| Claim | Scope Required | Description |
|---|---|---|
sub | openid | Unique user identifier |
email | email | User's email address |
name | profile | User's display name |
nonce | - | Echo of your nonce parameter |
UserInfo Endpoint
Retrieve additional user information using an access token:
curl "https://auth.propper.ai/oauth2/userinfo" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response:
{
"sub": "user_123",
"email": "user@example.com",
"name": "John Doe",
"roles": ["admin", "user"],
"scope": "openid profile email"
}
Nonce Parameter
Use the nonce parameter to prevent replay attacks:
- Generate a random nonce before authorization
- Include it in the authorization request
- Verify the nonce in the ID token matches
// Generate nonce
const nonce = generateRandomString(32);
sessionStorage.setItem('oidc_nonce', nonce);
// Include in authorization URL
const authUrl = `https://auth.propper.ai/oauth2/authorize?...&nonce=${nonce}`;
// After receiving ID token, verify nonce
const idToken = decodeJwt(response.id_token);
if (idToken.nonce !== sessionStorage.getItem('oidc_nonce')) {
throw new Error('Nonce mismatch - possible replay attack');
}
Integrating with OIDC Libraries
Most OAuth/OIDC libraries can auto-configure using the discovery document.
JavaScript (oidc-client-ts)
import { UserManager } from 'oidc-client-ts';
const userManager = new UserManager({
authority: 'https://auth.propper.ai',
client_id: 'YOUR_CLIENT_ID',
redirect_uri: 'https://yourapp.com/callback',
scope: 'openid profile email sign:read',
});
// Start login
await userManager.signinRedirect();
// Handle callback
const user = await userManager.signinRedirectCallback();
console.log('User:', user.profile);
Python (authlib)
from authlib.integrations.requests_client import OAuth2Session
client = OAuth2Session(
client_id='YOUR_CLIENT_ID',
client_secret='YOUR_CLIENT_SECRET',
scope='openid profile email'
)
# Fetch discovery document
client.fetch_metadata('https://auth.propper.ai/.well-known/openid-configuration')
# Create authorization URL
uri, state = client.create_authorization_url(
'https://auth.propper.ai/oauth2/authorize'
)
.NET (Microsoft.AspNetCore.Authentication.OpenIdConnect)
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = "https://auth.propper.ai";
options.ClientId = "YOUR_CLIENT_ID";
options.ClientSecret = "YOUR_CLIENT_SECRET";
options.ResponseType = "code";
options.Scope.Add("profile");
options.Scope.Add("email");
});
Session Management
Checking Session Status
Your application should periodically verify the user's session is still valid:
- Check if the access token is expired
- Attempt to refresh using the refresh token
- If refresh fails, redirect to login
Logout
To properly log out:
- Revoke the refresh token
- Clear local session data
- Optionally redirect to the authorization server's logout endpoint
async function logout() {
// Revoke refresh token
await fetch('https://auth.propper.ai/oauth2/revoke', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `token=${refreshToken}&token_type_hint=refresh_token`
});
// Clear local storage
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
// Redirect to login
window.location.href = '/login';
}