> For the complete documentation index, see [llms.txt](https://oten.gitbook.io/identity-support/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://oten.gitbook.io/identity-support/integration/prerequisites/support-and-troubleshoot/debug-and-troubleshooting.md).

# 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:**

1. **JAR Creation** - Creating and signing JWT authorization request
2. **Authorization** - Redirecting user to Oten IDP
3. **Callback** - Handling authorization response
4. **Token Exchange** - Converting authorization code to tokens
5. **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:

```javascript
// 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:

```javascript
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:

```bash
# 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:**

* Network timeouts
* Connection refused errors
* DNS resolution failures

**Solutions:**

1. **Check network connectivity:**

```bash
# Test basic connectivity
ping account.oten.com

# Test HTTPS connectivity
curl -I https://account.oten.com
```

2. **Verify firewall settings:**

* Ensure outbound HTTPS (port 443) is allowed
* Check corporate firewall/proxy settings
* Verify no SSL/TLS inspection is interfering

3. **Check DNS resolution:**

```bash
nslookup account.oten.com
```

### Problem: "JAR signature verification failed"

**Symptoms:**

* Error code: `invalid_request_object`
* Authorization request rejected

**Solutions:**

1. **For HS256 issues:**

```javascript
// 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);
}
```

2. **For EdDSA issues:**

```javascript
// 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:**

1. **Check authorization code:**

```javascript
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');
});
```

2. **Verify PKCE parameters:**

```javascript
// 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);
```

3. **Check redirect URI:**

```javascript
// 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:**

* [ ] Client ID is correct and registered
* [ ] Redirect URI matches exactly (including protocol, domain, port, path)
* [ ] Environment variables are set correctly
* [ ] Network connectivity to Oten IDP is working

**JAR Implementation:**

* [ ] JAR contains all required JWT claims (iss, aud, iat, exp, jti)
* [ ] JAR contains all OAuth parameters (client\_id, redirect\_uri, response\_type, etc.)
* [ ] JAR is signed with correct algorithm (HS256 or EdDSA)
* [ ] JAR expiration is set appropriately (≤ 5 minutes)
* [ ] For EdDSA: Key ID matches registered public key

**OAuth Flow:**

* [ ] Authorization URL contains only client\_id and request parameters
* [ ] PKCE code\_verifier and code\_challenge are generated correctly
* [ ] State parameter is used and verified
* [ ] Authorization code is used only once
* [ ] Token exchange includes all required parameters

**Error Information Collected:**

* [ ] Exact error message and error code
* [ ] HTTP status code
* [ ] Request/response headers
* [ ] Timestamp of the error
* [ ] Steps to reproduce the issue

## 🆘 Getting Help

If you've completed the troubleshooting checklist and still need help:

### Contact Support

**Technical Support**: <support@oten.dev>

### Include This Information

When contacting support, please include:

1. **Environment details:**
   * Development or production
   * Programming language and version
   * Library versions used
2. **Error information:**
   * Complete error message
   * Error code and HTTP status
   * Timestamp of the error
3. **Configuration (sanitized):**
   * Client ID (safe to share)
   * Redirect URI
   * Scopes requested
   * JAR signing method used
4. **Code samples:**
   * JAR creation code (remove secrets)
   * Authorization URL generation
   * Token exchange implementation
5. **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](broken://pages/ChQqcK8cqX9LLgyQtBJT) - Specific error codes and solutions
* [JAR Complete Implementation Guide](broken://pages/TTsI7h4QqrFoRyKuF1Di) - JAR implementation examples
* [API Reference](broken://pages/rBfeuN3JiwHAXoU2ybbc) - Complete API documentation
* [Configuration Reference](broken://pages/XsyPoCRDPUpz0vcP6KkD) - Endpoints and settings
