From 274909b7c992c71ec4bd7789ae6c2319f5551a77 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sun, 23 Oct 2022 21:08:08 +0530 Subject: [PATCH] feat: add nonce variable to create auth token --- server/handlers/authorize.go | 53 +++++++------------------- server/handlers/oauth_callback.go | 4 +- server/handlers/token.go | 4 +- server/handlers/verify_email.go | 5 ++- server/resolvers/login.go | 4 +- server/resolvers/session.go | 4 +- server/resolvers/signup.go | 4 +- server/resolvers/verify_email.go | 4 +- server/resolvers/verify_otp.go | 4 +- server/test/validate_jwt_token_test.go | 3 +- server/token/auth_token.go | 12 +++--- 11 files changed, 46 insertions(+), 55 deletions(-) diff --git a/server/handlers/authorize.go b/server/handlers/authorize.go index 373e1ba..f57c98d 100644 --- a/server/handlers/authorize.go +++ b/server/handlers/authorize.go @@ -5,7 +5,6 @@ import ( "net/http" "strconv" "strings" - "time" "github.com/gin-gonic/gin" "github.com/google/uuid" @@ -224,65 +223,39 @@ func AuthorizeHandler() gin.HandlerFunc { if responseType == constants.ResponseTypeToken || responseType == constants.ResponseTypeIDToken { hostname := parsers.GetHost(gc) - nonce := uuid.New().String() - _, fingerPrintHash, err := token.CreateSessionToken(user, nonce, claims.Roles, scope, claims.LoginMethod) - if err != nil { - log.Debug("CreateSessionToken failed: ", err) - handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK) - return - } - accessToken, accessTokenExpiresAt, err := token.CreateAccessToken(user, claims.Roles, scope, hostname, nonce, claims.LoginMethod) - if err != nil { - log.Debug("CreateAccessToken failed: ", err) - handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK) - return - } - - idToken, _, err := token.CreateIDToken(user, claims.Roles, hostname, nonce, claims.LoginMethod) - if err != nil { - log.Debug("CreateIDToken failed: ", err) - handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK) - return - } // rollover the session for security - // authToken, err := token.CreateAuthToken(gc, user, claims.Roles, scope, claims.LoginMethod) - // if err != nil { - // log.Debug("CreateAuthToken failed: ", err) - // handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK) - // return - // } + 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) + return + } - if err := memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+nonce, fingerPrintHash); err != nil { + if err := memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+nonce, authToken.FingerPrintHash); err != nil { log.Debug("SetUserSession failed: ", err) handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK) return } - if err := memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+nonce, accessToken); err != nil { + if err := memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+nonce, authToken.FingerPrintHash); err != nil { log.Debug("SetUserSession failed: ", err) handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK) return } - cookie.SetSession(gc, fingerPrintHash) - - expiresIn := accessTokenExpiresAt - time.Now().Unix() - if expiresIn <= 0 { - expiresIn = 1 - } + cookie.SetSession(gc, authToken.FingerPrintHash) // used of query mode - params := "access_token=" + accessToken + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + state + "&id_token=" + idToken + "&code=" + code + "&nonce=" + nonce + params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(authToken.IDToken.ExpiresAt, 10) + "&state=" + state + "&id_token=" + authToken.IDToken.Token + "&code=" + code res := map[string]interface{}{ - "access_token": accessToken, - "id_token": idToken, + "access_token": authToken.AccessToken.Token, + "id_token": authToken.IDToken.Token, "state": state, "scope": scope, "token_type": "Bearer", - "expires_in": expiresIn, + "expires_in": authToken.AccessToken.ExpiresAt, "code": code, - "nonce": nonce, } if utils.StringSliceContains(scope, "offline_access") { diff --git a/server/handlers/oauth_callback.go b/server/handlers/oauth_callback.go index 02c284c..20e256f 100644 --- a/server/handlers/oauth_callback.go +++ b/server/handlers/oauth_callback.go @@ -13,6 +13,7 @@ import ( "github.com/coreos/go-oidc/v3/oidc" "github.com/gin-gonic/gin" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "golang.org/x/oauth2" @@ -196,7 +197,8 @@ func OAuthCallbackHandler() gin.HandlerFunc { } } - authToken, err := token.CreateAuthToken(ctx, user, inputRoles, scopes, provider) + nonce := uuid.New().String() + 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 da72969..5240b30 100644 --- a/server/handlers/token.go +++ b/server/handlers/token.go @@ -8,6 +8,7 @@ import ( "time" "github.com/gin-gonic/gin" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "github.com/authorizerdev/authorizer/server/constants" @@ -202,7 +203,8 @@ func TokenHandler() gin.HandlerFunc { return } - authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod) + nonce := uuid.New().String() + authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod, nonce) 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 10d4fad..c0f0283 100644 --- a/server/handlers/verify_email.go +++ b/server/handlers/verify_email.go @@ -7,6 +7,7 @@ import ( "time" "github.com/gin-gonic/gin" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "github.com/authorizerdev/authorizer/server/constants" @@ -98,7 +99,9 @@ func VerifyEmailHandler() gin.HandlerFunc { if verificationRequest.Identifier == constants.VerificationTypeMagicLinkLogin { loginMethod = constants.AuthRecipeMethodMagicLinkLogin } - authToken, err := token.CreateAuthToken(c, user, roles, scope, loginMethod) + + nonce := uuid.New().String() + 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 b597ada..7683932 100644 --- a/server/resolvers/login.go +++ b/server/resolvers/login.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "golang.org/x/crypto/bcrypt" @@ -140,7 +141,8 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes }, nil } - authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth) + nonce := uuid.New().String() + authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce) if err != nil { log.Debug("Failed to create auth token", err) return res, err diff --git a/server/resolvers/session.go b/server/resolvers/session.go index dfa4e3d..7bc0e72 100644 --- a/server/resolvers/session.go +++ b/server/resolvers/session.go @@ -6,6 +6,7 @@ import ( "fmt" "time" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "github.com/authorizerdev/authorizer/server/constants" @@ -70,7 +71,8 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod scope = params.Scope } - authToken, err := token.CreateAuthToken(gc, user, claimRoles, scope, claims.LoginMethod) + nonce := uuid.New().String() + 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 d5cd071..3365cd6 100644 --- a/server/resolvers/signup.go +++ b/server/resolvers/signup.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "github.com/authorizerdev/authorizer/server/constants" @@ -242,7 +243,8 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR scope = params.Scope } - authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth) + nonce := uuid.New().String() + authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce) 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 624d08a..37cd7b2 100644 --- a/server/resolvers/verify_email.go +++ b/server/resolvers/verify_email.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "github.com/authorizerdev/authorizer/server/constants" @@ -84,7 +85,8 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m roles := strings.Split(user.Roles, ",") scope := []string{"openid", "email", "profile"} - authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod) + nonce := uuid.New().String() + 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 b792adb..6aeea5f 100644 --- a/server/resolvers/verify_otp.go +++ b/server/resolvers/verify_otp.go @@ -14,6 +14,7 @@ import ( "github.com/authorizerdev/authorizer/server/memorystore" "github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/utils" + "github.com/google/uuid" log "github.com/sirupsen/logrus" ) @@ -57,7 +58,8 @@ func VerifyOtpResolver(ctx context.Context, params model.VerifyOTPRequest) (*mod roles := strings.Split(user.Roles, ",") scope := []string{"openid", "email", "profile"} - authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod) + nonce := uuid.New().String() + 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 0d5358a..db46fab 100644 --- a/server/test/validate_jwt_token_test.go +++ b/server/test/validate_jwt_token_test.go @@ -51,7 +51,8 @@ func validateJwtTokenTest(t *testing.T, s TestSetup) { gc, err := utils.GinContextFromContext(ctx) assert.NoError(t, err) sessionKey := constants.AuthRecipeMethodBasicAuth + ":" + user.ID - authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth) + nonce := uuid.New().String() + 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 4572b6b..152f5b4 100644 --- a/server/token/auth_token.go +++ b/server/token/auth_token.go @@ -10,7 +10,6 @@ import ( "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt" - "github.com/google/uuid" "github.com/robertkrimen/otto" "github.com/authorizerdev/authorizer/server/constants" @@ -68,9 +67,8 @@ func CreateSessionToken(user models.User, nonce string, roles, scope []string, l } // CreateAuthToken creates a new auth token when userlogs in -func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, loginMethod string) (*Token, error) { +func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, loginMethod, nonce string) (*Token, error) { hostname := parsers.GetHost(gc) - nonce := uuid.New().String() _, fingerPrintHash, err := CreateSessionToken(user, nonce, roles, scope, loginMethod) if err != nil { return nil, err @@ -317,6 +315,8 @@ func ValidateBrowserSession(gc *gin.Context, encryptedSession string) (*SessionD // CreateIDToken util to create JWT token, based on // user information, roles config and CUSTOM_ACCESS_TOKEN_SCRIPT +// For response_type (code) / authorization_code grant nonce should be empty +// for implicit flow it should be present to verify with actual state func CreateIDToken(user models.User, roles []string, hostname, nonce, loginMethod string) (string, int64, error) { expireTime, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAccessTokenExpiryTime) if err != nil { @@ -344,9 +344,9 @@ func CreateIDToken(user models.User, roles []string, hostname, nonce, loginMetho return "", 0, err } customClaims := jwt.MapClaims{ - "iss": hostname, - "aud": clientID, - "nonce": nonce, + "iss": hostname, + "aud": clientID, + // "nonce": nonce, "sub": user.ID, "exp": expiresAt, "iat": time.Now().Unix(),