From e61dc2f08a4ebc3a59a9249c0b40abc09e32446d Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Mon, 7 Mar 2022 08:31:39 +0530 Subject: [PATCH] fix: oauth login --- server/handlers/authorize.go | 69 ++++++++++++++++++++++++------- server/handlers/oauth_callback.go | 11 +++-- server/handlers/token.go | 28 +++++++++---- server/routes/routes.go | 2 +- templates/authorize.tmpl | 4 +- 5 files changed, 83 insertions(+), 31 deletions(-) diff --git a/server/handlers/authorize.go b/server/handlers/authorize.go index 3450a02..c07bfd2 100644 --- a/server/handlers/authorize.go +++ b/server/handlers/authorize.go @@ -4,8 +4,10 @@ import ( "net/http" "strings" + "github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/envstore" "github.com/authorizerdev/authorizer/server/sessionstore" "github.com/authorizerdev/authorizer/server/token" "github.com/gin-gonic/gin" @@ -27,12 +29,38 @@ func AuthorizeHandler() gin.HandlerFunc { state := strings.TrimSpace(gc.Query("state")) codeChallenge := strings.TrimSpace(gc.Query("code_challenge")) scopeString := strings.TrimSpace(gc.Query("scope")) - scope := []string{} + clientID := strings.TrimSpace(gc.Query("client_id")) template := "authorize.tmpl" + if clientID == "" { + gc.HTML(http.StatusOK, template, gin.H{ + "target_origin": redirectURI, + "authorization_response": map[string]interface{}{ + "type": "authorization_response", + "response": map[string]string{ + "error": "client_id is required", + }, + }, + }) + return + } + + if clientID != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID) { + gc.HTML(http.StatusOK, template, gin.H{ + "target_origin": redirectURI, + "authorization_response": map[string]interface{}{ + "type": "authorization_response", + "response": map[string]string{ + "error": "invalid_client_id", + }, + }, + }) + return + } + if redirectURI == "" { gc.HTML(http.StatusOK, template, gin.H{ - "target_origin": nil, + "target_origin": redirectURI, "authorization_response": map[string]interface{}{ "type": "authorization_response", "response": map[string]string{ @@ -45,7 +73,7 @@ func AuthorizeHandler() gin.HandlerFunc { if state == "" { gc.HTML(http.StatusOK, template, gin.H{ - "target_origin": nil, + "target_origin": redirectURI, "authorization_response": map[string]interface{}{ "type": "authorization_response", "response": map[string]string{ @@ -60,8 +88,11 @@ func AuthorizeHandler() gin.HandlerFunc { responseType = "token" } + var scope []string if scopeString == "" { scope = []string{"openid", "profile", "email"} + } else { + scope = strings.Split(scopeString, " ") } isResponseTypeCode := responseType == "code" @@ -69,7 +100,7 @@ func AuthorizeHandler() gin.HandlerFunc { if !isResponseTypeCode && !isResponseTypeToken { gc.HTML(http.StatusOK, template, gin.H{ - "target_origin": nil, + "target_origin": redirectURI, "authorization_response": map[string]interface{}{ "type": "authorization_response", "response": map[string]string{ @@ -83,7 +114,7 @@ func AuthorizeHandler() gin.HandlerFunc { if isResponseTypeCode { if codeChallenge == "" { gc.HTML(http.StatusBadRequest, template, gin.H{ - "target_origin": nil, + "target_origin": redirectURI, "authorization_response": map[string]interface{}{ "type": "authorization_response", "response": map[string]string{ @@ -98,7 +129,7 @@ func AuthorizeHandler() gin.HandlerFunc { sessionToken, err := cookie.GetSession(gc) if err != nil { gc.HTML(http.StatusOK, template, gin.H{ - "target_origin": nil, + "target_origin": redirectURI, "authorization_response": map[string]interface{}{ "type": "authorization_response", "response": map[string]string{ @@ -114,7 +145,7 @@ func AuthorizeHandler() gin.HandlerFunc { claims, err := token.ValidateBrowserSession(gc, sessionToken) if err != nil { gc.HTML(http.StatusOK, template, gin.H{ - "target_origin": nil, + "target_origin": redirectURI, "authorization_response": map[string]interface{}{ "type": "authorization_response", "response": map[string]string{ @@ -129,7 +160,7 @@ func AuthorizeHandler() gin.HandlerFunc { user, err := db.Provider.GetUserByID(userID) if err != nil { gc.HTML(http.StatusOK, template, gin.H{ - "target_origin": nil, + "target_origin": redirectURI, "authorization_response": map[string]interface{}{ "type": "authorization_response", "response": map[string]string{ @@ -150,7 +181,7 @@ func AuthorizeHandler() gin.HandlerFunc { newSessionTokenData, newSessionToken, err := token.CreateSessionToken(user, nonce, claims.Roles, scope) if err != nil { gc.HTML(http.StatusOK, template, gin.H{ - "target_origin": nil, + "target_origin": redirectURI, "authorization_response": map[string]interface{}{ "type": "authorization_response", "response": map[string]string{ @@ -168,9 +199,12 @@ func AuthorizeHandler() gin.HandlerFunc { sessionstore.SetState(codeChallenge, code+"@"+newSessionToken) gc.HTML(http.StatusOK, template, gin.H{ "target_origin": redirectURI, - "authorization_response": map[string]string{ - "code": code, - "state": state, + "authorization_response": map[string]interface{}{ + "type": "authorization_response", + "response": map[string]string{ + "code": code, + "state": state, + }, }, }) return @@ -181,7 +215,7 @@ func AuthorizeHandler() gin.HandlerFunc { authToken, err := token.CreateAuthToken(gc, user, claims.Roles, scope) if err != nil { gc.HTML(http.StatusOK, template, gin.H{ - "target_origin": nil, + "target_origin": redirectURI, "authorization_response": map[string]interface{}{ "type": "authorization_response", "response": map[string]string{ @@ -213,15 +247,18 @@ func AuthorizeHandler() gin.HandlerFunc { } gc.HTML(http.StatusOK, template, gin.H{ - "target_origin": redirectURI, - "authorization_response": res, + "target_origin": redirectURI, + "authorization_response": map[string]interface{}{ + "type": "authorization_response", + "response": res, + }, }) return } // by default return with error gc.HTML(http.StatusOK, template, gin.H{ - "target_origin": nil, + "target_origin": redirectURI, "authorization_response": map[string]interface{}{ "type": "authorization_response", "response": map[string]string{ diff --git a/server/handlers/oauth_callback.go b/server/handlers/oauth_callback.go index b16c789..81aea1e 100644 --- a/server/handlers/oauth_callback.go +++ b/server/handlers/oauth_callback.go @@ -21,6 +21,7 @@ import ( "github.com/authorizerdev/authorizer/server/utils" "github.com/coreos/go-oidc/v3/oidc" "github.com/gin-gonic/gin" + "github.com/google/uuid" "golang.org/x/oauth2" ) @@ -146,10 +147,14 @@ func OAuthCallbackHandler() gin.HandlerFunc { // TODO use query param scope := []string{"openid", "email", "profile"} - authToken, _ := token.CreateAuthToken(c, user, inputRoles, scope) + nonce := uuid.New().String() + _, newSessionToken, err := token.CreateSessionToken(user, nonce, inputRoles, scope) + if err != nil { + c.JSON(500, gin.H{"error": err.Error()}) + } - sessionstore.SetState(authToken.FingerPrint, user.ID) - cookie.SetSession(c, authToken.FingerPrintHash) + sessionstore.SetState(newSessionToken, nonce+"@"+user.ID) + cookie.SetSession(c, newSessionToken) go utils.SaveSessionInDB(c, user.ID) c.Redirect(http.StatusTemporaryRedirect, redirectURL) } diff --git a/server/handlers/token.go b/server/handlers/token.go index 6d852d1..4a18a4d 100644 --- a/server/handlers/token.go +++ b/server/handlers/token.go @@ -6,8 +6,10 @@ import ( "net/http" "strings" + "github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/envstore" "github.com/authorizerdev/authorizer/server/sessionstore" "github.com/authorizerdev/authorizer/server/token" "github.com/gin-gonic/gin" @@ -26,7 +28,23 @@ func TokenHandler() gin.HandlerFunc { codeVerifier := strings.TrimSpace(reqBody["code_verifier"]) code := strings.TrimSpace(reqBody["code"]) - redirectURI := strings.TrimSpace(reqBody["redirect_uri"]) + clientID := strings.TrimSpace(reqBody["client_id"]) + + if clientID == "" { + gc.JSON(http.StatusBadRequest, gin.H{ + "error": "client_id_required", + "error_description": "The client id is required", + }) + return + } + + if clientID != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID) { + gc.JSON(http.StatusBadRequest, gin.H{ + "error": "invalid_client_id", + "error_description": "The client id is invalid", + }) + return + } if codeVerifier == "" { gc.JSON(http.StatusBadRequest, gin.H{ @@ -44,14 +62,6 @@ func TokenHandler() gin.HandlerFunc { return } - if redirectURI == "" { - gc.JSON(http.StatusBadRequest, gin.H{ - "error": "invalid_redirect_uri", - "error_description": "The redirect URI is required", - }) - return - } - hash := sha256.New() hash.Write([]byte(codeVerifier)) encryptedCode := strings.ReplaceAll(base64.URLEncoding.EncodeToString(hash.Sum(nil)), "+", "-") diff --git a/server/routes/routes.go b/server/routes/routes.go index 89b6073..6b99d3a 100644 --- a/server/routes/routes.go +++ b/server/routes/routes.go @@ -26,7 +26,7 @@ func InitRouter() *gin.Engine { router.GET("/authorize", handlers.AuthorizeHandler()) router.GET("/userinfo", handlers.UserInfoHandler()) router.GET("/logout", handlers.LogoutHandler()) - router.POST("/token", handlers.TokenHandler()) + router.POST("/oauth/token", handlers.TokenHandler()) router.LoadHTMLGlob("templates/*") // login page app related routes. diff --git a/templates/authorize.tmpl b/templates/authorize.tmpl index 8842463..cc6c659 100644 --- a/templates/authorize.tmpl +++ b/templates/authorize.tmpl @@ -8,8 +8,8 @@ (function (window, document) { var targetOrigin = {{.target_origin}}; var authorizationResponse = {{.authorization_response}}; - var mainWin = window.parent; - mainWin.postMessage(authorizationResponse, targetOrigin); + console.log({targetOrigin}) + window.parent.postMessage(authorizationResponse, targetOrigin); })(this, this.document);