Appearance
Quick Reference
Essential Information
Base URLs
- Production:
https://engagifii-identity-live.azurewebsites.net - QA/Staging:
https://engagifii-qa-identity.azurewebsites.net - Development:
https://engagifii-dev-identity.azurewebsites.net
Key Endpoints
Authorization: /connect/authorize
Token: /connect/token
UserInfo: /connect/userinfo
Logout: /connect/endsession
Discovery: /.well-known/openid-configuration
JWKS: /.well-known/openid-configuration/jwksCommon Scopes
openid- OpenID Connect identityprofile- User profile informationemail- Email addressoffline_access- Refresh tokensapi- API access
Quick Start Examples
Web Application Login
javascript
// 1. Redirect to login
window.location.href =
'https://engagifii-identity-live.azurewebsites.net/connect/authorize?' +
'client_id=YOUR_CLIENT_ID&' +
'response_type=code&' +
'redirect_uri=https://yourapp.com/callback&' +
'scope=openid profile email';
// 2. Handle callback and exchange code
const code = new URLSearchParams(window.location.search).get('code');
const tokenResponse = await fetch('https://engagifii-identity-live.azurewebsites.net/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
redirect_uri: 'https://yourapp.com/callback',
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET'
})
});
const tokens = await tokenResponse.json();Service-to-Service Authentication
javascript
// Get access token for API calls
const response = await fetch('https://engagifii-identity-live.azurewebsites.net/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: 'SERVICE_CLIENT_ID',
client_secret: 'SERVICE_CLIENT_SECRET',
scope: 'api.read api.write'
})
});
const { access_token } = await response.json();SPA with PKCE
javascript
// Generate PKCE challenge
const codeVerifier = generateRandomString(128);
const codeChallenge = await sha256(codeVerifier);
// 1. Authorization request
window.location.href =
'https://engagifii-identity-live.azurewebsites.net/connect/authorize?' +
'client_id=SPA_CLIENT_ID&' +
'response_type=code&' +
'redirect_uri=https://spa.com/callback&' +
'scope=openid profile api&' +
'code_challenge=' + codeChallenge + '&' +
'code_challenge_method=S256';
// 2. Token exchange (no client secret)
const tokens = await fetch('https://engagifii-identity-live.azurewebsites.net/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: authCode,
redirect_uri: 'https://spa.com/callback',
client_id: 'SPA_CLIENT_ID',
code_verifier: codeVerifier
})
});Common Operations
Get User Information
javascript
const userInfo = await fetch('https://engagifii-identity-live.azurewebsites.net/connect/userinfo', {
headers: {
'Authorization': `Bearer ${access_token}`
}
});
const user = await userInfo.json();
// Returns: { sub, name, email, ... }Refresh Access Token
javascript
const response = await fetch('https://engagifii-identity-live.azurewebsites.net/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: 'YOUR_REFRESH_TOKEN',
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET'
})
});
const newTokens = await response.json();Logout
javascript
// Redirect to logout
window.location.href =
'https://engagifii-identity-live.azurewebsites.net/connect/endsession?' +
'id_token_hint=' + idToken + '&' +
'post_logout_redirect_uri=https://yourapp.com';Validate Token (Introspection)
javascript
const response = await fetch('https://engagifii-identity-live.azurewebsites.net/connect/introspect', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + btoa(client_id + ':' + client_secret)
},
body: new URLSearchParams({
token: access_token
})
});
const tokenInfo = await response.json();
// Returns: { active: true/false, scope, exp, ... }Token Formats
Access Token Claims
json
{
"iss": "https://engagifii-identity-live.azurewebsites.net",
"aud": ["api1", "api2"],
"client_id": "webapp",
"sub": "user123",
"scope": ["openid", "profile", "api"],
"exp": 1672531200,
"iat": 1672527600
}ID Token Claims
json
{
"iss": "https://engagifii-identity-live.azurewebsites.net",
"aud": "webapp",
"sub": "user123",
"name": "John Doe",
"email": "john@example.com",
"email_verified": true,
"iat": 1672527600,
"exp": 1672531200
}Error Quick Reference
| Error Code | Meaning | Quick Fix |
|---|---|---|
invalid_client | Wrong credentials | Check client_id and secret |
invalid_grant | Code/token expired | Request new authorization |
invalid_scope | Scope not allowed | Use configured scopes |
invalid_request | Missing parameter | Check required params |
access_denied | User denied | Handle in UI gracefully |
invalid_token | Token expired/invalid | Refresh or re-authenticate |
HTTP Status Codes
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Process response |
| 302 | Redirect | Follow redirect |
| 400 | Bad request | Fix parameters |
| 401 | Unauthorized | Authenticate |
| 429 | Rate limited | Wait and retry |
| 500 | Server error | Retry with backoff |
Security Checklist
- [ ] Always use HTTPS
- [ ] Store secrets securely (never client-side)
- [ ] Validate state parameter
- [ ] Use PKCE for public clients
- [ ] Implement token refresh
- [ ] Handle token expiry
- [ ] Validate ID token signature
- [ ] Implement proper logout
Integration Patterns
Token Management Class
javascript
class TokenManager {
constructor(clientId, clientSecret) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.tokens = null;
}
async getAccessToken() {
if (!this.tokens || this.isExpired()) {
await this.refresh();
}
return this.tokens.access_token;
}
isExpired() {
return Date.now() >= (this.tokens.expires_at - 300000);
}
async refresh() {
// Implement token refresh logic
}
}API Request Wrapper
javascript
async function apiRequest(endpoint, options = {}) {
const token = await tokenManager.getAccessToken();
const response = await fetch(endpoint, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${token}`
}
});
if (response.status === 401) {
// Token expired, refresh and retry
await tokenManager.refresh();
return apiRequest(endpoint, options);
}
return response;
}Express Middleware
javascript
function requireAuth(req, res, next) {
if (!req.session?.tokens?.access_token) {
return res.redirect('/login');
}
const expiresAt = req.session.tokens.expires_at;
if (Date.now() >= expiresAt) {
return res.redirect('/login');
}
next();
}Testing Tools
cURL Examples
bash
# Get access token (client credentials)
curl -X POST https://engagifii-identity-live.azurewebsites.net/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=CLIENT_ID&client_secret=SECRET&scope=api"
# Get user info
curl -X GET https://engagifii-identity-live.azurewebsites.net/connect/userinfo \
-H "Authorization: Bearer ACCESS_TOKEN"
# Introspect token
curl -X POST https://engagifii-identity-live.azurewebsites.net/connect/introspect \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "CLIENT_ID:CLIENT_SECRET" \
-d "token=ACCESS_TOKEN"Postman Environment Variables
json
{
"identity_url": "https://engagifii-identity-live.azurewebsites.net",
"client_id": "your-client-id",
"client_secret": "your-client-secret",
"redirect_uri": "https://oauth.pstmn.io/v1/callback",
"scope": "openid profile email api",
"access_token": "{{auto-populated}}",
"refresh_token": "{{auto-populated}}"
}Debugging Commands
Decode JWT (bash)
bash
echo "JWT_TOKEN" | cut -d. -f2 | base64 -d | jqDecode JWT (JavaScript)
javascript
const decoded = JSON.parse(atob(token.split('.')[1]));
console.log(decoded);Check Token Expiry
javascript
const payload = JSON.parse(atob(token.split('.')[1]));
const expiresAt = new Date(payload.exp * 1000);
console.log('Token expires at:', expiresAt);
console.log('Is expired:', Date.now() > payload.exp * 1000);Environment Variables
Required Configuration
bash
# Identity Service
IDENTITY_URL=https://engagifii-identity-live.azurewebsites.net
CLIENT_ID=your-client-id
CLIENT_SECRET=your-client-secret
# Application
REDIRECT_URI=https://yourapp.com/callback
POST_LOGOUT_URI=https://yourapp.com
SCOPES=openid profile email api
# Session
SESSION_SECRET=random-secret-string
SESSION_TIMEOUT=3600000Rate Limits
| Endpoint | Limit | Window |
|---|---|---|
| /connect/authorize | 10 req | Per minute |
| /connect/token | 20 req | Per minute |
| /connect/userinfo | 100 req | Per minute |
| /connect/introspect | 50 req | Per minute |
Support Links
Remember: Always use HTTPS, never expose secrets client-side, and implement proper error handling!
