Skip to content

Commit 2a57fe4

Browse files
committed
Refactor code logic for http requests in auth proxy server
1 parent 20219dd commit 2a57fe4

File tree

1 file changed

+116
-144
lines changed

1 file changed

+116
-144
lines changed

oauth.go

Lines changed: 116 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,11 @@ func getToken(r *http.Request) string {
253253

254254
// helper function to check access token of the client
255255
// it is done via introspect auth end-point
256-
func checkAccessToken(r *http.Request) bool {
256+
func checkAccessToken(r *http.Request) (TokenAttributes, error) {
257257
// extract token from a request
258258
token := getToken(r)
259259
if token == "" {
260-
return false
260+
return TokenAttributes{}, errors.New("no token present in HTTP request")
261261
}
262262

263263
// first, we inspect our token
@@ -269,7 +269,7 @@ func checkAccessToken(r *http.Request) bool {
269269
r.Header.Set("scope", attrs.Scope)
270270
r.Header.Set("client-host", attrs.ClientHost)
271271
r.Header.Set("client-id", attrs.ClientID)
272-
return true
272+
return attrs, nil
273273
}
274274

275275
log.Println("unable to inspect token: ", err)
@@ -280,12 +280,12 @@ func checkAccessToken(r *http.Request) bool {
280280
if err != nil {
281281
msg := fmt.Sprintf("unable to verify token: %+v", err)
282282
log.Println(msg)
283-
return false
283+
return attrs, err
284284
}
285285
if !attrs.Active || attrs.Expiration-time.Now().Unix() < 0 {
286286
msg := fmt.Sprintf("token is invalid: %+v", attrs)
287287
log.Println(msg)
288-
return false
288+
return attrs, errors.New("invalid token")
289289
}
290290
if Config.Verbose > 2 {
291291
if err := printJSON(attrs, "token attributes"); err != nil {
@@ -296,7 +296,7 @@ func checkAccessToken(r *http.Request) bool {
296296
r.Header.Set("scope", attrs.Scope)
297297
r.Header.Set("client-host", attrs.ClientHost)
298298
r.Header.Set("client-id", attrs.ClientID)
299-
return true
299+
return attrs, nil
300300
}
301301

302302
// callback handler function performs authentication callback and obtain
@@ -407,95 +407,112 @@ func oauthRequestHandler(w http.ResponseWriter, r *http.Request) {
407407
sessLock.Unlock()
408408
}
409409
oauthState := uuid.New().String()
410+
411+
// check userinfo in the session or if client provides valid access token.
410412
sessLock.Lock()
411413
sess.Set("somestate", oauthState)
412414
if sess.Get("path") == nil || sess.Get("path") == "" {
413415
sess.Set("path", r.URL.Path)
414416
}
415-
// checking the userinfo in the session or if client provides valid access token.
416-
// if either is present we'll allow user request
417417
userInfo := sess.Get("userinfo")
418418
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)
424425
}
426+
status = http.StatusFound
427+
http.Redirect(w, r, aurl, status)
428+
return
425429
}
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)
431447
return
432448
}
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)
434457
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)
437461
return
438462
}
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]
449482
}
450483
}
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)
459486
}
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)
496506
return
497507
}
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
499516
switch t := userInfo.(type) {
500517
case *json.RawMessage:
501518
err := json.Unmarshal(*t, &userData)
@@ -506,78 +523,33 @@ func oauthRequestHandler(w http.ResponseWriter, r *http.Request) {
506523
return
507524
}
508525
}
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")
523539
}
524540
}
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")
569548
}
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)
577549
}
578-
status = http.StatusFound
579-
http.Redirect(w, r, aurl, status)
580-
return
550+
551+
// redirect HTTP requests
552+
redirect(w, r)
581553
}
582554

583555
// oauth server provides reverse proxy functionality with

0 commit comments

Comments
 (0)