fix: other auth recipes for oidc idp + remove logs
This commit is contained in:
parent
579899c397
commit
75a547cfe2
|
@ -57,7 +57,6 @@ export default function Root({
|
|||
urlProps.redirect_uri = urlProps.redirectURL;
|
||||
|
||||
useEffect(() => {
|
||||
console.log(config);
|
||||
if (token) {
|
||||
let redirectURL = config.redirectURL || '/app';
|
||||
let params = `access_token=${token.access_token}&id_token=${token.id_token}&expires_in=${token.expires_in}&state=${globalState.state}`;
|
||||
|
@ -113,7 +112,7 @@ export default function Root({
|
|||
<Route path="/app" exact>
|
||||
<Login urlProps={urlProps} />
|
||||
</Route>
|
||||
<Route path="/app/signup" exact>
|
||||
<Route path="/app/signup">
|
||||
<SignUp urlProps={urlProps} />
|
||||
</Route>
|
||||
<Route path="/app/reset-password">
|
||||
|
|
|
@ -2278,6 +2278,10 @@ input VerifyEmailInput {
|
|||
input ResendVerifyEmailInput {
|
||||
email: String!
|
||||
identifier: String!
|
||||
# state is used for authorization code grant flow
|
||||
# it is used to get code for an on-going auth process during login
|
||||
# and use that code for setting ` + "`" + `c_hash` + "`" + ` in id_token
|
||||
state: String
|
||||
}
|
||||
|
||||
input UpdateProfileInput {
|
||||
|
@ -2425,10 +2429,18 @@ input DeleteEmailTemplateRequest {
|
|||
input VerifyOTPRequest {
|
||||
email: String!
|
||||
otp: String!
|
||||
# state is used for authorization code grant flow
|
||||
# it is used to get code for an on-going auth process during login
|
||||
# and use that code for setting ` + "`" + `c_hash` + "`" + ` in id_token
|
||||
state: String
|
||||
}
|
||||
|
||||
input ResendOTPRequest {
|
||||
email: String!
|
||||
# state is used for authorization code grant flow
|
||||
# it is used to get code for an on-going auth process during login
|
||||
# and use that code for setting ` + "`" + `c_hash` + "`" + ` in id_token
|
||||
state: String
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
|
@ -14679,7 +14691,7 @@ func (ec *executionContext) unmarshalInputResendOTPRequest(ctx context.Context,
|
|||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"email"}
|
||||
fieldsInOrder := [...]string{"email", "state"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
|
@ -14694,6 +14706,14 @@ func (ec *executionContext) unmarshalInputResendOTPRequest(ctx context.Context,
|
|||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "state":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("state"))
|
||||
it.State, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14707,7 +14727,7 @@ func (ec *executionContext) unmarshalInputResendVerifyEmailInput(ctx context.Con
|
|||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"email", "identifier"}
|
||||
fieldsInOrder := [...]string{"email", "identifier", "state"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
|
@ -14730,6 +14750,14 @@ func (ec *executionContext) unmarshalInputResendVerifyEmailInput(ctx context.Con
|
|||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "state":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("state"))
|
||||
it.State, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15879,7 +15907,7 @@ func (ec *executionContext) unmarshalInputVerifyOTPRequest(ctx context.Context,
|
|||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"email", "otp"}
|
||||
fieldsInOrder := [...]string{"email", "otp", "state"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
|
@ -15902,6 +15930,14 @@ func (ec *executionContext) unmarshalInputVerifyOTPRequest(ctx context.Context,
|
|||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "state":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("state"))
|
||||
it.State, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -201,11 +201,13 @@ type PaginationInput struct {
|
|||
|
||||
type ResendOTPRequest struct {
|
||||
Email string `json:"email"`
|
||||
State *string `json:"state"`
|
||||
}
|
||||
|
||||
type ResendVerifyEmailInput struct {
|
||||
Email string `json:"email"`
|
||||
Identifier string `json:"identifier"`
|
||||
State *string `json:"state"`
|
||||
}
|
||||
|
||||
type ResetPasswordInput struct {
|
||||
|
@ -417,6 +419,7 @@ type VerifyEmailInput struct {
|
|||
type VerifyOTPRequest struct {
|
||||
Email string `json:"email"`
|
||||
Otp string `json:"otp"`
|
||||
State *string `json:"state"`
|
||||
}
|
||||
|
||||
type Webhook struct {
|
||||
|
|
|
@ -45,9 +45,7 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/cookie"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/parsers"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
// Check the flow for generating and verifying codes: https://developer.okta.com/blog/2019/08/22/okta-authjs-pkce#:~:text=PKCE%20works%20by%20having%20the,is%20called%20the%20Code%20Challenge.
|
||||
|
@ -110,17 +108,9 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||
log := log.WithFields(log.Fields{
|
||||
"response_mode": responseMode,
|
||||
"response_type": responseType,
|
||||
"state": state,
|
||||
"code_challenge": codeChallenge,
|
||||
"scope": scope,
|
||||
"redirect_uri": redirectURI,
|
||||
"nonce": nonce,
|
||||
"code": code,
|
||||
})
|
||||
|
||||
// memorystore.Provider.SetState(codeChallenge, code)
|
||||
// TODO add state with timeout
|
||||
|
||||
// used for response mode query or fragment
|
||||
loginState := "state=" + state + "&scope=" + strings.Join(scope, " ") + "&redirect_uri=" + redirectURI
|
||||
if responseType == constants.ResponseTypeCode {
|
||||
|
@ -141,17 +131,6 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||
loginURL = "/app#" + loginState
|
||||
}
|
||||
|
||||
if state == "" {
|
||||
handleResponse(gc, responseMode, loginURL, redirectURI, map[string]interface{}{
|
||||
"type": "authorization_response",
|
||||
"response": map[string]interface{}{
|
||||
"error": "state_required",
|
||||
"error_description": "state is required",
|
||||
},
|
||||
}, http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
if responseType == constants.ResponseTypeCode && codeChallenge == "" {
|
||||
handleResponse(gc, responseMode, loginURL, redirectURI, map[string]interface{}{
|
||||
"type": "authorization_response",
|
||||
|
@ -275,7 +254,6 @@ 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, "")
|
||||
if err != nil {
|
||||
|
@ -299,7 +277,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||
|
||||
// used of query mode
|
||||
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
|
||||
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(authToken.IDToken.ExpiresAt, 10) + "&state=" + state + "&id_token=" + authToken.IDToken.Token
|
||||
|
||||
res := map[string]interface{}{
|
||||
"access_token": authToken.AccessToken.Token,
|
||||
|
@ -308,19 +286,17 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||
"scope": scope,
|
||||
"token_type": "Bearer",
|
||||
"expires_in": authToken.AccessToken.ExpiresAt,
|
||||
"code": code,
|
||||
}
|
||||
|
||||
if utils.StringSliceContains(scope, "offline_access") {
|
||||
refreshToken, _, err := token.CreateRefreshToken(user, claims.Roles, scope, hostname, nonce, claims.LoginMethod)
|
||||
if err != nil {
|
||||
log.Debug("SetUserSession failed: ", err)
|
||||
handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK)
|
||||
return
|
||||
if nonce != "" {
|
||||
params += "&nonce=" + nonce
|
||||
res["nonce"] = nonce
|
||||
}
|
||||
res["refresh_token"] = refreshToken
|
||||
params += "&refresh_token=" + refreshToken
|
||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+nonce, refreshToken)
|
||||
|
||||
if authToken.RefreshToken != nil {
|
||||
res["refresh_token"] = authToken.RefreshToken.Token
|
||||
params += "&refresh_token=" + authToken.RefreshToken.Token
|
||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
||||
}
|
||||
|
||||
if responseMode == constants.ResponseModeQuery {
|
||||
|
@ -349,6 +325,9 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||
}
|
||||
|
||||
func validateAuthorizeRequest(responseType, responseMode, clientID, state, codeChallenge string) error {
|
||||
if strings.TrimSpace(state) == "" {
|
||||
return fmt.Errorf("invalid state. state is required to prevent csrf attack", responseMode)
|
||||
}
|
||||
if responseType != constants.ResponseTypeCode && responseType != constants.ResponseTypeToken && responseType != constants.ResponseTypeIDToken {
|
||||
return fmt.Errorf("invalid response type %s. 'code' & 'token' are valid response_type", responseMode)
|
||||
}
|
||||
|
@ -387,8 +366,6 @@ func handleResponse(gc *gin.Context, responseMode, loginURI, redirectURI string,
|
|||
})
|
||||
return
|
||||
case constants.ResponseModeFormPost:
|
||||
fmt.Println("=> trying tof orm post")
|
||||
fmt.Printf("=> %+v \n", data["response"])
|
||||
gc.HTML(httpStatusCode, authorizeFormPostTemplate, gin.H{
|
||||
"target_origin": redirectURI,
|
||||
"authorization_response": data["response"],
|
||||
|
|
|
@ -56,20 +56,20 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
scopes := strings.Split(sessionSplit[3], ",")
|
||||
|
||||
user := models.User{}
|
||||
code := ctx.Request.FormValue("code")
|
||||
oauthCode := ctx.Request.FormValue("code")
|
||||
switch provider {
|
||||
case constants.AuthRecipeMethodGoogle:
|
||||
user, err = processGoogleUserInfo(code)
|
||||
user, err = processGoogleUserInfo(oauthCode)
|
||||
case constants.AuthRecipeMethodGithub:
|
||||
user, err = processGithubUserInfo(code)
|
||||
user, err = processGithubUserInfo(oauthCode)
|
||||
case constants.AuthRecipeMethodFacebook:
|
||||
user, err = processFacebookUserInfo(code)
|
||||
user, err = processFacebookUserInfo(oauthCode)
|
||||
case constants.AuthRecipeMethodLinkedIn:
|
||||
user, err = processLinkedInUserInfo(code)
|
||||
user, err = processLinkedInUserInfo(oauthCode)
|
||||
case constants.AuthRecipeMethodApple:
|
||||
user, err = processAppleUserInfo(code)
|
||||
user, err = processAppleUserInfo(oauthCode)
|
||||
case constants.AuthRecipeMethodTwitter:
|
||||
user, err = processTwitterUserInfo(code, sessionState)
|
||||
user, err = processTwitterUserInfo(oauthCode, sessionState)
|
||||
default:
|
||||
log.Info("Invalid oauth provider")
|
||||
err = fmt.Errorf(`invalid oauth provider`)
|
||||
|
@ -200,19 +200,50 @@ 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, "")
|
||||
code := ""
|
||||
codeChallenge := ""
|
||||
nonce := ""
|
||||
if stateValue != "" {
|
||||
// Get state from store
|
||||
authorizeState, _ := memorystore.Provider.GetState(stateValue)
|
||||
if authorizeState != "" {
|
||||
authorizeStateSplit := strings.Split(authorizeState, "@@")
|
||||
if len(authorizeStateSplit) > 1 {
|
||||
code = authorizeStateSplit[0]
|
||||
codeChallenge = authorizeStateSplit[1]
|
||||
} else {
|
||||
nonce = authorizeState
|
||||
}
|
||||
go memorystore.Provider.RemoveState(stateValue)
|
||||
}
|
||||
}
|
||||
if nonce == "" {
|
||||
nonce = uuid.New().String()
|
||||
}
|
||||
authToken, err := token.CreateAuthToken(ctx, user, inputRoles, scopes, provider, nonce, code)
|
||||
if err != nil {
|
||||
log.Debug("Failed to create auth token: ", err)
|
||||
ctx.JSON(500, gin.H{"error": err.Error()})
|
||||
}
|
||||
|
||||
// Code challenge could be optional if PKCE flow is not used
|
||||
if code != "" {
|
||||
if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
|
||||
log.Debug("SetState failed: ", err)
|
||||
ctx.JSON(500, gin.H{"error": err.Error()})
|
||||
}
|
||||
}
|
||||
|
||||
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
||||
if expiresIn <= 0 {
|
||||
expiresIn = 1
|
||||
}
|
||||
|
||||
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + stateValue + "&id_token=" + authToken.IDToken.Token
|
||||
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + stateValue + "&id_token=" + authToken.IDToken.Token + "&nonce=" + nonce
|
||||
|
||||
if code != "" {
|
||||
params += "&code=" + code
|
||||
}
|
||||
|
||||
sessionKey := provider + ":" + user.ID
|
||||
cookie.SetSession(ctx, authToken.FingerPrintHash)
|
||||
|
@ -220,7 +251,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
||||
|
||||
if authToken.RefreshToken != nil {
|
||||
params = params + `&refresh_token=` + authToken.RefreshToken.Token
|
||||
params += `&refresh_token=` + authToken.RefreshToken.Token
|
||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package handlers
|
|||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -33,10 +32,6 @@ type RequestBody struct {
|
|||
// grant type required
|
||||
func TokenHandler() gin.HandlerFunc {
|
||||
return func(gc *gin.Context) {
|
||||
// body := gc.Request.Body
|
||||
// x, _ := ioutil.ReadAll(body)
|
||||
|
||||
// fmt.Printf("=> %s \n %s\n", string(x), gc.Request.Header.Get("Content-Type"))
|
||||
var reqBody RequestBody
|
||||
if err := gc.Bind(&reqBody); err != nil {
|
||||
log.Debug("Error binding JSON: ", err)
|
||||
|
@ -47,8 +42,6 @@ func TokenHandler() gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
fmt.Printf("=>req body: %+v\n", reqBody)
|
||||
|
||||
codeVerifier := strings.TrimSpace(reqBody.CodeVerifier)
|
||||
code := strings.TrimSpace(reqBody.Code)
|
||||
clientID := strings.TrimSpace(reqBody.ClientID)
|
||||
|
@ -125,7 +118,6 @@ func TokenHandler() gin.HandlerFunc {
|
|||
// [0] -> code_challenge
|
||||
// [1] -> session cookie
|
||||
sessionDataSplit := strings.Split(sessionData, "@@")
|
||||
fmt.Println("=> sessionDataSplit:", sessionDataSplit)
|
||||
|
||||
go memorystore.Provider.RemoveState(code)
|
||||
|
||||
|
@ -135,7 +127,6 @@ func TokenHandler() gin.HandlerFunc {
|
|||
encryptedCode := strings.ReplaceAll(base64.RawURLEncoding.EncodeToString(hash.Sum(nil)), "+", "-")
|
||||
encryptedCode = strings.ReplaceAll(encryptedCode, "/", "_")
|
||||
encryptedCode = strings.ReplaceAll(encryptedCode, "=", "")
|
||||
fmt.Println("=> encryptedCode", encryptedCode)
|
||||
if encryptedCode != sessionDataSplit[0] {
|
||||
gc.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "invalid_code_verifier",
|
||||
|
@ -166,8 +157,6 @@ func TokenHandler() gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
fmt.Printf("=>claims: %+v\n", &claims)
|
||||
|
||||
userID = claims.Subject
|
||||
roles = claims.Roles
|
||||
scope = claims.Scope
|
||||
|
@ -242,10 +231,6 @@ func TokenHandler() gin.HandlerFunc {
|
|||
}
|
||||
|
||||
nonce := uuid.New().String() + "@@" + code
|
||||
|
||||
fmt.Println("=> code", code)
|
||||
fmt.Println("=> nonce", nonce)
|
||||
|
||||
authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod, nonce, code)
|
||||
if err != nil {
|
||||
log.Debug("Error creating auth token: ", err)
|
||||
|
|
|
@ -100,8 +100,29 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||
loginMethod = constants.AuthRecipeMethodMagicLinkLogin
|
||||
}
|
||||
|
||||
nonce := uuid.New().String()
|
||||
authToken, err := token.CreateAuthToken(c, user, roles, scope, loginMethod, nonce, "")
|
||||
code := ""
|
||||
// Not required as /oauth/token cannot be resumed from other tab
|
||||
// codeChallenge := ""
|
||||
nonce := ""
|
||||
if state != "" {
|
||||
// Get state from store
|
||||
authorizeState, _ := memorystore.Provider.GetState(state)
|
||||
if authorizeState != "" {
|
||||
authorizeStateSplit := strings.Split(authorizeState, "@@")
|
||||
if len(authorizeStateSplit) > 1 {
|
||||
code = authorizeStateSplit[0]
|
||||
// Not required as /oauth/token cannot be resumed from other tab
|
||||
// codeChallenge = authorizeStateSplit[1]
|
||||
} else {
|
||||
nonce = authorizeState
|
||||
}
|
||||
go memorystore.Provider.RemoveState(state)
|
||||
}
|
||||
}
|
||||
if nonce == "" {
|
||||
nonce = uuid.New().String()
|
||||
}
|
||||
authToken, err := token.CreateAuthToken(c, user, roles, scope, loginMethod, nonce, code)
|
||||
if err != nil {
|
||||
log.Debug("Error creating auth token: ", err)
|
||||
errorRes["error_description"] = err.Error()
|
||||
|
@ -109,12 +130,27 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
// Code challenge could be optional if PKCE flow is not used
|
||||
// Not required as /oauth/token cannot be resumed from other tab
|
||||
// if code != "" {
|
||||
// if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
|
||||
// log.Debug("Error setting code state ", err)
|
||||
// errorRes["error_description"] = err.Error()
|
||||
// c.JSON(500, errorRes)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
|
||||
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
||||
if expiresIn <= 0 {
|
||||
expiresIn = 1
|
||||
}
|
||||
|
||||
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + state + "&id_token=" + authToken.IDToken.Token
|
||||
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + state + "&id_token=" + authToken.IDToken.Token + "&nonce=" + nonce
|
||||
|
||||
if code != "" {
|
||||
params += "&code=" + code
|
||||
}
|
||||
|
||||
sessionKey := loginMethod + ":" + user.ID
|
||||
cookie.SetSession(c, authToken.FingerPrintHash)
|
||||
|
|
|
@ -141,10 +141,9 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||
}, nil
|
||||
}
|
||||
|
||||
nonce := uuid.New().String()
|
||||
fmt.Println("=> state", refs.StringValue(params.State))
|
||||
code := ""
|
||||
codeChallenge := ""
|
||||
nonce := ""
|
||||
if params.State != nil {
|
||||
// Get state from store
|
||||
authorizeState, _ := memorystore.Provider.GetState(refs.StringValue(params.State))
|
||||
|
@ -153,8 +152,6 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||
if len(authorizeStateSplit) > 1 {
|
||||
code = authorizeStateSplit[0]
|
||||
codeChallenge = authorizeStateSplit[1]
|
||||
|
||||
fmt.Println("=> code info", authorizeStateSplit)
|
||||
} else {
|
||||
nonce = authorizeState
|
||||
}
|
||||
|
@ -162,12 +159,25 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||
}
|
||||
}
|
||||
|
||||
if nonce == "" {
|
||||
nonce = uuid.New().String()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// TODO add to other login options as well
|
||||
// Code challenge could be optional if PKCE flow is not used
|
||||
if code != "" {
|
||||
if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
|
||||
log.Debug("SetState failed: ", err)
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
||||
if expiresIn <= 0 {
|
||||
expiresIn = 1
|
||||
|
@ -185,15 +195,6 @@ 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 {
|
||||
log.Debug("SetState failed: ", err)
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
if authToken.RefreshToken != nil {
|
||||
res.RefreshToken = &authToken.RefreshToken.Token
|
||||
|
|
|
@ -34,16 +34,6 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
return res, err
|
||||
}
|
||||
|
||||
code := ""
|
||||
if params.State != nil {
|
||||
// Get state from store
|
||||
code, err = memorystore.Provider.GetState(*params.State)
|
||||
if err != nil {
|
||||
log.Debug("Invalid Error State:", err)
|
||||
return res, fmt.Errorf("invalid_state: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
isSignupDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp)
|
||||
if err != nil {
|
||||
log.Debug("Error getting signup disabled: ", err)
|
||||
|
@ -253,9 +243,26 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
scope = params.Scope
|
||||
}
|
||||
|
||||
nonce := uuid.New().String()
|
||||
if code != "" {
|
||||
nonce = nonce + "@@" + code
|
||||
code := ""
|
||||
codeChallenge := ""
|
||||
nonce := ""
|
||||
if params.State != nil {
|
||||
// Get state from store
|
||||
authorizeState, _ := memorystore.Provider.GetState(refs.StringValue(params.State))
|
||||
if authorizeState != "" {
|
||||
authorizeStateSplit := strings.Split(authorizeState, "@@")
|
||||
if len(authorizeStateSplit) > 1 {
|
||||
code = authorizeStateSplit[0]
|
||||
codeChallenge = authorizeStateSplit[1]
|
||||
} else {
|
||||
nonce = authorizeState
|
||||
}
|
||||
go memorystore.Provider.RemoveState(refs.StringValue(params.State))
|
||||
}
|
||||
}
|
||||
|
||||
if nonce == "" {
|
||||
nonce = uuid.New().String()
|
||||
}
|
||||
|
||||
authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce, code)
|
||||
|
@ -264,6 +271,14 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
return res, err
|
||||
}
|
||||
|
||||
// Code challenge could be optional if PKCE flow is not used
|
||||
if code != "" {
|
||||
if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
|
||||
log.Debug("SetState failed: ", err)
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
||||
if expiresIn <= 0 {
|
||||
expiresIn = 1
|
||||
|
|
|
@ -16,6 +16,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"
|
||||
)
|
||||
|
@ -85,13 +86,42 @@ 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, "")
|
||||
code := ""
|
||||
// Not required as /oauth/token cannot be resumed from other tab
|
||||
// codeChallenge := ""
|
||||
nonce := ""
|
||||
if params.State != nil {
|
||||
// Get state from store
|
||||
authorizeState, _ := memorystore.Provider.GetState(refs.StringValue(params.State))
|
||||
if authorizeState != "" {
|
||||
authorizeStateSplit := strings.Split(authorizeState, "@@")
|
||||
if len(authorizeStateSplit) > 1 {
|
||||
code = authorizeStateSplit[0]
|
||||
// Not required as /oauth/token cannot be resumed from other tab
|
||||
// codeChallenge = authorizeStateSplit[1]
|
||||
} else {
|
||||
nonce = authorizeState
|
||||
}
|
||||
go memorystore.Provider.RemoveState(refs.StringValue(params.State))
|
||||
}
|
||||
}
|
||||
if nonce == "" {
|
||||
nonce = uuid.New().String()
|
||||
}
|
||||
authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod, nonce, code)
|
||||
if err != nil {
|
||||
log.Debug("Failed to create auth token: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Code challenge could be optional if PKCE flow is not used
|
||||
// Not required as /oauth/token cannot be resumed from other tab
|
||||
// if code != "" {
|
||||
// if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
|
||||
// log.Debug("SetState failed: ", err)
|
||||
// return res, err
|
||||
// }
|
||||
// }
|
||||
go func() {
|
||||
if isSignUp {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, loginMethod, user)
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/refs"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/google/uuid"
|
||||
|
@ -58,13 +59,40 @@ 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, "")
|
||||
code := ""
|
||||
codeChallenge := ""
|
||||
nonce := ""
|
||||
if params.State != nil {
|
||||
// Get state from store
|
||||
authorizeState, _ := memorystore.Provider.GetState(refs.StringValue(params.State))
|
||||
if authorizeState != "" {
|
||||
authorizeStateSplit := strings.Split(authorizeState, "@@")
|
||||
if len(authorizeStateSplit) > 1 {
|
||||
code = authorizeStateSplit[0]
|
||||
codeChallenge = authorizeStateSplit[1]
|
||||
} else {
|
||||
nonce = authorizeState
|
||||
}
|
||||
go memorystore.Provider.RemoveState(refs.StringValue(params.State))
|
||||
}
|
||||
}
|
||||
if nonce == "" {
|
||||
nonce = uuid.New().String()
|
||||
}
|
||||
authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod, nonce, code)
|
||||
if err != nil {
|
||||
log.Debug("Failed to create auth token: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Code challenge could be optional if PKCE flow is not used
|
||||
if code != "" {
|
||||
if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
|
||||
log.Debug("Failed to set code state: ", err)
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
db.Provider.DeleteOTP(gc, otp)
|
||||
if isSignUp {
|
||||
|
|
|
@ -50,9 +50,6 @@ 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, code string) (*Token, error) {
|
||||
|
||||
fmt.Println("=> original nonce:", nonce)
|
||||
|
||||
hostname := parsers.GetHost(gc)
|
||||
_, fingerPrintHash, err := CreateSessionToken(user, nonce, roles, scope, loginMethod)
|
||||
if err != nil {
|
||||
|
@ -72,7 +69,6 @@ func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, l
|
|||
|
||||
codeHashString := ""
|
||||
if code != "" {
|
||||
fmt.Println("=> atHash", atHashString)
|
||||
codeHash := sha256.New()
|
||||
codeHash.Write([]byte(code))
|
||||
codeHashBytes := codeHash.Sum(nil)
|
||||
|
@ -80,7 +76,6 @@ func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, l
|
|||
codeHashString = base64.RawURLEncoding.EncodeToString(codeHashDigest)
|
||||
}
|
||||
|
||||
fmt.Println("=> at hash nonce", nonce)
|
||||
idToken, idTokenExpiresAt, err := CreateIDToken(user, roles, hostname, nonce, atHashString, codeHashString, loginMethod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -116,7 +111,6 @@ func CreateSessionToken(user models.User, nonce string, roles, scope []string, l
|
|||
IssuedAt: time.Now().Unix(),
|
||||
ExpiresAt: time.Now().AddDate(1, 0, 0).Unix(),
|
||||
}
|
||||
fmt.Printf("=> session data %+v\n", fingerPrintMap)
|
||||
fingerPrintBytes, _ := json.Marshal(fingerPrintMap)
|
||||
fingerPrintHash, err := crypto.EncryptAES(string(fingerPrintBytes))
|
||||
if err != nil {
|
||||
|
@ -381,8 +375,6 @@ func CreateIDToken(user models.User, roles []string, hostname, nonce, atHash, cH
|
|||
claimKey: roles,
|
||||
}
|
||||
|
||||
fmt.Println("=> nonce", nonce)
|
||||
|
||||
// split nonce to see if its authorization code grant method
|
||||
|
||||
if cHash != "" {
|
||||
|
@ -393,8 +385,6 @@ func CreateIDToken(user models.User, roles []string, hostname, nonce, atHash, cH
|
|||
customClaims["at_hash"] = atHash
|
||||
}
|
||||
|
||||
fmt.Println("custom_claims", customClaims)
|
||||
|
||||
for k, v := range userMap {
|
||||
if k != "roles" {
|
||||
customClaims[k] = v
|
||||
|
|
Loading…
Reference in New Issue
Block a user