OAuth 2.0 & OpenID Connect
Optare is a standards-compliant OAuth 2.0 and OpenID Connect provider.
OAuth 2.0 Flows
Authorization Code Flow
The most secure flow for web applications.
// 1. Redirect to authorization endpoint
const authUrl = new URL('https://id.optare.one/oauth/authorize')
authUrl.searchParams.set('client_id', 'your-client-id')
authUrl.searchParams.set('redirect_uri', 'https://yourapp.com/callback')
authUrl.searchParams.set('response_type', 'code')
authUrl.searchParams.set('scope', 'openid profile email')
window.location.href = authUrl.toString()
// 2. Exchange code for tokens
const response = await fetch('https://id.optare.one/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'authorization_code',
code: 'authorization-code',
client_id: 'your-client-id',
client_secret: 'your-client-secret',
redirect_uri: 'https://yourapp.com/callback'
})
})
const { access_token, id_token, refresh_token } = await response.json()PKCE Flow
For mobile and single-page applications.
// 1. Generate code verifier and challenge
const codeVerifier = generateRandomString(128)
const codeChallenge = await sha256(codeVerifier)
// 2. Authorization request with PKCE
const authUrl = new URL('https://id.optare.one/oauth/authorize')
authUrl.searchParams.set('client_id', 'your-client-id')
authUrl.searchParams.set('redirect_uri', 'yourapp://callback')
authUrl.searchParams.set('response_type', 'code')
authUrl.searchParams.set('code_challenge', codeChallenge)
authUrl.searchParams.set('code_challenge_method', 'S256')
// 3. Token exchange with verifier
const response = await fetch('https://id.optare.one/oauth/token', {
method: 'POST',
body: JSON.stringify({
grant_type: 'authorization_code',
code: 'authorization-code',
client_id: 'your-client-id',
redirect_uri: 'yourapp://callback',
code_verifier: codeVerifier
})
})OpenID Connect
Get user information with OIDC.
UserInfo Endpoint
const response = await fetch('https://id.optare.one/oauth/userinfo', {
headers: {
'Authorization': `Bearer ${access_token}`
}
})
const userInfo = await response.json()
// { sub, name, email, picture, ... }ID Token
Decode the JWT ID token to get user claims.
import { jwtVerify } from 'jose'
const { payload } = await jwtVerify(
id_token,
publicKey,
{ issuer: 'https://id.optare.one' }
)
console.log(payload.sub) // User ID
console.log(payload.email) // User emailScopes
Request specific permissions:
openid- Required for OIDCprofile- User profile (name, picture)email- Email addressoffline_access- Refresh token
scope: 'openid profile email offline_access'Refresh Tokens
Get new access tokens without re-authentication.
const response = await fetch('https://id.optare.one/oauth/token', {
method: 'POST',
body: JSON.stringify({
grant_type: 'refresh_token',
refresh_token: 'your-refresh-token',
client_id: 'your-client-id',
client_secret: 'your-client-secret'
})
})
const { access_token } = await response.json()Discovery Endpoint
Get OAuth configuration automatically.
https://id.optare.one/.well-known/openid-configurationNext Steps
- API Keys - Server authentication
- Organizations - Multi-tenant setup
- Security - Security best practices