1- import { verifyAndExchangeCode , ACCESS_TOKEN_TTL_SECONDS } from '@/features/oauth/server' ;
1+ import { verifyAndExchangeCode , verifyAndRotateRefreshToken , ACCESS_TOKEN_TTL_SECONDS } from '@/ee /features/oauth/server' ;
22import { apiHandler } from '@/lib/apiHandler' ;
33import { hasEntitlement } from '@sourcebot/shared' ;
44import { NextRequest } from 'next/server' ;
@@ -17,45 +17,86 @@ export const POST = apiHandler(async (request: NextRequest) => {
1717 const formData = await request . formData ( ) ;
1818
1919 const grantType = formData . get ( 'grant_type' ) ;
20- if ( grantType !== 'authorization_code' ) {
21- return Response . json (
22- { error : 'unsupported_grant_type' , error_description : 'Only authorization_code is supported.' } ,
23- { status : 400 }
24- ) ;
25- }
26-
27- const code = formData . get ( 'code' ) ;
2820 const clientId = formData . get ( 'client_id' ) ;
29- const redirectUri = formData . get ( 'redirect_uri' ) ;
30- const codeVerifier = formData . get ( 'code_verifier' ) ;
3121 const resource = formData . get ( 'resource' ) ;
3222
33- if ( ! code || ! clientId || ! redirectUri || ! codeVerifier ) {
23+ if ( ! clientId ) {
3424 return Response . json (
35- { error : 'invalid_request' , error_description : 'Missing required parameters: code, client_id, redirect_uri, code_verifier .' } ,
25+ { error : 'invalid_request' , error_description : 'Missing required parameter: client_id.' } ,
3626 { status : 400 }
3727 ) ;
3828 }
3929
40- const result = await verifyAndExchangeCode ( {
41- rawCode : code . toString ( ) ,
42- clientId : clientId . toString ( ) ,
43- redirectUri : redirectUri . toString ( ) ,
44- codeVerifier : codeVerifier . toString ( ) ,
45- resource : resource ? resource . toString ( ) : null ,
46- } ) ;
30+ if ( grantType === 'authorization_code' ) {
31+ const code = formData . get ( 'code' ) ;
32+ const redirectUri = formData . get ( 'redirect_uri' ) ;
33+ const codeVerifier = formData . get ( 'code_verifier' ) ;
4734
48- if ( 'error' in result ) {
49- return Response . json (
50- { error : result . error , error_description : result . errorDescription } ,
51- { status : 400 }
52- ) ;
35+ if ( ! code || ! redirectUri || ! codeVerifier ) {
36+ return Response . json (
37+ { error : 'invalid_request' , error_description : 'Missing required parameters: code, redirect_uri, code_verifier.' } ,
38+ { status : 400 }
39+ ) ;
40+ }
41+
42+ const result = await verifyAndExchangeCode ( {
43+ rawCode : code . toString ( ) ,
44+ clientId : clientId . toString ( ) ,
45+ redirectUri : redirectUri . toString ( ) ,
46+ codeVerifier : codeVerifier . toString ( ) ,
47+ resource : resource ? resource . toString ( ) : null ,
48+ } ) ;
49+
50+ if ( 'error' in result ) {
51+ return Response . json (
52+ { error : result . error , error_description : result . errorDescription } ,
53+ { status : 400 }
54+ ) ;
55+ }
56+
57+ return Response . json ( {
58+ access_token : result . token ,
59+ refresh_token : result . refreshToken ,
60+ token_type : 'Bearer' ,
61+ expires_in : ACCESS_TOKEN_TTL_SECONDS ,
62+ scope : '' ,
63+ } ) ;
64+ }
65+
66+ if ( grantType === 'refresh_token' ) {
67+ const rawRefreshToken = formData . get ( 'refresh_token' ) ;
68+
69+ if ( ! rawRefreshToken ) {
70+ return Response . json (
71+ { error : 'invalid_request' , error_description : 'Missing required parameter: refresh_token.' } ,
72+ { status : 400 }
73+ ) ;
74+ }
75+
76+ const result = await verifyAndRotateRefreshToken ( {
77+ rawRefreshToken : rawRefreshToken . toString ( ) ,
78+ clientId : clientId . toString ( ) ,
79+ resource : resource ? resource . toString ( ) : null ,
80+ } ) ;
81+
82+ if ( 'error' in result ) {
83+ return Response . json (
84+ { error : result . error , error_description : result . errorDescription } ,
85+ { status : 400 }
86+ ) ;
87+ }
88+
89+ return Response . json ( {
90+ access_token : result . token ,
91+ refresh_token : result . refreshToken ,
92+ token_type : 'Bearer' ,
93+ expires_in : ACCESS_TOKEN_TTL_SECONDS ,
94+ scope : '' ,
95+ } ) ;
5396 }
5497
55- return Response . json ( {
56- access_token : result . token ,
57- token_type : 'Bearer' ,
58- expires_in : ACCESS_TOKEN_TTL_SECONDS ,
59- scope : '' ,
60- } ) ;
98+ return Response . json (
99+ { error : 'unsupported_grant_type' , error_description : 'Supported grant types: authorization_code, refresh_token.' } ,
100+ { status : 400 }
101+ ) ;
61102} ) ;
0 commit comments