@@ -21,7 +21,9 @@ const configSchema = z.object({
2121 OAUTH_SCOPE : z . string ( ) . default ( "openid profile email" ) ,
2222} ) ;
2323
24- export type Config = z . infer < typeof configSchema > ;
24+ export type Config = z . infer < typeof configSchema > & {
25+ BASE_URL : string ;
26+ } ;
2527
2628let config : Config ;
2729
@@ -30,19 +32,25 @@ export function getConfig(): Config {
3032 try {
3133 const parsed = configSchema . parse ( process . env ) ;
3234
35+ if ( ! parsed . BASE_URL ) {
36+ parsed . BASE_URL = `http://localhost:${ parsed . PORT } ` ;
37+ }
38+
3339 // Full mode validation - OAuth Authorization Server with external IdP
3440 if ( parsed . AUTH_MODE === "full" ) {
3541 const requiredVars = [ ] ;
3642 if ( ! parsed . OAUTH_ISSUER ) requiredVars . push ( "OAUTH_ISSUER" ) ;
3743 if ( ! parsed . OAUTH_CLIENT_ID ) requiredVars . push ( "OAUTH_CLIENT_ID" ) ;
38- if ( ! parsed . OAUTH_CLIENT_SECRET ) requiredVars . push ( "OAUTH_CLIENT_SECRET" ) ;
44+ if ( ! parsed . OAUTH_CLIENT_SECRET )
45+ requiredVars . push ( "OAUTH_CLIENT_SECRET" ) ;
3946
4047 // Provide default for OAUTH_REDIRECT_URI if not set
4148 if ( ! parsed . OAUTH_REDIRECT_URI ) {
42- const baseUrl = parsed . BASE_URL || "http://localhost:3000" ;
43- const callbackUrl = new URL ( "/callback" , baseUrl ) ;
49+ const callbackUrl = new URL ( "/callback" , parsed . BASE_URL ) ;
4450 parsed . OAUTH_REDIRECT_URI = callbackUrl . toString ( ) ;
45- console . log ( `⚠️ OAUTH_REDIRECT_URI not set, using default: ${ parsed . OAUTH_REDIRECT_URI } ` ) ;
51+ console . log (
52+ `⚠️ OAUTH_REDIRECT_URI not set, using default: ${ parsed . OAUTH_REDIRECT_URI } ` ,
53+ ) ;
4654 }
4755
4856 if ( requiredVars . length > 0 ) {
@@ -52,21 +60,20 @@ export function getConfig(): Config {
5260 "OAUTH_ISSUER=https://your-domain.auth0.com\n" +
5361 "OAUTH_CLIENT_ID=your-client-id\n" +
5462 "OAUTH_CLIENT_SECRET=your-client-secret\n" +
55- "OAUTH_REDIRECT_URI=http://localhost:3000/callback # Optional, defaults to BASE_URL/callback\n" +
56- "OAUTH_AUDIENCE=your-api-identifier # Optional but recommended"
63+ "OAUTH_REDIRECT_URI=http://localhost:3000/callback # Optional, defaults to BASE_URL/callback or http://localhost:PORT/callback \n" +
64+ "OAUTH_AUDIENCE=your-api-identifier # Optional but recommended" ,
5765 ) ;
5866 }
5967
60- // OAUTH_AUDIENCE is optional but recommended for full mode
68+ // OAUTH_AUDIENCE is optional but recommended when a resource server is used
6169 if ( ! parsed . OAUTH_AUDIENCE ) {
6270 console . warn (
6371 "⚠️ OAUTH_AUDIENCE not set for full mode. Token validation will not check audience.\n" +
64- " For production deployments, consider setting OAUTH_AUDIENCE to your API identifier"
72+ " For production deployments, consider setting OAUTH_AUDIENCE to your API identifier" ,
6573 ) ;
6674 }
6775 }
6876
69- // Resource server mode validation
7077 if ( parsed . AUTH_MODE === "resource_server" ) {
7178 const requiredVars = [ ] ;
7279 if ( ! parsed . OAUTH_ISSUER ) requiredVars . push ( "OAUTH_ISSUER" ) ;
@@ -77,12 +84,12 @@ export function getConfig(): Config {
7784 `AUTH_MODE=resource_server requires OAuth configuration. Missing: ${ requiredVars . join ( ", " ) } \n` +
7885 "Example configuration:\n" +
7986 "OAUTH_ISSUER=https://your-domain.auth0.com\n" +
80- "OAUTH_AUDIENCE=your-api-identifier"
87+ "OAUTH_AUDIENCE=your-api-identifier" ,
8188 ) ;
8289 }
8390 }
8491
85- config = parsed ;
92+ config = parsed as Config ;
8693 } catch ( error ) {
8794 console . error ( "❌ Invalid environment configuration:" , error ) ;
8895 process . exit ( 1 ) ;
0 commit comments