Debug and Troubleshooting
This comprehensive guide helps you debug and troubleshoot Oten IDP integration issues systematically.
π Debugging Methodology
Step 1: Identify the Problem Area
OAuth Flow Stages:
JAR Creation - Creating and signing JWT authorization request
Authorization - Redirecting user to Oten IDP
Callback - Handling authorization response
Token Exchange - Converting authorization code to tokens
API Calls - Using access tokens for API requests
Step 2: Gather Information
Before troubleshooting, collect:
Error messages (exact text and error codes)
HTTP status codes
Request/response headers
Timestamps
Environment (development/production)
Client configuration
Step 3: Use Debugging Tools
π οΈ Debugging Tools
1. JAR Token Decoder
Use this to inspect your JAR tokens:
// Decode JAR without verification (for debugging only)
function debugJAR(jarToken) {
try {
const decoded = jwt.decode(jarToken, { complete: true });
console.log('=== JAR DEBUG INFO ===');
console.log('Header:', JSON.stringify(decoded.header, null, 2));
console.log('Payload:', JSON.stringify(decoded.payload, null, 2));
// Check required claims
const required = ['iss', 'aud', 'iat', 'exp', 'jti', 'client_id', 'redirect_uri', 'response_type'];
const missing = required.filter(claim => !decoded.payload[claim]);
if (missing.length > 0) {
console.log('β Missing required claims:', missing);
} else {
console.log('β
All required claims present');
}
// Check expiration
const now = Math.floor(Date.now() / 1000);
if (decoded.payload.exp < now) {
console.log('β Token expired');
} else {
console.log('β
Token not expired');
}
// Check audience
if (decoded.payload.aud !== 'https://account.oten.com' &&
decoded.payload.aud !== 'https://account.sbx.oten.dev') {
console.log('β Invalid audience');
} else {
console.log('β
Valid audience');
}
} catch (error) {
console.log('β Failed to decode JAR:', error.message);
}
}
// Usage
debugJAR(yourJARToken);2. Environment Checker
Verify your environment configuration:
function checkEnvironment() {
console.log('=== ENVIRONMENT CHECK ===');
const required = [
'OTEN_CLIENT_ID',
'OTEN_REDIRECT_URI'
];
const optional = [
'OTEN_CLIENT_SECRET',
'OTEN_PRIVATE_KEY_PATH',
'OTEN_KEY_ID',
'OTEN_ENV'
];
console.log('Required variables:');
required.forEach(key => {
const value = process.env[key];
console.log(` ${key}: ${value ? 'β
Set' : 'β Missing'}`);
});
console.log('Optional variables:');
optional.forEach(key => {
const value = process.env[key];
console.log(` ${key}: ${value ? 'β
Set' : 'β οΈ Not set'}`);
});
// Check redirect URI format
const redirectUri = process.env.OTEN_REDIRECT_URI;
if (redirectUri) {
if (redirectUri.startsWith('https://') || redirectUri.startsWith('http://localhost')) {
console.log('β
Redirect URI format valid');
} else {
console.log('β Redirect URI must use HTTPS (or http://localhost for development)');
}
}
}3. Quick Connectivity Test
Test basic connectivity to Oten IDP:
# Test basic connectivity
curl -I https://account.oten.com
# Test discovery endpoint
curl https://account.oten.com/.well-known/openid_configuration
# Test JWKS endpoint
curl https://account.oten.com/.well-known/jwks.jsonStep-by-Step Troubleshooting
Problem: "Cannot connect to Oten IDP"
Symptoms:
Network timeouts
Connection refused errors
DNS resolution failures
Solutions:
Check network connectivity:
# Test basic connectivity
ping account.oten.com
# Test HTTPS connectivity
curl -I https://account.oten.comVerify firewall settings:
Ensure outbound HTTPS (port 443) is allowed
Check corporate firewall/proxy settings
Verify no SSL/TLS inspection is interfering
Check DNS resolution:
nslookup account.oten.comProblem: "JAR signature verification failed"
Symptoms:
Error code:
invalid_request_objectAuthorization request rejected
Solutions:
For HS256 issues:
// Verify client secret
console.log('Client secret length:', process.env.OTEN_CLIENT_SECRET?.length);
// Test JAR creation
const testPayload = { test: 'data', iat: Math.floor(Date.now() / 1000) };
try {
const testJWT = jwt.sign(testPayload, process.env.OTEN_CLIENT_SECRET, { algorithm: 'HS256' });
console.log('β
JWT signing works');
// Verify locally
const verified = jwt.verify(testJWT, process.env.OTEN_CLIENT_SECRET, { algorithm: 'HS256' });
console.log('β
JWT verification works');
} catch (error) {
console.log('β JWT signing/verification failed:', error.message);
}For EdDSA issues:
// Check private key format
const fs = require('fs');
try {
const privateKey = fs.readFileSync(process.env.OTEN_PRIVATE_KEY_PATH, 'utf8');
console.log('β
Private key file readable');
if (privateKey.includes('BEGIN PRIVATE KEY')) {
console.log('β
Private key format appears correct');
} else {
console.log('β οΈ Private key format may be incorrect');
}
} catch (error) {
console.log('β Cannot read private key file:', error.message);
}
// Verify Key ID is set
if (process.env.OTEN_KEY_ID) {
console.log('β
Key ID is set:', process.env.OTEN_KEY_ID);
} else {
console.log('β Key ID is not set');
}Problem: "Token exchange fails"
Symptoms:
Error code:
invalid_grantAuthorization code rejected
Solutions:
Check authorization code:
app.get('/callback', (req, res) => {
const { code, state, error } = req.query;
console.log('Authorization code length:', code?.length);
console.log('State matches:', state === storedState);
if (!code) {
console.log('β No authorization code received');
return;
}
if (code.length < 10) {
console.log('β Authorization code seems too short');
return;
}
console.log('β
Authorization code appears valid');
});Verify PKCE parameters:
// Ensure code_verifier matches code_challenge
const storedVerifier = session.codeVerifier;
const challengeFromVerifier = crypto
.createHash('sha256')
.update(storedVerifier)
.digest('base64url');
console.log('Stored verifier:', storedVerifier);
console.log('Challenge from verifier:', challengeFromVerifier);
console.log('Original challenge:', session.codeChallenge);
console.log('Challenges match:', challengeFromVerifier === session.codeChallenge);Check redirect URI:
// Ensure redirect URI exactly matches registration
const configuredURI = process.env.OTEN_REDIRECT_URI;
const requestURI = req.get('host') + req.originalUrl.split('?')[0];
console.log('Configured redirect URI:', configuredURI);
console.log('Actual request URI:', requestURI);
console.log('URIs match:', configuredURI.includes(requestURI));Troubleshooting Checklist
Before Contacting Support
Complete this checklist before reaching out for help:
Environment Setup:
JAR Implementation:
OAuth Flow:
Error Information Collected:
π Getting Help
If you've completed the troubleshooting checklist and still need help:
Contact Support
Technical Support: [email protected]
Include This Information
When contacting support, please include:
Environment details:
Development or production
Programming language and version
Library versions used
Error information:
Complete error message
Error code and HTTP status
Timestamp of the error
Configuration (sanitized):
Client ID (safe to share)
Redirect URI
Scopes requested
JAR signing method used
Code samples:
JAR creation code (remove secrets)
Authorization URL generation
Token exchange implementation
Debugging output:
JAR token structure (decoded)
Network request/response logs
Environment check results
What NOT to Share
Never share these in support requests:
Client secrets
Private keys
Access tokens
Refresh tokens
User credentials
π Related Documentation
Common Errors - Specific error codes and solutions
JAR Complete Implementation Guide - JAR implementation examples
API Reference - Complete API documentation
Configuration Reference - Endpoints and settings
Last updated