11import type { Request , Response } from "express" ;
2- import OAuth2Server from ' @node-oauth/oauth2-server' ;
2+ import OAuth2Server from " @node-oauth/oauth2-server" ;
33import { getConfig } from "../config.ts" ;
44import { logger } from "../logger.ts" ;
55
66/**
77 * OAuth 2.0 Authorization Server Metadata endpoint
88 * RFC 8414: https://tools.ietf.org/html/rfc8414
9- *
9+ *
1010 * For AUTH_MODE=full, this describes our OAuth client proxy endpoints
1111 */
1212export function createAuthorizationServerMetadataHandler ( ) {
1313 return ( req : Request , res : Response ) => {
1414 try {
1515 const config = getConfig ( ) ;
16- const baseUrl = `${ req . protocol } ://${ req . get ( ' host' ) } ` ;
16+ const baseUrl = `${ req . protocol } ://${ req . get ( " host" ) } ` ;
1717
1818 const metadata = {
1919 issuer : baseUrl ,
@@ -23,21 +23,21 @@ export function createAuthorizationServerMetadataHandler() {
2323 grant_types_supported : [ "authorization_code" ] ,
2424 code_challenge_methods_supported : [ "S256" ] ,
2525 scopes_supported : [ "read" , "write" , "mcp" ] ,
26- token_endpoint_auth_methods_supported : [ "none" ]
26+ token_endpoint_auth_methods_supported : [ "none" ] ,
2727 } ;
2828
29- logger . info ( "OAuth authorization server metadata requested" , {
30- issuer : metadata . issuer
29+ logger . info ( "OAuth authorization server metadata requested" , {
30+ issuer : metadata . issuer ,
3131 } ) ;
3232
3333 res . json ( metadata ) ;
3434 } catch ( error ) {
35- logger . error ( "Error serving authorization server metadata" , {
36- error : error instanceof Error ? error . message : error
35+ logger . error ( "Error serving authorization server metadata" , {
36+ error : error instanceof Error ? error . message : error ,
3737 } ) ;
3838 res . status ( 500 ) . json ( {
3939 error : "server_error" ,
40- error_description : "Failed to serve authorization server metadata"
40+ error_description : "Failed to serve authorization server metadata" ,
4141 } ) ;
4242 }
4343 } ;
@@ -46,35 +46,35 @@ export function createAuthorizationServerMetadataHandler() {
4646/**
4747 * OAuth 2.0 Protected Resource Metadata endpoint
4848 * RFC 8705: https://tools.ietf.org/html/rfc8705
49- *
49+ *
5050 * For AUTH_MODE=full, this describes our resource server capabilities
5151 */
5252export function createProtectedResourceMetadataHandler ( ) {
5353 return ( req : Request , res : Response ) => {
5454 try {
5555 const config = getConfig ( ) ;
56- const baseUrl = `${ req . protocol } ://${ req . get ( ' host' ) } ` ;
56+ const baseUrl = `${ req . protocol } ://${ req . get ( " host" ) } ` ;
5757
5858 const metadata = {
5959 resource : baseUrl ,
6060 authorization_servers : [ baseUrl ] ,
6161 scopes_supported : [ "read" , "write" , "mcp" ] ,
6262 bearer_methods_supported : [ "header" ] ,
63- resource_documentation : new URL ( "/docs" , baseUrl ) . toString ( )
63+ resource_documentation : new URL ( "/docs" , baseUrl ) . toString ( ) ,
6464 } ;
6565
66- logger . info ( "OAuth protected resource metadata requested" , {
67- resource : metadata . resource
66+ logger . info ( "OAuth protected resource metadata requested" , {
67+ resource : metadata . resource ,
6868 } ) ;
6969
7070 res . json ( metadata ) ;
7171 } catch ( error ) {
72- logger . error ( "Error serving protected resource metadata" , {
73- error : error instanceof Error ? error . message : error
72+ logger . error ( "Error serving protected resource metadata" , {
73+ error : error instanceof Error ? error . message : error ,
7474 } ) ;
7575 res . status ( 500 ) . json ( {
7676 error : "server_error" ,
77- error_description : "Failed to serve protected resource metadata"
77+ error_description : "Failed to serve protected resource metadata" ,
7878 } ) ;
7979 }
8080 } ;
@@ -86,9 +86,9 @@ export function createProtectedResourceMetadataHandler() {
8686export function createAuthorizeHandler ( oauthServer : OAuth2Server ) {
8787 return async ( req : Request , res : Response ) => {
8888 try {
89- logger . debug ( "Authorization request received" , {
89+ logger . debug ( "Authorization request received" , {
9090 query : req . query ,
91- method : req . method
91+ method : req . method ,
9292 } ) ;
9393
9494 // Real OAuth implementation: Check for authenticated user
@@ -97,73 +97,77 @@ export function createAuthorizeHandler(oauthServer: OAuth2Server) {
9797 // 2. If not authenticated, redirect to login page
9898 // 3. After login, show consent page
9999 // 4. Only then proceed with authorization
100-
100+
101101 // For now, this implementation requires external authentication
102102 // The user must be authenticated before reaching this endpoint
103- const userId = req . headers [ ' x-user-id' ] as string ;
104- const username = req . headers [ ' x-username' ] as string ;
105-
103+ const userId = req . headers [ " x-user-id" ] as string ;
104+ const username = req . headers [ " x-username" ] as string ;
105+
106106 if ( ! userId || ! username ) {
107107 logger . warn ( "Missing user authentication headers" ) ;
108108 return res . status ( 401 ) . json ( {
109109 error : "access_denied" ,
110- error_description : "User must be authenticated before authorization"
110+ error_description : "User must be authenticated before authorization" ,
111111 } ) ;
112112 }
113-
113+
114114 const user = {
115115 id : userId ,
116- username : username
116+ username : username ,
117117 } ;
118118
119- logger . debug ( "User authenticated, proceeding with authorization" , { userId : user . id } ) ;
119+ logger . debug ( "User authenticated, proceeding with authorization" , {
120+ userId : user . id ,
121+ } ) ;
120122
121123 // Use the OAuth2Server authorize method
122124 const request = new ( OAuth2Server as any ) . Request ( req ) ;
123125 const response = new ( OAuth2Server as any ) . Response ( res ) ;
124-
126+
125127 const authorizationCode = await oauthServer . authorize ( request , response , {
126128 authenticateHandler : {
127129 handle : async ( ) => {
128130 logger . debug ( "Authenticate handler called" ) ;
129131 return user ;
130- }
131- }
132+ } ,
133+ } ,
132134 } ) ;
133135
134- logger . info ( "Authorization code granted" , {
136+ logger . info ( "Authorization code granted" , {
135137 clientId : authorizationCode . client . id ,
136- userId : user . id
138+ userId : user . id ,
137139 } ) ;
138140
139141 // Redirect back to client with authorization code
140142 const redirectUri = req . query . redirect_uri as string ;
141143 const state = req . query . state as string ;
142-
144+
143145 if ( redirectUri ) {
144146 const url = new URL ( redirectUri ) ;
145- url . searchParams . set ( ' code' , authorizationCode . authorizationCode ) ;
146- if ( state ) url . searchParams . set ( ' state' , state ) ;
147-
147+ url . searchParams . set ( " code" , authorizationCode . authorizationCode ) ;
148+ if ( state ) url . searchParams . set ( " state" , state ) ;
149+
148150 logger . info ( "Redirecting to client" , { redirectUrl : url . toString ( ) } ) ;
149151 res . redirect ( url . toString ( ) ) ;
150152 } else {
151153 // Fallback - return as JSON
152- res . json ( {
154+ res . json ( {
153155 authorization_code : authorizationCode . authorizationCode ,
154- state
156+ state,
155157 } ) ;
156158 }
157-
158159 } catch ( error ) {
159- logger . error ( "Authorization endpoint error" , {
160+ logger . error ( "Authorization endpoint error" , {
160161 error : error instanceof Error ? error . message : error ,
161- stack : error instanceof Error ? error . stack : undefined
162+ stack : error instanceof Error ? error . stack : undefined ,
162163 } ) ;
163-
164+
164165 res . status ( 400 ) . json ( {
165166 error : "server_error" ,
166- error_description : error instanceof Error ? error . message : "Failed to process authorization request"
167+ error_description :
168+ error instanceof Error
169+ ? error . message
170+ : "Failed to process authorization request" ,
167171 } ) ;
168172 }
169173 } ;
@@ -177,31 +181,33 @@ export function createTokenHandler(oauthServer: OAuth2Server) {
177181 try {
178182 const request = new ( OAuth2Server as any ) . Request ( req ) ;
179183 const response = new ( OAuth2Server as any ) . Response ( res ) ;
180-
184+
181185 const token = await oauthServer . token ( request , response ) ;
182-
183- logger . info ( "Access token granted" , {
186+
187+ logger . info ( "Access token granted" , {
184188 clientId : token . client . id ,
185189 userId : token . user ?. id ,
186- scope : token . scope
190+ scope : token . scope ,
187191 } ) ;
188192
189193 res . json ( {
190194 access_token : token . accessToken ,
191195 token_type : "Bearer" ,
192- expires_in : Math . floor ( ( token . accessTokenExpiresAt ! . getTime ( ) - Date . now ( ) ) / 1000 ) ,
193- scope : Array . isArray ( token . scope ) ? token . scope . join ( ' ' ) : token . scope ,
194- refresh_token : token . refreshToken
196+ expires_in : Math . floor (
197+ ( token . accessTokenExpiresAt ! . getTime ( ) - Date . now ( ) ) / 1000 ,
198+ ) ,
199+ scope : Array . isArray ( token . scope ) ? token . scope . join ( " " ) : token . scope ,
200+ refresh_token : token . refreshToken ,
195201 } ) ;
196-
197202 } catch ( error ) {
198- logger . error ( "Token endpoint error" , {
199- error : error instanceof Error ? error . message : error
203+ logger . error ( "Token endpoint error" , {
204+ error : error instanceof Error ? error . message : error ,
200205 } ) ;
201-
206+
202207 res . status ( 400 ) . json ( {
203208 error : "invalid_request" ,
204- error_description : error instanceof Error ? error . message : "Token request failed"
209+ error_description :
210+ error instanceof Error ? error . message : "Token request failed" ,
205211 } ) ;
206212 }
207213 } ;
@@ -215,29 +221,28 @@ export function createIntrospectionHandler(oauthServer: OAuth2Server) {
215221 try {
216222 const request = new ( OAuth2Server as any ) . Request ( req ) ;
217223 const response = new ( OAuth2Server as any ) . Response ( res ) ;
218-
224+
219225 const token = await oauthServer . authenticate ( request , response ) ;
220-
221- logger . info ( "Token introspection successful" , {
226+
227+ logger . info ( "Token introspection successful" , {
222228 clientId : token . client . id ,
223229 userId : token . user ?. id ,
224- scope : token . scope
230+ scope : token . scope ,
225231 } ) ;
226232
227233 res . json ( {
228234 active : true ,
229- scope : Array . isArray ( token . scope ) ? token . scope . join ( ' ' ) : token . scope ,
235+ scope : Array . isArray ( token . scope ) ? token . scope . join ( " " ) : token . scope ,
230236 client_id : token . client . id ,
231237 username : token . user ?. username ,
232238 sub : token . user ?. id ,
233- exp : Math . floor ( ( token . accessTokenExpiresAt ?. getTime ( ) || 0 ) / 1000 )
239+ exp : Math . floor ( ( token . accessTokenExpiresAt ?. getTime ( ) || 0 ) / 1000 ) ,
234240 } ) ;
235-
236241 } catch ( error ) {
237- logger . debug ( "Token introspection failed" , {
238- error : error instanceof Error ? error . message : error
242+ logger . debug ( "Token introspection failed" , {
243+ error : error instanceof Error ? error . message : error ,
239244 } ) ;
240-
245+
241246 res . json ( { active : false } ) ;
242247 }
243248 } ;
@@ -251,20 +256,19 @@ export function createRevocationHandler(oauthServer: OAuth2Server) {
251256 try {
252257 const request = new ( OAuth2Server as any ) . Request ( req ) ;
253258 const response = new ( OAuth2Server as any ) . Response ( res ) ;
254-
259+
255260 await oauthServer . revoke ( request , response ) ;
256-
261+
257262 logger . info ( "Token revoked successfully" ) ;
258263 res . status ( 200 ) . send ( ) ;
259-
260264 } catch ( error ) {
261- logger . error ( "Token revocation error" , {
262- error : error instanceof Error ? error . message : error
265+ logger . error ( "Token revocation error" , {
266+ error : error instanceof Error ? error . message : error ,
263267 } ) ;
264268 res . status ( 400 ) . json ( {
265269 error : "invalid_request" ,
266- error_description : "Failed to revoke token"
270+ error_description : "Failed to revoke token" ,
267271 } ) ;
268272 }
269273 } ;
270- }
274+ }
0 commit comments