[server]fix: error redirection for email verification

This commit is contained in:
Lakhan Samani 2023-05-02 18:39:10 +05:30
parent a6f6e0b18a
commit a50f6becbd
8 changed files with 57 additions and 22 deletions

View File

@ -24,21 +24,22 @@ import (
// It verifies email based on JWT token in query string // It verifies email based on JWT token in query string
func VerifyEmailHandler() gin.HandlerFunc { func VerifyEmailHandler() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
redirectURL := strings.TrimSpace(c.Query("redirect_uri"))
errorRes := gin.H{ errorRes := gin.H{
"error": "invalid_token", "error": "token is required",
} }
tokenInQuery := c.Query("token") tokenInQuery := c.Query("token")
if tokenInQuery == "" { if tokenInQuery == "" {
log.Debug("Token is empty") log.Debug("Token is empty")
c.JSON(400, errorRes) utils.HandleRedirectORJsonResponse(c, http.StatusBadRequest, errorRes, generateRedirectURL(redirectURL, errorRes))
return return
} }
verificationRequest, err := db.Provider.GetVerificationRequestByToken(c, tokenInQuery) verificationRequest, err := db.Provider.GetVerificationRequestByToken(c, tokenInQuery)
if err != nil { if err != nil {
log.Debug("Error getting verification request: ", err) log.Debug("Error getting verification request: ", err)
errorRes["error_description"] = err.Error() errorRes["error"] = err.Error()
c.JSON(400, errorRes) utils.HandleRedirectORJsonResponse(c, http.StatusBadRequest, errorRes, generateRedirectURL(redirectURL, errorRes))
return return
} }
@ -47,23 +48,23 @@ func VerifyEmailHandler() gin.HandlerFunc {
claim, err := token.ParseJWTToken(tokenInQuery) claim, err := token.ParseJWTToken(tokenInQuery)
if err != nil { if err != nil {
log.Debug("Error parsing token: ", err) log.Debug("Error parsing token: ", err)
errorRes["error_description"] = err.Error() errorRes["error"] = err.Error()
c.JSON(400, errorRes) utils.HandleRedirectORJsonResponse(c, http.StatusBadRequest, errorRes, generateRedirectURL(redirectURL, errorRes))
return return
} }
if ok, err := token.ValidateJWTClaims(claim, hostname, verificationRequest.Nonce, verificationRequest.Email); !ok || err != nil { if ok, err := token.ValidateJWTClaims(claim, hostname, verificationRequest.Nonce, verificationRequest.Email); !ok || err != nil {
log.Debug("Error validating jwt claims: ", err) log.Debug("Error validating jwt claims: ", err)
errorRes["error_description"] = err.Error() errorRes["error"] = err.Error()
c.JSON(400, errorRes) utils.HandleRedirectORJsonResponse(c, http.StatusBadRequest, errorRes, generateRedirectURL(redirectURL, errorRes))
return return
} }
user, err := db.Provider.GetUserByEmail(c, verificationRequest.Email) user, err := db.Provider.GetUserByEmail(c, verificationRequest.Email)
if err != nil { if err != nil {
log.Debug("Error getting user: ", err) log.Debug("Error getting user: ", err)
errorRes["error_description"] = err.Error() errorRes["error"] = err.Error()
c.JSON(400, errorRes) utils.HandleRedirectORJsonResponse(c, http.StatusBadRequest, errorRes, generateRedirectURL(redirectURL, errorRes))
return return
} }
@ -79,7 +80,6 @@ func VerifyEmailHandler() gin.HandlerFunc {
db.Provider.DeleteVerificationRequest(c, verificationRequest) db.Provider.DeleteVerificationRequest(c, verificationRequest)
state := strings.TrimSpace(c.Query("state")) state := strings.TrimSpace(c.Query("state"))
redirectURL := strings.TrimSpace(c.Query("redirect_uri"))
rolesString := strings.TrimSpace(c.Query("roles")) rolesString := strings.TrimSpace(c.Query("roles"))
var roles []string var roles []string
if rolesString == "" { if rolesString == "" {
@ -125,8 +125,8 @@ func VerifyEmailHandler() gin.HandlerFunc {
authToken, err := token.CreateAuthToken(c, user, roles, scope, loginMethod, nonce, code) authToken, err := token.CreateAuthToken(c, user, roles, scope, loginMethod, nonce, code)
if err != nil { if err != nil {
log.Debug("Error creating auth token: ", err) log.Debug("Error creating auth token: ", err)
errorRes["error_description"] = err.Error() errorRes["error"] = err.Error()
c.JSON(500, errorRes) utils.HandleRedirectORJsonResponse(c, http.StatusInternalServerError, errorRes, generateRedirectURL(redirectURL, errorRes))
return return
} }
@ -135,7 +135,7 @@ func VerifyEmailHandler() gin.HandlerFunc {
// if code != "" { // if code != "" {
// if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil { // if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
// log.Debug("Error setting code state ", err) // log.Debug("Error setting code state ", err)
// errorRes["error_description"] = err.Error() // errorRes["error"] = err.Error()
// c.JSON(500, errorRes) // c.JSON(500, errorRes)
// return // return
// } // }
@ -189,3 +189,21 @@ func VerifyEmailHandler() gin.HandlerFunc {
c.Redirect(http.StatusTemporaryRedirect, redirectURL) c.Redirect(http.StatusTemporaryRedirect, redirectURL)
} }
} }
func generateRedirectURL(url string, res map[string]interface{}) string {
redirectURL := url
if redirectURL == "" {
return ""
}
var paramsArr []string
for key, value := range res {
paramsArr = append(paramsArr, key+"="+value.(string))
}
params := strings.Join(paramsArr, "&")
if strings.Contains(redirectURL, "?") {
redirectURL = redirectURL + "&" + params
} else {
redirectURL = redirectURL + "?" + strings.TrimPrefix(params, "&")
}
return redirectURL
}

View File

@ -224,7 +224,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
go email.SendEmail([]string{params.Email}, constants.VerificationTypeMagicLinkLogin, map[string]interface{}{ go email.SendEmail([]string{params.Email}, constants.VerificationTypeMagicLinkLogin, map[string]interface{}{
"user": user.ToMap(), "user": user.ToMap(),
"organization": utils.GetOrganization(), "organization": utils.GetOrganization(),
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname), "verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, redirectURL),
}) })
} }

View File

@ -83,7 +83,7 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
go email.SendEmail([]string{params.Email}, params.Identifier, map[string]interface{}{ go email.SendEmail([]string{params.Email}, params.Identifier, map[string]interface{}{
"user": user.ToMap(), "user": user.ToMap(),
"organization": utils.GetOrganization(), "organization": utils.GetOrganization(),
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname), "verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, verificationRequest.RedirectURI),
}) })
res = &model.Response{ res = &model.Response{

View File

@ -227,7 +227,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
email.SendEmail([]string{params.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{ email.SendEmail([]string{params.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{
"user": user.ToMap(), "user": user.ToMap(),
"organization": utils.GetOrganization(), "organization": utils.GetOrganization(),
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname), "verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, redirectURL),
}) })
utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodBasicAuth, user) utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
}() }()

View File

@ -259,7 +259,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
go email.SendEmail([]string{user.Email}, verificationType, map[string]interface{}{ go email.SendEmail([]string{user.Email}, verificationType, map[string]interface{}{
"user": user.ToMap(), "user": user.ToMap(),
"organization": utils.GetOrganization(), "organization": utils.GetOrganization(),
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname), "verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, redirectURL),
}) })
} }

View File

@ -164,7 +164,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
go email.SendEmail([]string{user.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{ go email.SendEmail([]string{user.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{
"user": user.ToMap(), "user": user.ToMap(),
"organization": utils.GetOrganization(), "organization": utils.GetOrganization(),
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname), "verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, redirectURL),
}) })
} }

View File

@ -82,7 +82,7 @@ func GetOrganization() map[string]interface{} {
// GetForgotPasswordURL to get url for given token and hostname // GetForgotPasswordURL to get url for given token and hostname
func GetForgotPasswordURL(token, redirectURI string) string { func GetForgotPasswordURL(token, redirectURI string) string {
verificationURL := redirectURI + "?token=" + token verificationURL := redirectURI + "?token=" + token + "&redirect_uri=" + redirectURI
return verificationURL return verificationURL
} }
@ -92,6 +92,6 @@ func GetInviteVerificationURL(verificationURL, token, redirectURI string) string
} }
// GetEmailVerificationURL to get url for invite email verification // GetEmailVerificationURL to get url for invite email verification
func GetEmailVerificationURL(token, hostname string) string { func GetEmailVerificationURL(token, hostname, redirectURI string) string {
return hostname + "/verify_email?token=" + token return hostname + "/verify_email?token=" + token + "&redirect_uri=" + redirectURI
} }

17
server/utils/response.go Normal file
View File

@ -0,0 +1,17 @@
package utils
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// HandleRedirectORJsonResponse handles the response based on redirectURL
func HandleRedirectORJsonResponse(c *gin.Context, httpResponse int, response map[string]interface{}, redirectURL string) {
if strings.TrimSpace(redirectURL) == "" {
c.JSON(httpResponse, response)
} else {
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
}
}