From 579899c397614cd06a61480c9eca1142c519e4af Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sun, 13 Nov 2022 01:22:21 +0530 Subject: [PATCH] fix(server): creepy @@ string split logic for auth_token --- server/handlers/authorize.go | 8 ++++---- server/handlers/oauth_callback.go | 5 ++++- server/handlers/token.go | 2 +- server/handlers/verify_email.go | 2 +- server/resolvers/login.go | 5 ++--- server/resolvers/magic_link_login.go | 3 ++- server/resolvers/session.go | 2 +- server/resolvers/signup.go | 2 +- server/resolvers/verify_email.go | 2 +- server/resolvers/verify_otp.go | 2 +- server/test/validate_jwt_token_test.go | 2 +- server/token/auth_token.go | 15 ++------------- 12 files changed, 21 insertions(+), 29 deletions(-) diff --git a/server/handlers/authorize.go b/server/handlers/authorize.go index 7bf97b2..171e343 100644 --- a/server/handlers/authorize.go +++ b/server/handlers/authorize.go @@ -16,7 +16,7 @@ jargons login resolver has optional param state -if state found in store, split with @@ - if len > 1 -> response type is code and has code + challenge - - set `nonce@@code` for createAuthToken request so that `c_hash` can be generated + - set `nonce, code` for createAuthToken request so that `c_hash` can be generated - do not add `nonce` to id_token in code flow, instead set `c_hash` and `at_hash` @@ -26,8 +26,8 @@ jargons - add &nonce to login redirect url login resolver has optional param state - if state found in store, split with @@ - - if len < 1 -> response type is token / id_token and has nonce - - send received nonce for createAuthToken + - if len < 1 -> response type is token / id_token and value is nonce + - send received nonce for createAuthToken with empty code value - set `nonce` and `at_hash` in `id_token` **/ @@ -277,7 +277,7 @@ func AuthorizeHandler() gin.HandlerFunc { if responseType == constants.ResponseTypeToken || responseType == constants.ResponseTypeIDToken { hostname := parsers.GetHost(gc) // rollover the session for security - authToken, err := token.CreateAuthToken(gc, user, claims.Roles, scope, claims.LoginMethod, nonce) + authToken, err := token.CreateAuthToken(gc, user, claims.Roles, scope, claims.LoginMethod, nonce, "") if err != nil { log.Debug("CreateAuthToken failed: ", err) handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK) diff --git a/server/handlers/oauth_callback.go b/server/handlers/oauth_callback.go index 20e256f..2dfe2c5 100644 --- a/server/handlers/oauth_callback.go +++ b/server/handlers/oauth_callback.go @@ -197,8 +197,11 @@ func OAuthCallbackHandler() gin.HandlerFunc { } } + // TODO + // use stateValue to get code / nonce + // add code / nonce to id_token nonce := uuid.New().String() - authToken, err := token.CreateAuthToken(ctx, user, inputRoles, scopes, provider, nonce) + authToken, err := token.CreateAuthToken(ctx, user, inputRoles, scopes, provider, nonce, "") if err != nil { log.Debug("Failed to create auth token: ", err) ctx.JSON(500, gin.H{"error": err.Error()}) diff --git a/server/handlers/token.go b/server/handlers/token.go index 9a9ca1f..5e80ada 100644 --- a/server/handlers/token.go +++ b/server/handlers/token.go @@ -246,7 +246,7 @@ func TokenHandler() gin.HandlerFunc { fmt.Println("=> code", code) fmt.Println("=> nonce", nonce) - authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod, nonce) + authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod, nonce, code) if err != nil { log.Debug("Error creating auth token: ", err) gc.JSON(http.StatusUnauthorized, gin.H{ diff --git a/server/handlers/verify_email.go b/server/handlers/verify_email.go index c0f0283..c57d0e2 100644 --- a/server/handlers/verify_email.go +++ b/server/handlers/verify_email.go @@ -101,7 +101,7 @@ func VerifyEmailHandler() gin.HandlerFunc { } nonce := uuid.New().String() - authToken, err := token.CreateAuthToken(c, user, roles, scope, loginMethod, nonce) + authToken, err := token.CreateAuthToken(c, user, roles, scope, loginMethod, nonce, "") if err != nil { log.Debug("Error creating auth token: ", err) errorRes["error_description"] = err.Error() diff --git a/server/resolvers/login.go b/server/resolvers/login.go index 5e59bc6..6a724a8 100644 --- a/server/resolvers/login.go +++ b/server/resolvers/login.go @@ -155,7 +155,6 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes codeChallenge = authorizeStateSplit[1] fmt.Println("=> code info", authorizeStateSplit) - nonce = nonce + "@@" + code } else { nonce = authorizeState } @@ -163,7 +162,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes } } - authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce) + authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce, code) if err != nil { log.Debug("Failed to create auth token", err) return res, err @@ -186,8 +185,8 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes sessionStoreKey := constants.AuthRecipeMethodBasicAuth + ":" + user.ID memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash) memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token) + // TODO add to other login options as well // Code challenge could be optional if PKCE flow is not used - if code != "" { fmt.Println("=> setting the state here....") if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil { diff --git a/server/resolvers/magic_link_login.go b/server/resolvers/magic_link_login.go index 611c47f..bcc7ce2 100644 --- a/server/resolvers/magic_link_login.go +++ b/server/resolvers/magic_link_login.go @@ -15,6 +15,7 @@ import ( "github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/memorystore" "github.com/authorizerdev/authorizer/server/parsers" + "github.com/authorizerdev/authorizer/server/refs" "github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/utils" "github.com/authorizerdev/authorizer/server/validators" @@ -185,7 +186,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu } redirectURLParams := "&roles=" + strings.Join(inputRoles, ",") if params.State != nil { - redirectURLParams = redirectURLParams + "&state=" + *params.State + redirectURLParams = redirectURLParams + "&state=" + refs.StringValue(params.State) } if params.Scope != nil && len(params.Scope) > 0 { redirectURLParams = redirectURLParams + "&scope=" + strings.Join(params.Scope, " ") diff --git a/server/resolvers/session.go b/server/resolvers/session.go index 7bc0e72..79ea012 100644 --- a/server/resolvers/session.go +++ b/server/resolvers/session.go @@ -72,7 +72,7 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod } nonce := uuid.New().String() - authToken, err := token.CreateAuthToken(gc, user, claimRoles, scope, claims.LoginMethod, nonce) + authToken, err := token.CreateAuthToken(gc, user, claimRoles, scope, claims.LoginMethod, nonce, "") if err != nil { log.Debug("Failed to create auth token: ", err) return res, err diff --git a/server/resolvers/signup.go b/server/resolvers/signup.go index 06a477c..3df520f 100644 --- a/server/resolvers/signup.go +++ b/server/resolvers/signup.go @@ -258,7 +258,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR nonce = nonce + "@@" + code } - authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce) + authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce, code) if err != nil { log.Debug("Failed to create auth token: ", err) return res, err diff --git a/server/resolvers/verify_email.go b/server/resolvers/verify_email.go index 37cd7b2..7dbf404 100644 --- a/server/resolvers/verify_email.go +++ b/server/resolvers/verify_email.go @@ -86,7 +86,7 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m roles := strings.Split(user.Roles, ",") scope := []string{"openid", "email", "profile"} nonce := uuid.New().String() - authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod, nonce) + authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod, nonce, "") if err != nil { log.Debug("Failed to create auth token: ", err) return res, err diff --git a/server/resolvers/verify_otp.go b/server/resolvers/verify_otp.go index 6aeea5f..fd70a9f 100644 --- a/server/resolvers/verify_otp.go +++ b/server/resolvers/verify_otp.go @@ -59,7 +59,7 @@ func VerifyOtpResolver(ctx context.Context, params model.VerifyOTPRequest) (*mod roles := strings.Split(user.Roles, ",") scope := []string{"openid", "email", "profile"} nonce := uuid.New().String() - authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod, nonce) + authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod, nonce, "") if err != nil { log.Debug("Failed to create auth token: ", err) return res, err diff --git a/server/test/validate_jwt_token_test.go b/server/test/validate_jwt_token_test.go index e4e3b45..52ce50b 100644 --- a/server/test/validate_jwt_token_test.go +++ b/server/test/validate_jwt_token_test.go @@ -52,7 +52,7 @@ func validateJwtTokenTest(t *testing.T, s TestSetup) { assert.NoError(t, err) sessionKey := constants.AuthRecipeMethodBasicAuth + ":" + user.ID nonce := uuid.New().String() - authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce) + authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce, "") memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash) memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token) diff --git a/server/token/auth_token.go b/server/token/auth_token.go index 1833db3..607f64d 100644 --- a/server/token/auth_token.go +++ b/server/token/auth_token.go @@ -49,18 +49,7 @@ type SessionData struct { } // CreateAuthToken creates a new auth token when userlogs in -func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, loginMethod, nonce string) (*Token, error) { - - code := "" - nonceSplit := strings.Split(nonce, "@@") - fingerPrint := nonce - fmt.Println("=> nonce split", nonceSplit) - if len(nonceSplit) > 1 { - code = nonceSplit[1] - // use original nonce for session token and access token - nonce = nonceSplit[0] - fingerPrint = nonce - } +func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, loginMethod, nonce string, code string) (*Token, error) { fmt.Println("=> original nonce:", nonce) @@ -98,7 +87,7 @@ func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, l } res := &Token{ - FingerPrint: fingerPrint, + FingerPrint: nonce, FingerPrintHash: fingerPrintHash, AccessToken: &JWTToken{Token: accessToken, ExpiresAt: accessTokenExpiresAt}, IDToken: &JWTToken{Token: idToken, ExpiresAt: idTokenExpiresAt},