mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:21:09 +02:00
fix(auth): add OAuth2 routes for OIDC discovery compatibility
Better Auth's OIDC discovery document advertises endpoints at /api/auth/oauth2/* paths. Add routes for these native paths to ensure Matrix Synapse and other OIDC clients can complete the authorization flow. Routes added: - GET /api/auth/oauth2/authorize - POST /api/auth/oauth2/token - GET /api/auth/oauth2/userinfo - GET /api/auth/jwks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c3dd7703b2
commit
baea194677
2 changed files with 76 additions and 33 deletions
|
|
@ -4,12 +4,17 @@
|
|||
* Exposes Better Auth's OIDC Provider endpoints for external services
|
||||
* like Matrix/Synapse to use SSO authentication.
|
||||
*
|
||||
* Better Auth exposes OIDC endpoints at /api/auth/oauth2/* paths.
|
||||
* This controller provides routes at both:
|
||||
* - /api/auth/oauth2/* (native Better Auth paths from discovery document)
|
||||
* - /api/oidc/* (alternative paths for convenience)
|
||||
*
|
||||
* Endpoints:
|
||||
* - GET /.well-known/openid-configuration - OIDC Discovery
|
||||
* - GET /api/oidc/authorize - Authorization endpoint
|
||||
* - POST /api/oidc/token - Token endpoint
|
||||
* - GET /api/oidc/userinfo - UserInfo endpoint
|
||||
* - GET /api/oidc/jwks - JWKS endpoint
|
||||
* - GET /api/auth/oauth2/authorize - Authorization endpoint
|
||||
* - POST /api/auth/oauth2/token - Token endpoint
|
||||
* - GET /api/auth/oauth2/userinfo - UserInfo endpoint
|
||||
* - GET /api/auth/jwks - JWKS endpoint
|
||||
*/
|
||||
|
||||
import { Controller, Get, Post, All, Req, Res, HttpStatus } from '@nestjs/common';
|
||||
|
|
@ -30,10 +35,58 @@ export class OidcController {
|
|||
return this.handleOidcRequest(req, res);
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Better Auth Native OAuth2 Endpoints
|
||||
// These match the paths in the discovery document
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Authorization Endpoint
|
||||
*
|
||||
* Handles OAuth2 authorization requests.
|
||||
* Authorization Endpoint (Better Auth native path)
|
||||
*/
|
||||
@Get('api/auth/oauth2/authorize')
|
||||
async authorizeOauth2(@Req() req: Request, @Res() res: Response) {
|
||||
return this.handleOidcRequest(req, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Token Endpoint (Better Auth native path)
|
||||
*/
|
||||
@Post('api/auth/oauth2/token')
|
||||
async tokenOauth2(@Req() req: Request, @Res() res: Response) {
|
||||
return this.handleOidcRequest(req, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* UserInfo Endpoint (Better Auth native path)
|
||||
*/
|
||||
@Get('api/auth/oauth2/userinfo')
|
||||
async userinfoOauth2(@Req() req: Request, @Res() res: Response) {
|
||||
return this.handleOidcRequest(req, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* JWKS Endpoint (Better Auth native path)
|
||||
*/
|
||||
@Get('api/auth/jwks')
|
||||
async jwksAuth(@Req() req: Request, @Res() res: Response) {
|
||||
return this.handleOidcRequest(req, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Catch-all for other Better Auth OAuth2 endpoints
|
||||
*/
|
||||
@All('api/auth/oauth2/*')
|
||||
async catchAllOauth2(@Req() req: Request, @Res() res: Response) {
|
||||
return this.handleOidcRequest(req, res);
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Alternative /api/oidc/* paths
|
||||
// For backwards compatibility and convenience
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Authorization Endpoint (alternative path)
|
||||
*/
|
||||
@Get('api/oidc/authorize')
|
||||
async authorize(@Req() req: Request, @Res() res: Response) {
|
||||
|
|
@ -41,9 +94,7 @@ export class OidcController {
|
|||
}
|
||||
|
||||
/**
|
||||
* Token Endpoint
|
||||
*
|
||||
* Exchanges authorization codes for tokens.
|
||||
* Token Endpoint (alternative path)
|
||||
*/
|
||||
@Post('api/oidc/token')
|
||||
async token(@Req() req: Request, @Res() res: Response) {
|
||||
|
|
@ -51,9 +102,7 @@ export class OidcController {
|
|||
}
|
||||
|
||||
/**
|
||||
* UserInfo Endpoint
|
||||
*
|
||||
* Returns user information for the authenticated user.
|
||||
* UserInfo Endpoint (alternative path)
|
||||
*/
|
||||
@Get('api/oidc/userinfo')
|
||||
async userinfo(@Req() req: Request, @Res() res: Response) {
|
||||
|
|
@ -61,9 +110,7 @@ export class OidcController {
|
|||
}
|
||||
|
||||
/**
|
||||
* JWKS Endpoint (via /api/oidc/jwks)
|
||||
*
|
||||
* Returns JSON Web Key Set for token verification.
|
||||
* JWKS Endpoint (alternative path)
|
||||
*/
|
||||
@Get('api/oidc/jwks')
|
||||
async jwks(@Req() req: Request, @Res() res: Response) {
|
||||
|
|
@ -71,18 +118,7 @@ export class OidcController {
|
|||
}
|
||||
|
||||
/**
|
||||
* JWKS Endpoint (via /api/auth/jwks)
|
||||
*
|
||||
* Better Auth's discovery document points to this path,
|
||||
* so we need to expose it directly as well.
|
||||
*/
|
||||
@Get('api/auth/jwks')
|
||||
async jwksAlt(@Req() req: Request, @Res() res: Response) {
|
||||
return this.handleOidcRequest(req, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Catch-all for other OIDC endpoints
|
||||
* Catch-all for other OIDC endpoints (alternative path)
|
||||
*/
|
||||
@All('api/oidc/*')
|
||||
async catchAll(@Req() req: Request, @Res() res: Response) {
|
||||
|
|
|
|||
|
|
@ -81,18 +81,25 @@ async function bootstrap() {
|
|||
|
||||
// Global prefix (exclude metrics, health, Better Auth native routes, and OIDC routes)
|
||||
// Better Auth generates verification URLs with /api/auth/* prefix
|
||||
// OIDC Provider requires routes without prefix: /.well-known/*, /api/oidc/*
|
||||
// OIDC Provider requires routes without prefix: /.well-known/*, /api/auth/oauth2/*, /api/oidc/*
|
||||
app.setGlobalPrefix('api/v1', {
|
||||
exclude: [
|
||||
{ path: 'metrics', method: RequestMethod.ALL },
|
||||
{ path: 'health', method: RequestMethod.ALL },
|
||||
// Better Auth routes - use path-to-regexp wildcards
|
||||
{ path: 'api/auth/(.*)', method: RequestMethod.ALL },
|
||||
// Better Auth routes (verification emails, password reset)
|
||||
{ path: 'api/auth/verify-email', method: RequestMethod.ALL },
|
||||
{ path: 'api/auth/reset-password/(.*)', method: RequestMethod.ALL },
|
||||
// Better Auth OIDC/OAuth2 routes (native paths from discovery document)
|
||||
{ path: 'api/auth/jwks', method: RequestMethod.ALL },
|
||||
{ path: 'api/auth/:path*', method: RequestMethod.ALL },
|
||||
// OIDC routes
|
||||
{ path: 'api/auth/oauth2/(.*)', method: RequestMethod.ALL },
|
||||
{ path: 'api/auth/oauth2/authorize', method: RequestMethod.ALL },
|
||||
{ path: 'api/auth/oauth2/token', method: RequestMethod.ALL },
|
||||
{ path: 'api/auth/oauth2/userinfo', method: RequestMethod.ALL },
|
||||
{ path: 'api/auth/oauth2/:path*', method: RequestMethod.ALL },
|
||||
// OIDC discovery
|
||||
{ path: '.well-known/(.*)', method: RequestMethod.ALL },
|
||||
{ path: '.well-known/openid-configuration', method: RequestMethod.ALL },
|
||||
// Alternative OIDC routes
|
||||
{ path: 'api/oidc/(.*)', method: RequestMethod.ALL },
|
||||
{ path: 'api/oidc/:path*', method: RequestMethod.ALL },
|
||||
],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue