@@ -253,11 +253,11 @@ func getToken(r *http.Request) string {
253
253
254
254
// helper function to check access token of the client
255
255
// it is done via introspect auth end-point
256
- func checkAccessToken (r * http.Request ) bool {
256
+ func checkAccessToken (r * http.Request ) ( TokenAttributes , error ) {
257
257
// extract token from a request
258
258
token := getToken (r )
259
259
if token == "" {
260
- return false
260
+ return TokenAttributes {}, errors . New ( "no token present in HTTP request" )
261
261
}
262
262
263
263
// first, we inspect our token
@@ -269,7 +269,7 @@ func checkAccessToken(r *http.Request) bool {
269
269
r .Header .Set ("scope" , attrs .Scope )
270
270
r .Header .Set ("client-host" , attrs .ClientHost )
271
271
r .Header .Set ("client-id" , attrs .ClientID )
272
- return true
272
+ return attrs , nil
273
273
}
274
274
275
275
log .Println ("unable to inspect token: " , err )
@@ -280,12 +280,12 @@ func checkAccessToken(r *http.Request) bool {
280
280
if err != nil {
281
281
msg := fmt .Sprintf ("unable to verify token: %+v" , err )
282
282
log .Println (msg )
283
- return false
283
+ return attrs , err
284
284
}
285
285
if ! attrs .Active || attrs .Expiration - time .Now ().Unix () < 0 {
286
286
msg := fmt .Sprintf ("token is invalid: %+v" , attrs )
287
287
log .Println (msg )
288
- return false
288
+ return attrs , errors . New ( "invalid token" )
289
289
}
290
290
if Config .Verbose > 2 {
291
291
if err := printJSON (attrs , "token attributes" ); err != nil {
@@ -296,7 +296,7 @@ func checkAccessToken(r *http.Request) bool {
296
296
r .Header .Set ("scope" , attrs .Scope )
297
297
r .Header .Set ("client-host" , attrs .ClientHost )
298
298
r .Header .Set ("client-id" , attrs .ClientID )
299
- return true
299
+ return attrs , nil
300
300
}
301
301
302
302
// callback handler function performs authentication callback and obtain
@@ -407,95 +407,112 @@ func oauthRequestHandler(w http.ResponseWriter, r *http.Request) {
407
407
sessLock .Unlock ()
408
408
}
409
409
oauthState := uuid .New ().String ()
410
+
411
+ // check userinfo in the session or if client provides valid access token.
410
412
sessLock .Lock ()
411
413
sess .Set ("somestate" , oauthState )
412
414
if sess .Get ("path" ) == nil || sess .Get ("path" ) == "" {
413
415
sess .Set ("path" , r .URL .Path )
414
416
}
415
- // checking the userinfo in the session or if client provides valid access token.
416
- // if either is present we'll allow user request
417
417
userInfo := sess .Get ("userinfo" )
418
418
sessLock .Unlock ()
419
- hasToken := checkAccessToken (r )
420
- var accept string
421
- if v , ok := r .Header ["Accept" ]; ok {
422
- if len (v ) > 0 {
423
- accept = v [0 ]
419
+ attrs , err := checkAccessToken (r )
420
+ if err != nil {
421
+ // there is no proper authentication yet, redirect users to auth callback
422
+ aurl := OAuth2Config .AuthCodeURL (oauthState )
423
+ if Config .Verbose > 0 {
424
+ log .Println ("auth redirect to" , aurl )
424
425
}
426
+ status = http .StatusFound
427
+ http .Redirect (w , r , aurl , status )
428
+ return
425
429
}
426
- if hasToken && ! strings .Contains (r .URL .Path , "token" ) {
427
- // case of existing token CERN SSO or IAM and we not asked for token path
428
- token := getToken (r )
429
- if token == "" {
430
- http .Error (w , "unable to get user token" , http .StatusUnauthorized )
430
+
431
+ // if user wants to renew token
432
+ if r .URL .Path == fmt .Sprintf ("%s/token/renew" , Config .Base ) {
433
+ var token string
434
+ sessLock .Lock ()
435
+ t := sess .Get ("refreshToken" )
436
+ sessLock .Unlock ()
437
+ if t == nil { // cli request
438
+ token = getToken (r )
439
+ } else {
440
+ token = t .(string )
441
+ }
442
+ tokenInfo , err := renewToken (token , r )
443
+ if err != nil {
444
+ msg := fmt .Sprintf ("unable to refresh access token, %v" , err )
445
+ status = http .StatusInternalServerError
446
+ http .Error (w , msg , status )
431
447
return
432
448
}
433
- attrs , err := inspectTokenProviders (token )
449
+ if Config .Verbose > 2 {
450
+ printJSON (tokenInfo , "new token info" )
451
+ }
452
+ if ! strings .Contains (strings .ToLower (r .Header .Get ("Accept" )), "json" ) {
453
+ w .Write ([]byte (tokenInfo .String ()))
454
+ return
455
+ }
456
+ data , err := json .Marshal (tokenInfo )
434
457
if err != nil {
435
- log .Println ("fail to inspect user token" , err )
436
- http .Error (w , "unable to get user token" , http .StatusInternalServerError )
458
+ msg := fmt .Sprintf ("unable to marshal token info, %v" , err )
459
+ status = http .StatusInternalServerError
460
+ http .Error (w , msg , status )
437
461
return
438
462
}
439
- // in case of IAM token we'll get token attributes as user info
440
- userData ["email" ] = attrs .Email
441
- userData ["id" ] = attrs .ClientID
442
- userData ["name" ] = attrs .UserName
443
- userData ["exp" ] = attrs .Expiration
444
- // set CMS headers
445
- if Config .CMSHeaders {
446
- if Config .Verbose > 2 {
447
- if err := printJSON (userData , "user data" ); err != nil {
448
- log .Println ("unable to print user data" )
463
+ w .Write (data )
464
+ return
465
+ }
466
+ // if user wants to see token
467
+ if r .URL .Path == fmt .Sprintf ("%s/token" , Config .Base ) {
468
+ var token , rtoken string
469
+ sessLock .Lock ()
470
+ t := sess .Get ("rawIDToken" )
471
+ rt := sess .Get ("refreshToken" )
472
+ sessLock .Unlock ()
473
+ if t == nil { // cli request
474
+ token = getToken (r )
475
+ } else {
476
+ token = t .(string )
477
+ }
478
+ if rt == nil { // cli request
479
+ if v , ok := r .Header ["Refresh-Token" ]; ok {
480
+ if len (v ) == 1 {
481
+ rtoken = v [0 ]
449
482
}
450
483
}
451
- if Config .Verbose > 3 {
452
- CMSAuth .SetCMSHeadersByKey (r , userData , CricRecords , "id" , "oauth" , true )
453
- } else {
454
- CMSAuth .SetCMSHeadersByKey (r , userData , CricRecords , "id" , "oauth" , false )
455
- }
456
- if Config .Verbose > 0 {
457
- printHTTPRequest (r , "cms headers" )
458
- }
484
+ } else {
485
+ rtoken = rt .(string )
459
486
}
460
- redirect (w , r )
461
- return
462
- } else if userInfo != nil || hasToken {
463
- // renew existing token
464
- if r .URL .Path == fmt .Sprintf ("%s/token/renew" , Config .Base ) {
465
- var token string
466
- sessLock .Lock ()
467
- t := sess .Get ("refreshToken" )
468
- sessLock .Unlock ()
469
- if t == nil { // cli request
470
- token = getToken (r )
471
- } else {
472
- token = t .(string )
473
- }
474
- tokenInfo , err := renewToken (token , r )
475
- if err != nil {
476
- msg := fmt .Sprintf ("unable to refresh access token, %v" , err )
477
- status = http .StatusInternalServerError
478
- http .Error (w , msg , status )
479
- return
480
- }
481
- if Config .Verbose > 2 {
482
- printJSON (tokenInfo , "new token info" )
483
- }
484
- if ! strings .Contains (strings .ToLower (accept ), "json" ) {
485
- w .Write ([]byte (tokenInfo .String ()))
486
- return
487
- }
488
- data , err := json .Marshal (tokenInfo )
489
- if err != nil {
490
- msg := fmt .Sprintf ("unable to marshal token info, %v" , err )
491
- status = http .StatusInternalServerError
492
- http .Error (w , msg , status )
493
- return
494
- }
495
- w .Write (data )
487
+ var texp , rtexp int64
488
+ sessLock .Lock ()
489
+ if sess .Get ("accessExpire" ) != nil {
490
+ texp = sess .Get ("accessExpire" ).(int64 )
491
+ }
492
+ if sess .Get ("refreshExpire" ) != nil {
493
+ rtexp = sess .Get ("refreshExpire" ).(int64 )
494
+ }
495
+ sessLock .Unlock ()
496
+ tokenInfo := TokenInfo {AccessToken : token , RefreshToken : rtoken , AccessExpire : texp , RefreshExpire : rtexp , IDToken : token }
497
+ if ! strings .Contains (strings .ToLower (r .Header .Get ("Accept" )), "json" ) {
498
+ w .Write ([]byte (tokenInfo .String ()))
499
+ return
500
+ }
501
+ data , err := json .Marshal (tokenInfo )
502
+ if err != nil {
503
+ msg := fmt .Sprintf ("unable to marshal token info, %v" , err )
504
+ status = http .StatusInternalServerError
505
+ http .Error (w , msg , status )
496
506
return
497
507
}
498
- // decode userInfo
508
+ w .Write (data )
509
+ return
510
+ }
511
+
512
+ // fill out user data
513
+ if userInfo != nil {
514
+ // request through CERN SSO web interface which fills out user info
515
+ // which we use to initialize user data
499
516
switch t := userInfo .(type ) {
500
517
case * json.RawMessage :
501
518
err := json .Unmarshal (* t , & userData )
@@ -506,78 +523,33 @@ func oauthRequestHandler(w http.ResponseWriter, r *http.Request) {
506
523
return
507
524
}
508
525
}
509
- // set CMS headers
510
- if Config .CMSHeaders {
511
- if Config .Verbose > 2 {
512
- if err := printJSON (userData , "user data" ); err != nil {
513
- log .Println ("unable to print user data" )
514
- }
515
- }
516
- if Config .Verbose > 3 {
517
- CMSAuth .SetCMSHeadersByKey (r , userData , CricRecords , "id" , "oauth" , true )
518
- } else {
519
- CMSAuth .SetCMSHeadersByKey (r , userData , CricRecords , "id" , "oauth" , false )
520
- }
521
- if Config .Verbose > 0 {
522
- printHTTPRequest (r , "cms headers" )
526
+ } else {
527
+ // in case of existing token CERN SSO or IAM we use token attributes as user data
528
+ userData ["email" ] = attrs .Email
529
+ userData ["id" ] = attrs .ClientID
530
+ userData ["name" ] = attrs .UserName
531
+ userData ["exp" ] = attrs .Expiration
532
+ }
533
+
534
+ // set CMS headers
535
+ if Config .CMSHeaders {
536
+ if Config .Verbose > 2 {
537
+ if err := printJSON (userData , "user data" ); err != nil {
538
+ log .Println ("unable to print user data" )
523
539
}
524
540
}
525
- // return token back to the user
526
- if r .URL .Path == fmt .Sprintf ("%s/token" , Config .Base ) {
527
- var token , rtoken string
528
- sessLock .Lock ()
529
- t := sess .Get ("rawIDToken" )
530
- rt := sess .Get ("refreshToken" )
531
- sessLock .Unlock ()
532
- if t == nil { // cli request
533
- token = getToken (r )
534
- } else {
535
- token = t .(string )
536
- }
537
- if rt == nil { // cli request
538
- if v , ok := r .Header ["Refresh-Token" ]; ok {
539
- if len (v ) == 1 {
540
- rtoken = v [0 ]
541
- }
542
- }
543
- } else {
544
- rtoken = rt .(string )
545
- }
546
- var texp , rtexp int64
547
- sessLock .Lock ()
548
- if sess .Get ("accessExpire" ) != nil {
549
- texp = sess .Get ("accessExpire" ).(int64 )
550
- }
551
- if sess .Get ("refreshExpire" ) != nil {
552
- rtexp = sess .Get ("refreshExpire" ).(int64 )
553
- }
554
- sessLock .Unlock ()
555
- tokenInfo := TokenInfo {AccessToken : token , RefreshToken : rtoken , AccessExpire : texp , RefreshExpire : rtexp , IDToken : token }
556
- if ! strings .Contains (strings .ToLower (accept ), "json" ) {
557
- w .Write ([]byte (tokenInfo .String ()))
558
- return
559
- }
560
- data , err := json .Marshal (tokenInfo )
561
- if err != nil {
562
- msg := fmt .Sprintf ("unable to marshal token info, %v" , err )
563
- status = http .StatusInternalServerError
564
- http .Error (w , msg , status )
565
- return
566
- }
567
- w .Write (data )
568
- return
541
+ if Config .Verbose > 3 {
542
+ CMSAuth .SetCMSHeadersByKey (r , userData , CricRecords , "id" , "oauth" , true )
543
+ } else {
544
+ CMSAuth .SetCMSHeadersByKey (r , userData , CricRecords , "id" , "oauth" , false )
545
+ }
546
+ if Config .Verbose > 0 {
547
+ printHTTPRequest (r , "cms headers" )
569
548
}
570
- redirect (w , r )
571
- return
572
- }
573
- // there is no proper authentication yet, redirect users to auth callback
574
- aurl := OAuth2Config .AuthCodeURL (oauthState )
575
- if Config .Verbose > 0 {
576
- log .Println ("auth redirect to" , aurl )
577
549
}
578
- status = http . StatusFound
579
- http . Redirect ( w , r , aurl , status )
580
- return
550
+
551
+ // redirect HTTP requests
552
+ redirect ( w , r )
581
553
}
582
554
583
555
// oauth server provides reverse proxy functionality with
0 commit comments