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
Before troubleshooting, collect:
Error messages (exact text and error codes)
Environment (development/production)
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.json
Step-by-Step Troubleshooting
Problem: "Cannot connect to Oten IDP"
Symptoms:
Connection refused errors
Solutions:
Check network connectivity:
# Test basic connectivity
ping account.oten.com
# Test HTTPS connectivity
curl -I https://account.oten.com
Verify firewall settings:
Ensure outbound HTTPS (port 443) is allowed
Check corporate firewall/proxy settings
Verify no SSL/TLS inspection is interfering
nslookup account.oten.com
Problem: "JAR signature verification failed"
Symptoms:
Error code: invalid_request_object
Authorization request rejected
Solutions:
// 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);
}
// 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_grant
Authorization 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');
});
// 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);
// 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
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:
Technical Support: support@oten.dev
When contacting support, please include:
Environment details:
Development or production
Programming language and version
Error information:
Error code and HTTP status
Configuration (sanitized):
Client ID (safe to share)
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:
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