@@ -60,13 +60,22 @@ Basic transparent proxy:
60
60
61
61
thv proxy my-server --target-uri http://localhost:8080
62
62
63
- Proxy with OAuth authentication to remote server:
63
+ Proxy with OIDC authentication to remote server:
64
64
65
65
thv proxy my-server --target-uri https://api.example.com \
66
66
--remote-auth --remote-auth-issuer https://auth.example.com \
67
67
--remote-auth-client-id my-client-id \
68
68
--remote-auth-client-secret-file /path/to/secret
69
69
70
+ Proxy with non-OIDC OAuth authentication to remote server:
71
+
72
+ thv proxy my-server --target-uri https://api.example.com \
73
+ --remote-auth \
74
+ --remote-auth-authorize-url https://auth.example.com/oauth/authorize \
75
+ --remote-auth-token-url https://auth.example.com/oauth/token \
76
+ --remote-auth-client-id my-client-id \
77
+ --remote-auth-client-secret-file /path/to/secret
78
+
70
79
Proxy with OIDC protection for incoming requests:
71
80
72
81
thv proxy my-server --target-uri http://localhost:8080 \
@@ -98,6 +107,10 @@ var (
98
107
remoteAuthTimeout time.Duration
99
108
remoteAuthCallbackPort int
100
109
enableRemoteAuth bool
110
+
111
+ // Manual OAuth endpoint configuration
112
+ remoteAuthAuthorizeURL string
113
+ remoteAuthTokenURL string
101
114
)
102
115
103
116
// Default timeout constants
@@ -141,14 +154,18 @@ func init() {
141
154
"OAuth client secret for remote server authentication (optional for PKCE)" )
142
155
proxyCmd .Flags ().StringVar (& remoteAuthClientSecretFile , "remote-auth-client-secret-file" , "" ,
143
156
"Path to file containing OAuth client secret (alternative to --remote-auth-client-secret)" )
144
- proxyCmd .Flags ().StringSliceVar (& remoteAuthScopes , "remote-auth-scopes" ,
145
- [] string { "openid" , "profile" , "email" }, " OAuth scopes to request for remote server authentication" )
157
+ proxyCmd .Flags ().StringSliceVar (& remoteAuthScopes , "remote-auth-scopes" , [] string {},
158
+ " OAuth scopes to request for remote server authentication (defaults: OIDC uses 'openid,profile,email') " )
146
159
proxyCmd .Flags ().BoolVar (& remoteAuthSkipBrowser , "remote-auth-skip-browser" , false ,
147
160
"Skip opening browser for remote server OAuth flow" )
148
161
proxyCmd .Flags ().DurationVar (& remoteAuthTimeout , "remote-auth-timeout" , 30 * time .Second ,
149
162
"Timeout for OAuth authentication flow (e.g., 30s, 1m, 2m30s)" )
150
163
proxyCmd .Flags ().IntVar (& remoteAuthCallbackPort , "remote-auth-callback-port" , 8666 ,
151
164
"Port for OAuth callback server during remote authentication (default: 8666)" )
165
+ proxyCmd .Flags ().StringVar (& remoteAuthAuthorizeURL , "remote-auth-authorize-url" , "" ,
166
+ "OAuth authorization endpoint URL (alternative to --remote-auth-issuer for non-OIDC OAuth)" )
167
+ proxyCmd .Flags ().StringVar (& remoteAuthTokenURL , "remote-auth-token-url" , "" ,
168
+ "OAuth token endpoint URL (alternative to --remote-auth-issuer for non-OIDC OAuth)" )
152
169
153
170
// Mark target-uri as required
154
171
if err := proxyCmd .MarkFlagRequired ("target-uri" ); err != nil {
@@ -383,16 +400,34 @@ func performOAuthFlow(ctx context.Context, issuer, clientID, clientSecret string
383
400
scopes []string ) (* oauth2.TokenSource , * oauth.Config , error ) {
384
401
logger .Info ("Starting OAuth authentication flow..." )
385
402
386
- // Create OAuth config from OIDC discovery
387
- oauthConfig , err := oauth .CreateOAuthConfigFromOIDC (
388
- ctx ,
389
- issuer ,
390
- clientID ,
391
- clientSecret ,
392
- scopes ,
393
- true , // Enable PKCE by default for security
394
- remoteAuthCallbackPort ,
395
- )
403
+ var oauthConfig * oauth.Config
404
+ var err error
405
+
406
+ // Check if we have manual OAuth endpoints configured
407
+ if remoteAuthAuthorizeURL != "" && remoteAuthTokenURL != "" {
408
+ logger .Info ("Using manual OAuth configuration" )
409
+ oauthConfig , err = oauth .CreateOAuthConfigManual (
410
+ clientID ,
411
+ clientSecret ,
412
+ remoteAuthAuthorizeURL ,
413
+ remoteAuthTokenURL ,
414
+ scopes ,
415
+ true , // Enable PKCE by default for security
416
+ remoteAuthCallbackPort ,
417
+ )
418
+ } else {
419
+ // Fall back to OIDC discovery
420
+ logger .Info ("Using OIDC discovery" )
421
+ oauthConfig , err = oauth .CreateOAuthConfigFromOIDC (
422
+ ctx ,
423
+ issuer ,
424
+ clientID ,
425
+ clientSecret ,
426
+ scopes ,
427
+ true , // Enable PKCE by default for security
428
+ remoteAuthCallbackPort ,
429
+ )
430
+ }
396
431
if err != nil {
397
432
return nil , nil , fmt .Errorf ("failed to create OAuth config: %w" , err )
398
433
}
@@ -454,14 +489,24 @@ func handleOutgoingAuthentication(ctx context.Context) (*oauth2.TokenSource, *oa
454
489
}
455
490
456
491
if enableRemoteAuth {
457
- // If OAuth is explicitly enabled, use provided configuration
458
- if remoteAuthIssuer == "" {
459
- return nil , nil , fmt .Errorf ("remote-auth-issuer is required when remote authentication is enabled" )
460
- }
492
+ // If OAuth is explicitly enabled, validate configuration
461
493
if remoteAuthClientID == "" {
462
494
return nil , nil , fmt .Errorf ("remote-auth-client-id is required when remote authentication is enabled" )
463
495
}
464
496
497
+ // Check if we have either OIDC issuer or manual OAuth endpoints
498
+ hasOIDCConfig := remoteAuthIssuer != ""
499
+ hasManualConfig := remoteAuthAuthorizeURL != "" && remoteAuthTokenURL != ""
500
+
501
+ if ! hasOIDCConfig && ! hasManualConfig {
502
+ return nil , nil , fmt .Errorf ("either --remote-auth-issuer (for OIDC) or both --remote-auth-authorize-url " +
503
+ "and --remote-auth-token-url (for OAuth) are required" )
504
+ }
505
+
506
+ if hasOIDCConfig && hasManualConfig {
507
+ return nil , nil , fmt .Errorf ("cannot specify both OIDC issuer and manual OAuth endpoints - choose one approach" )
508
+ }
509
+
465
510
return performOAuthFlow (ctx , remoteAuthIssuer , remoteAuthClientID , clientSecret , remoteAuthScopes )
466
511
}
467
512
0 commit comments