/**
 * Authentication and authorization middleware
 */
import { verify } from 'jsonwebtoken';
import { DIDResolver } from '@the-order/auth';
import { getEnv } from './env';
import { AppError } from './error-handler';
import fetch from 'node-fetch';
/**
 * JWT authentication middleware
 */
export async function authenticateJWT(request, _reply) {
    const authHeader = request.headers.authorization;
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
        throw new AppError(401, 'UNAUTHORIZED', 'Missing or invalid authorization header');
    }
    const token = authHeader.substring(7);
    const env = getEnv();
    if (!env.JWT_SECRET) {
        throw new AppError(500, 'CONFIG_ERROR', 'JWT secret not configured');
    }
    try {
        const decoded = verify(token, env.JWT_SECRET);
        request.user = decoded;
    }
    catch (error) {
        throw new AppError(401, 'INVALID_TOKEN', 'Invalid or expired token');
    }
}
/**
 * DID-based authentication middleware
 */
export async function authenticateDID(request, _reply) {
    const didHeader = request.headers['x-did'];
    const signatureHeader = request.headers['x-did-signature'];
    const messageHeader = request.headers['x-did-message'];
    if (!didHeader || !signatureHeader || !messageHeader) {
        throw new AppError(401, 'UNAUTHORIZED', 'Missing DID authentication headers');
    }
    try {
        const resolver = new DIDResolver();
        const isValid = await resolver.verifySignature(didHeader, messageHeader, signatureHeader);
        if (!isValid) {
            throw new AppError(401, 'INVALID_SIGNATURE', 'Invalid DID signature');
        }
        request.user = {
            id: didHeader,
            did: didHeader,
        };
    }
    catch (error) {
        if (error instanceof AppError) {
            throw error;
        }
        throw new AppError(401, 'AUTH_ERROR', 'DID authentication failed');
    }
}
/**
 * Role-based access control middleware
 */
export function requireRole(...allowedRoles) {
    return async (request, _reply) => {
        if (!request.user) {
            throw new AppError(401, 'UNAUTHORIZED', 'Authentication required');
        }
        const userRoles = request.user.roles || [];
        const hasRole = allowedRoles.some((role) => userRoles.includes(role));
        if (!hasRole) {
            throw new AppError(403, 'FORBIDDEN', `Required role: ${allowedRoles.join(' or ')}`);
        }
    };
}
/**
 * OIDC token validation middleware
 */
export async function authenticateOIDC(request, _reply) {
    const authHeader = request.headers.authorization;
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
        throw new AppError(401, 'UNAUTHORIZED', 'Missing authorization header');
    }
    const token = authHeader.substring(7);
    const env = getEnv();
    // Validate token with OIDC issuer
    if (!env.OIDC_ISSUER) {
        throw new AppError(500, 'CONFIG_ERROR', 'OIDC issuer not configured');
    }
    try {
        // Introspect token with issuer
        const introspectionUrl = `${env.OIDC_ISSUER}/introspect`;
        const response = await fetch(introspectionUrl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                Authorization: `Basic ${Buffer.from(`${env.OIDC_CLIENT_ID}:${env.OIDC_CLIENT_SECRET}`).toString('base64')}`,
            },
            body: new URLSearchParams({
                token,
                token_type_hint: 'access_token',
            }),
        });
        if (!response.ok) {
            throw new AppError(401, 'INVALID_TOKEN', 'Token introspection failed');
        }
        const tokenInfo = (await response.json());
        if (!tokenInfo.active) {
            throw new AppError(401, 'INVALID_TOKEN', 'Token is not active');
        }
        // Get user info from userinfo endpoint
        const userInfoUrl = `${env.OIDC_ISSUER}/userinfo`;
        const userInfoResponse = await fetch(userInfoUrl, {
            headers: {
                Authorization: `Bearer ${token}`,
            },
        });
        if (userInfoResponse.ok) {
            const userInfo = (await userInfoResponse.json());
            request.user = {
                id: userInfo.sub,
                email: userInfo.email,
            };
        }
        else {
            // Fallback to token info
            request.user = {
                id: tokenInfo.sub || 'oidc-user',
                email: tokenInfo.email,
            };
        }
    }
    catch (error) {
        if (error instanceof AppError) {
            throw error;
        }
        throw new AppError(401, 'AUTH_ERROR', 'OIDC token validation failed');
    }
}
//# sourceMappingURL=auth.js.map