OAuth and Third-Party Authentication Headers

OAuth and Third-Party Authentication Headers

OAuth2 Security Headers Implementation

// OAuth2 authorization endpoint
app.get('/oauth/authorize', (req, res) => {
    // Set security headers for OAuth flow
    res.setHeader('X-Frame-Options', 'DENY'); // Prevent clickjacking
    res.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
    res.setHeader('Cache-Control', 'no-store');
    res.setHeader('Pragma', 'no-cache');
    
    // PKCE (Proof Key for Code Exchange) for public clients
    const codeChallenge = req.query.code_challenge;
    const codeChallengeMethod = req.query.code_challenge_method;
    
    if (req.query.response_type === 'code' && !codeChallenge) {
        return res.status(400).json({
            error: 'invalid_request',
            error_description: 'PKCE required for public clients'
        });
    }
    
    // Generate authorization code
    const authCode = generateAuthorizationCode({
        clientId: req.query.client_id,
        userId: req.session.userId,
        redirectUri: req.query.redirect_uri,
        scope: req.query.scope,
        codeChallenge: codeChallenge,
        codeChallengeMethod: codeChallengeMethod
    });
    
    // Set state cookie for CSRF protection
    if (req.query.state) {
        res.cookie('oauth_state', req.query.state, {
            secure: true,
            httpOnly: true,
            sameSite: 'lax', // Allow for OAuth redirects
            maxAge: 600000 // 10 minutes
        });
    }
    
    // Redirect with authorization code
    const redirectUrl = new URL(req.query.redirect_uri);
    redirectUrl.searchParams.set('code', authCode);
    redirectUrl.searchParams.set('state', req.query.state);
    
    res.redirect(redirectUrl.toString());
});

// Token endpoint with security headers
app.post('/oauth/token', (req, res) => {
    // Security headers for token endpoint
    res.setHeader('Cache-Control', 'no-store');
    res.setHeader('Pragma', 'no-cache');
    res.setHeader('Content-Type', 'application/json;charset=UTF-8');
    res.setHeader('X-Content-Type-Options', 'nosniff');
    res.setHeader('X-Frame-Options', 'DENY');
    
    // CORS headers for public clients
    const origin = req.headers.origin;
    const allowedOrigins = ['https://app.example.com', 'https://mobile.example.com'];
    
    if (allowedOrigins.includes(origin)) {
        res.setHeader('Access-Control-Allow-Origin', origin);
        res.setHeader('Access-Control-Allow-Methods', 'POST');
        res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
    }
    
    // Token generation logic...
});