Compare commits
22 Commits
fix-db-ref
...
1.1.63
Author | SHA1 | Date | |
---|---|---|---|
![]() |
09cfad9c27 | ||
![]() |
35e563ab3b | ||
![]() |
e625ed9633 | ||
![]() |
a042c202a0 | ||
![]() |
7a76b783b1 | ||
![]() |
e5400bc7bd | ||
![]() |
a8503666e3 | ||
![]() |
b028be3cbc | ||
![]() |
9a8d20b698 | ||
![]() |
fab3c2f87e | ||
![]() |
0c334856bc | ||
![]() |
ba0cf189de | ||
![]() |
9f52c08883 | ||
![]() |
80f3698f06 | ||
![]() |
2a2b7abc08 | ||
![]() |
27e3ed82e4 | ||
![]() |
6077702626 | ||
![]() |
cf54fcef03 | ||
![]() |
2f849b8f0c | ||
![]() |
85ca0f09bf | ||
![]() |
e7652db89c | ||
![]() |
5018462559 |
@@ -118,7 +118,6 @@ const Webhooks = () => {
|
||||
useEffect(() => {
|
||||
fetchWebookData();
|
||||
}, [paginationProps.page, paginationProps.limit]);
|
||||
console.log({ webhookData });
|
||||
return (
|
||||
<Box m="5" py="5" px="10" bg="white" rounded="md">
|
||||
<Flex margin="2% 0" justifyContent="space-between" alignItems="center">
|
||||
|
@@ -5,4 +5,6 @@ const (
|
||||
AppCookieName = "cookie"
|
||||
// AdminCookieName is the name of the cookie that is used to store the admin token
|
||||
AdminCookieName = "authorizer-admin"
|
||||
// MfaCookieName is the name of the cookie that is used to store the mfa session
|
||||
MfaCookieName = "mfa"
|
||||
)
|
||||
|
89
server/cookie/mfa_session.go
Normal file
89
server/cookie/mfa_session.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package cookie
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/parsers"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// SetMfaSession sets the mfa session cookie in the response
|
||||
func SetMfaSession(gc *gin.Context, sessionID string) {
|
||||
appCookieSecure, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyAppCookieSecure)
|
||||
if err != nil {
|
||||
log.Debug("Error while getting app cookie secure from env variable: %v", err)
|
||||
appCookieSecure = true
|
||||
}
|
||||
|
||||
secure := appCookieSecure
|
||||
httpOnly := appCookieSecure
|
||||
hostname := parsers.GetHost(gc)
|
||||
host, _ := parsers.GetHostParts(hostname)
|
||||
domain := parsers.GetDomainName(hostname)
|
||||
if domain != "localhost" {
|
||||
domain = "." + domain
|
||||
}
|
||||
|
||||
// Since app cookie can come from cross site it becomes important to set this in lax mode when insecure.
|
||||
// Example person using custom UI on their app domain and making request to authorizer domain.
|
||||
// For more information check:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
|
||||
// https://github.com/gin-gonic/gin/blob/master/context.go#L86
|
||||
// TODO add ability to sameSite = none / strict from dashboard
|
||||
if !appCookieSecure {
|
||||
gc.SetSameSite(http.SameSiteLaxMode)
|
||||
} else {
|
||||
gc.SetSameSite(http.SameSiteNoneMode)
|
||||
}
|
||||
// TODO allow configuring from dashboard
|
||||
age := 60
|
||||
|
||||
gc.SetCookie(constants.MfaCookieName+"_session", sessionID, age, "/", host, secure, httpOnly)
|
||||
gc.SetCookie(constants.MfaCookieName+"_session_domain", sessionID, age, "/", domain, secure, httpOnly)
|
||||
}
|
||||
|
||||
// DeleteMfaSession deletes the mfa session cookies to expire
|
||||
func DeleteMfaSession(gc *gin.Context) {
|
||||
appCookieSecure, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyAppCookieSecure)
|
||||
if err != nil {
|
||||
log.Debug("Error while getting app cookie secure from env variable: %v", err)
|
||||
appCookieSecure = true
|
||||
}
|
||||
|
||||
secure := appCookieSecure
|
||||
httpOnly := appCookieSecure
|
||||
hostname := parsers.GetHost(gc)
|
||||
host, _ := parsers.GetHostParts(hostname)
|
||||
domain := parsers.GetDomainName(hostname)
|
||||
if domain != "localhost" {
|
||||
domain = "." + domain
|
||||
}
|
||||
|
||||
gc.SetSameSite(http.SameSiteNoneMode)
|
||||
gc.SetCookie(constants.MfaCookieName+"_session", "", -1, "/", host, secure, httpOnly)
|
||||
gc.SetCookie(constants.MfaCookieName+"_session_domain", "", -1, "/", domain, secure, httpOnly)
|
||||
}
|
||||
|
||||
// GetMfaSession gets the mfa session cookie from context
|
||||
func GetMfaSession(gc *gin.Context) (string, error) {
|
||||
var cookie *http.Cookie
|
||||
var err error
|
||||
cookie, err = gc.Request.Cookie(constants.MfaCookieName + "_session")
|
||||
if err != nil {
|
||||
cookie, err = gc.Request.Cookie(constants.MfaCookieName + "_session_domain")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
decodedValue, err := url.PathUnescape(cookie.Value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return decodedValue, nil
|
||||
}
|
@@ -33,12 +33,14 @@ type User struct {
|
||||
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled" bson:"is_multi_factor_auth_enabled" cql:"is_multi_factor_auth_enabled" dynamo:"is_multi_factor_auth_enabled"`
|
||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at" dynamo:"updated_at"`
|
||||
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at" dynamo:"created_at"`
|
||||
AppData *string `json:"app_data" bson:"app_data" cql:"app_data" dynamo:"app_data"`
|
||||
}
|
||||
|
||||
func (user *User) AsAPIUser() *model.User {
|
||||
isEmailVerified := user.EmailVerifiedAt != nil
|
||||
isPhoneVerified := user.PhoneNumberVerifiedAt != nil
|
||||
|
||||
appDataMap := make(map[string]interface{})
|
||||
json.Unmarshal([]byte(refs.StringValue(user.AppData)), &appDataMap)
|
||||
// id := user.ID
|
||||
// if strings.Contains(id, Collections.User+"/") {
|
||||
// id = strings.TrimPrefix(id, Collections.User+"/")
|
||||
@@ -63,6 +65,7 @@ func (user *User) AsAPIUser() *model.User {
|
||||
IsMultiFactorAuthEnabled: user.IsMultiFactorAuthEnabled,
|
||||
CreatedAt: refs.NewInt64Ref(user.CreatedAt),
|
||||
UpdatedAt: refs.NewInt64Ref(user.UpdatedAt),
|
||||
AppData: appDataMap,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -72,7 +72,6 @@ func getEmailTemplate(event string, data map[string]interface{}) (*model.EmailTe
|
||||
return nil, err
|
||||
}
|
||||
subjectString := buf.String()
|
||||
|
||||
return &model.EmailTemplate{
|
||||
Template: templateString,
|
||||
Subject: subjectString,
|
||||
|
@@ -30,7 +30,7 @@ require (
|
||||
go.mongodb.org/mongo-driver v1.8.1
|
||||
golang.org/x/crypto v0.4.0
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/appengine v1.6.7
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/mail.v2 v2.3.1
|
||||
|
1275
server/go.sum
1275
server/go.sum
File diff suppressed because it is too large
Load Diff
@@ -245,6 +245,7 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
User struct {
|
||||
AppData func(childComplexity int) int
|
||||
Birthdate func(childComplexity int) int
|
||||
CreatedAt func(childComplexity int) int
|
||||
Email func(childComplexity int) int
|
||||
@@ -1695,6 +1696,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.TestEndpointResponse.Response(childComplexity), true
|
||||
|
||||
case "User.app_data":
|
||||
if e.complexity.User.AppData == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.User.AppData(childComplexity), true
|
||||
|
||||
case "User.birthdate":
|
||||
if e.complexity.User.Birthdate == nil {
|
||||
break
|
||||
@@ -2229,6 +2237,7 @@ type User {
|
||||
updated_at: Int64
|
||||
revoked_timestamp: Int64
|
||||
is_multi_factor_auth_enabled: Boolean
|
||||
app_data: Map
|
||||
}
|
||||
|
||||
type Users {
|
||||
@@ -2500,6 +2509,7 @@ input MobileSignUpInput {
|
||||
# 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
|
||||
app_data: Map
|
||||
}
|
||||
|
||||
input SignUpInput {
|
||||
@@ -2522,6 +2532,7 @@ input SignUpInput {
|
||||
# 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
|
||||
app_data: Map
|
||||
}
|
||||
|
||||
input LoginInput {
|
||||
@@ -2577,6 +2588,7 @@ input UpdateProfileInput {
|
||||
phone_number: String
|
||||
picture: String
|
||||
is_multi_factor_auth_enabled: Boolean
|
||||
app_data: Map
|
||||
}
|
||||
|
||||
input UpdateUserInput {
|
||||
@@ -2593,6 +2605,7 @@ input UpdateUserInput {
|
||||
picture: String
|
||||
roles: [String]
|
||||
is_multi_factor_auth_enabled: Boolean
|
||||
app_data: Map
|
||||
}
|
||||
|
||||
input ForgotPasswordInput {
|
||||
@@ -2690,6 +2703,7 @@ input WebhookRequest {
|
||||
input TestEndpointRequest {
|
||||
endpoint: String!
|
||||
event_name: String!
|
||||
event_description: String
|
||||
headers: Map
|
||||
}
|
||||
|
||||
@@ -3803,6 +3817,8 @@ func (ec *executionContext) fieldContext_AuthResponse_user(ctx context.Context,
|
||||
return ec.fieldContext_User_revoked_timestamp(ctx, field)
|
||||
case "is_multi_factor_auth_enabled":
|
||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||
case "app_data":
|
||||
return ec.fieldContext_User_app_data(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||
},
|
||||
@@ -7098,6 +7114,8 @@ func (ec *executionContext) fieldContext_InviteMembersResponse_Users(ctx context
|
||||
return ec.fieldContext_User_revoked_timestamp(ctx, field)
|
||||
case "is_multi_factor_auth_enabled":
|
||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||
case "app_data":
|
||||
return ec.fieldContext_User_app_data(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||
},
|
||||
@@ -8800,6 +8818,8 @@ func (ec *executionContext) fieldContext_Mutation__update_user(ctx context.Conte
|
||||
return ec.fieldContext_User_revoked_timestamp(ctx, field)
|
||||
case "is_multi_factor_auth_enabled":
|
||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||
case "app_data":
|
||||
return ec.fieldContext_User_app_data(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||
},
|
||||
@@ -10102,6 +10122,8 @@ func (ec *executionContext) fieldContext_Query_profile(ctx context.Context, fiel
|
||||
return ec.fieldContext_User_revoked_timestamp(ctx, field)
|
||||
case "is_multi_factor_auth_enabled":
|
||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||
case "app_data":
|
||||
return ec.fieldContext_User_app_data(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||
},
|
||||
@@ -10367,6 +10389,8 @@ func (ec *executionContext) fieldContext_Query__user(ctx context.Context, field
|
||||
return ec.fieldContext_User_revoked_timestamp(ctx, field)
|
||||
case "is_multi_factor_auth_enabled":
|
||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||
case "app_data":
|
||||
return ec.fieldContext_User_app_data(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||
},
|
||||
@@ -12228,6 +12252,47 @@ func (ec *executionContext) fieldContext_User_is_multi_factor_auth_enabled(ctx c
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _User_app_data(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_User_app_data(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.AppData, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(map[string]interface{})
|
||||
fc.Result = res
|
||||
return ec.marshalOMap2map(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_User_app_data(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "User",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type Map does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Users_pagination(ctx context.Context, field graphql.CollectedField, obj *model.Users) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Users_pagination(ctx, field)
|
||||
if err != nil {
|
||||
@@ -12359,6 +12424,8 @@ func (ec *executionContext) fieldContext_Users_users(ctx context.Context, field
|
||||
return ec.fieldContext_User_revoked_timestamp(ctx, field)
|
||||
case "is_multi_factor_auth_enabled":
|
||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||
case "app_data":
|
||||
return ec.fieldContext_User_app_data(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||
},
|
||||
@@ -16200,7 +16267,7 @@ func (ec *executionContext) unmarshalInputMobileSignUpInput(ctx context.Context,
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"email", "given_name", "family_name", "middle_name", "nickname", "gender", "birthdate", "phone_number", "picture", "password", "confirm_password", "roles", "scope", "redirect_uri", "is_multi_factor_auth_enabled", "state"}
|
||||
fieldsInOrder := [...]string{"email", "given_name", "family_name", "middle_name", "nickname", "gender", "birthdate", "phone_number", "picture", "password", "confirm_password", "roles", "scope", "redirect_uri", "is_multi_factor_auth_enabled", "state", "app_data"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -16335,6 +16402,14 @@ func (ec *executionContext) unmarshalInputMobileSignUpInput(ctx context.Context,
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "app_data":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("app_data"))
|
||||
it.AppData, err = ec.unmarshalOMap2map(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16608,7 +16683,7 @@ func (ec *executionContext) unmarshalInputSignUpInput(ctx context.Context, obj i
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"email", "given_name", "family_name", "middle_name", "nickname", "gender", "birthdate", "phone_number", "picture", "password", "confirm_password", "roles", "scope", "redirect_uri", "is_multi_factor_auth_enabled", "state"}
|
||||
fieldsInOrder := [...]string{"email", "given_name", "family_name", "middle_name", "nickname", "gender", "birthdate", "phone_number", "picture", "password", "confirm_password", "roles", "scope", "redirect_uri", "is_multi_factor_auth_enabled", "state", "app_data"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -16743,6 +16818,14 @@ func (ec *executionContext) unmarshalInputSignUpInput(ctx context.Context, obj i
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "app_data":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("app_data"))
|
||||
it.AppData, err = ec.unmarshalOMap2map(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16756,7 +16839,7 @@ func (ec *executionContext) unmarshalInputTestEndpointRequest(ctx context.Contex
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"endpoint", "event_name", "headers"}
|
||||
fieldsInOrder := [...]string{"endpoint", "event_name", "event_description", "headers"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -16779,6 +16862,14 @@ func (ec *executionContext) unmarshalInputTestEndpointRequest(ctx context.Contex
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "event_description":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("event_description"))
|
||||
it.EventDescription, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "headers":
|
||||
var err error
|
||||
|
||||
@@ -17324,7 +17415,7 @@ func (ec *executionContext) unmarshalInputUpdateProfileInput(ctx context.Context
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"old_password", "new_password", "confirm_new_password", "email", "given_name", "family_name", "middle_name", "nickname", "gender", "birthdate", "phone_number", "picture", "is_multi_factor_auth_enabled"}
|
||||
fieldsInOrder := [...]string{"old_password", "new_password", "confirm_new_password", "email", "given_name", "family_name", "middle_name", "nickname", "gender", "birthdate", "phone_number", "picture", "is_multi_factor_auth_enabled", "app_data"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -17435,6 +17526,14 @@ func (ec *executionContext) unmarshalInputUpdateProfileInput(ctx context.Context
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "app_data":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("app_data"))
|
||||
it.AppData, err = ec.unmarshalOMap2map(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17448,7 +17547,7 @@ func (ec *executionContext) unmarshalInputUpdateUserInput(ctx context.Context, o
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"id", "email", "email_verified", "given_name", "family_name", "middle_name", "nickname", "gender", "birthdate", "phone_number", "picture", "roles", "is_multi_factor_auth_enabled"}
|
||||
fieldsInOrder := [...]string{"id", "email", "email_verified", "given_name", "family_name", "middle_name", "nickname", "gender", "birthdate", "phone_number", "picture", "roles", "is_multi_factor_auth_enabled", "app_data"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -17559,6 +17658,14 @@ func (ec *executionContext) unmarshalInputUpdateUserInput(ctx context.Context, o
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "app_data":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("app_data"))
|
||||
it.AppData, err = ec.unmarshalOMap2map(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19465,6 +19572,10 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj
|
||||
|
||||
out.Values[i] = ec._User_is_multi_factor_auth_enabled(ctx, field, obj)
|
||||
|
||||
case "app_data":
|
||||
|
||||
out.Values[i] = ec._User_app_data(ctx, field, obj)
|
||||
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
|
@@ -223,6 +223,7 @@ type MobileSignUpInput struct {
|
||||
RedirectURI *string `json:"redirect_uri"`
|
||||
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
|
||||
State *string `json:"state"`
|
||||
AppData map[string]interface{} `json:"app_data"`
|
||||
}
|
||||
|
||||
type OAuthRevokeInput struct {
|
||||
@@ -298,11 +299,13 @@ type SignUpInput struct {
|
||||
RedirectURI *string `json:"redirect_uri"`
|
||||
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
|
||||
State *string `json:"state"`
|
||||
AppData map[string]interface{} `json:"app_data"`
|
||||
}
|
||||
|
||||
type TestEndpointRequest struct {
|
||||
Endpoint string `json:"endpoint"`
|
||||
EventName string `json:"event_name"`
|
||||
EventDescription *string `json:"event_description"`
|
||||
Headers map[string]interface{} `json:"headers"`
|
||||
}
|
||||
|
||||
@@ -392,6 +395,7 @@ type UpdateProfileInput struct {
|
||||
PhoneNumber *string `json:"phone_number"`
|
||||
Picture *string `json:"picture"`
|
||||
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
|
||||
AppData map[string]interface{} `json:"app_data"`
|
||||
}
|
||||
|
||||
type UpdateUserInput struct {
|
||||
@@ -408,6 +412,7 @@ type UpdateUserInput struct {
|
||||
Picture *string `json:"picture"`
|
||||
Roles []*string `json:"roles"`
|
||||
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
|
||||
AppData map[string]interface{} `json:"app_data"`
|
||||
}
|
||||
|
||||
type UpdateWebhookRequest struct {
|
||||
@@ -439,6 +444,7 @@ type User struct {
|
||||
UpdatedAt *int64 `json:"updated_at"`
|
||||
RevokedTimestamp *int64 `json:"revoked_timestamp"`
|
||||
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
|
||||
AppData map[string]interface{} `json:"app_data"`
|
||||
}
|
||||
|
||||
type Users struct {
|
||||
|
@@ -51,6 +51,7 @@ type User {
|
||||
updated_at: Int64
|
||||
revoked_timestamp: Int64
|
||||
is_multi_factor_auth_enabled: Boolean
|
||||
app_data: Map
|
||||
}
|
||||
|
||||
type Users {
|
||||
@@ -322,6 +323,7 @@ input MobileSignUpInput {
|
||||
# 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
|
||||
app_data: Map
|
||||
}
|
||||
|
||||
input SignUpInput {
|
||||
@@ -344,6 +346,7 @@ input SignUpInput {
|
||||
# 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
|
||||
app_data: Map
|
||||
}
|
||||
|
||||
input LoginInput {
|
||||
@@ -399,6 +402,7 @@ input UpdateProfileInput {
|
||||
phone_number: String
|
||||
picture: String
|
||||
is_multi_factor_auth_enabled: Boolean
|
||||
app_data: Map
|
||||
}
|
||||
|
||||
input UpdateUserInput {
|
||||
@@ -415,6 +419,7 @@ input UpdateUserInput {
|
||||
picture: String
|
||||
roles: [String]
|
||||
is_multi_factor_auth_enabled: Boolean
|
||||
app_data: Map
|
||||
}
|
||||
|
||||
input ForgotPasswordInput {
|
||||
@@ -512,6 +517,7 @@ input WebhookRequest {
|
||||
input TestEndpointRequest {
|
||||
endpoint: String!
|
||||
event_name: String!
|
||||
event_description: String
|
||||
headers: Map
|
||||
}
|
||||
|
||||
|
@@ -260,6 +260,8 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
||||
go func() {
|
||||
if isSignUp {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, provider, user)
|
||||
// User is also logged in with signup
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, provider, user)
|
||||
} else {
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, provider, user)
|
||||
}
|
||||
|
@@ -175,6 +175,8 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
||||
go func() {
|
||||
if isSignUp {
|
||||
utils.RegisterEvent(c, constants.UserSignUpWebhookEvent, loginMethod, user)
|
||||
// User is also logged in with signup
|
||||
utils.RegisterEvent(c, constants.UserLoginWebhookEvent, loginMethod, user)
|
||||
} else {
|
||||
utils.RegisterEvent(c, constants.UserLoginWebhookEvent, loginMethod, user)
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
type provider struct {
|
||||
mutex sync.Mutex
|
||||
sessionStore *stores.SessionStore
|
||||
mfasessionStore *stores.SessionStore
|
||||
stateStore *stores.StateStore
|
||||
envStore *stores.EnvStore
|
||||
}
|
||||
@@ -19,6 +20,7 @@ func NewInMemoryProvider() (*provider, error) {
|
||||
mutex: sync.Mutex{},
|
||||
envStore: stores.NewEnvStore(),
|
||||
sessionStore: stores.NewSessionStore(),
|
||||
mfasessionStore: stores.NewSessionStore(),
|
||||
stateStore: stores.NewStateStore(),
|
||||
}, nil
|
||||
}
|
||||
|
@@ -42,6 +42,27 @@ func (c *provider) DeleteSessionForNamespace(namespace string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetMfaSession sets the mfa session with key and value of userId
|
||||
func (c *provider) SetMfaSession(userId, key string, expiration int64) error {
|
||||
c.mfasessionStore.Set(userId, key, userId, expiration)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMfaSession returns value of given mfa session
|
||||
func (c *provider) GetMfaSession(userId, key string) (string, error) {
|
||||
val := c.mfasessionStore.Get(userId, key)
|
||||
if val == "" {
|
||||
return "", fmt.Errorf("Not found")
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// DeleteMfaSession deletes given mfa session from in-memory store.
|
||||
func (c *provider) DeleteMfaSession(userId, key string) error {
|
||||
c.mfasessionStore.Remove(userId, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetState sets the state in the in-memory store.
|
||||
func (c *provider) SetState(key, state string) error {
|
||||
if os.Getenv("ENV") != constants.TestEnv {
|
||||
|
@@ -112,4 +112,15 @@ func ProviderTests(t *testing.T, p Provider) {
|
||||
key, err = p.GetUserSession("auth_provider1:124", "access_token_key")
|
||||
assert.Empty(t, key)
|
||||
assert.Error(t, err)
|
||||
|
||||
err = p.SetMfaSession("auth_provider:123", "session123", time.Now().Add(60*time.Second).Unix())
|
||||
assert.NoError(t, err)
|
||||
key, err = p.GetMfaSession("auth_provider:123", "session123")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "auth_provider:123", key)
|
||||
err = p.DeleteMfaSession("auth_provider:123", "session123")
|
||||
assert.NoError(t, err)
|
||||
key, err = p.GetMfaSession("auth_provider:123", "session123")
|
||||
assert.Error(t, err)
|
||||
assert.Empty(t, key)
|
||||
}
|
||||
|
@@ -12,6 +12,12 @@ type Provider interface {
|
||||
DeleteAllUserSessions(userId string) error
|
||||
// DeleteSessionForNamespace deletes the session for a given namespace
|
||||
DeleteSessionForNamespace(namespace string) error
|
||||
// SetMfaSession sets the mfa session with key and value of userId
|
||||
SetMfaSession(userId, key string, expiration int64) error
|
||||
// GetMfaSession returns value of given mfa session
|
||||
GetMfaSession(userId, key string) (string, error)
|
||||
// DeleteMfaSession deletes given mfa session from in-memory store.
|
||||
DeleteMfaSession(userId, key string) error
|
||||
|
||||
// SetState sets the login state (key, value form) in the session store
|
||||
SetState(key, state string) error
|
||||
|
@@ -16,6 +16,8 @@ var (
|
||||
envStorePrefix = "authorizer_env"
|
||||
)
|
||||
|
||||
const mfaSessionPrefix = "mfa_sess_"
|
||||
|
||||
// SetUserSession sets the user session for given user identifier in form recipe:user_id
|
||||
func (c *provider) SetUserSession(userId, key, token string, expiration int64) error {
|
||||
currentTime := time.Now()
|
||||
@@ -91,6 +93,37 @@ func (c *provider) DeleteSessionForNamespace(namespace string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetMfaSession sets the mfa session with key and value of userId
|
||||
func (c *provider) SetMfaSession(userId, key string, expiration int64) error {
|
||||
currentTime := time.Now()
|
||||
expireTime := time.Unix(expiration, 0)
|
||||
duration := expireTime.Sub(currentTime)
|
||||
err := c.store.Set(c.ctx, fmt.Sprintf("%s%s:%s", mfaSessionPrefix, userId, key), userId, duration).Err()
|
||||
if err != nil {
|
||||
log.Debug("Error saving user session to redis: ", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMfaSession returns value of given mfa session
|
||||
func (c *provider) GetMfaSession(userId, key string) (string, error) {
|
||||
data, err := c.store.Get(c.ctx, fmt.Sprintf("%s%s:%s", mfaSessionPrefix, userId, key)).Result()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// DeleteMfaSession deletes given mfa session from in-memory store.
|
||||
func (c *provider) DeleteMfaSession(userId, key string) error {
|
||||
if err := c.store.Del(c.ctx, fmt.Sprintf("%s%s:%s", mfaSessionPrefix, userId, key)).Err(); err != nil {
|
||||
log.Debug("Error deleting user session from redis: ", err)
|
||||
// continue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetState sets the state in redis store.
|
||||
func (c *provider) SetState(key, value string) error {
|
||||
err := c.store.Set(c.ctx, stateStorePrefix+key, value, 0).Err()
|
||||
|
@@ -10,11 +10,16 @@ import (
|
||||
githubOAuth2 "golang.org/x/oauth2/github"
|
||||
linkedInOAuth2 "golang.org/x/oauth2/linkedin"
|
||||
microsoftOAuth2 "golang.org/x/oauth2/microsoft"
|
||||
"google.golang.org/appengine/log"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
)
|
||||
|
||||
const (
|
||||
microsoftCommonTenant = "common"
|
||||
)
|
||||
|
||||
// OAuthProviders is a struct that contains reference all the OAuth providers
|
||||
type OAuthProvider struct {
|
||||
GoogleConfig *oauth2.Config
|
||||
@@ -171,12 +176,16 @@ func InitOAuth() error {
|
||||
microsoftClientSecret = ""
|
||||
}
|
||||
microsoftActiveDirTenantID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyMicrosoftActiveDirectoryTenantID)
|
||||
if err != nil {
|
||||
microsoftActiveDirTenantID = "common"
|
||||
if err != nil || microsoftActiveDirTenantID == "" {
|
||||
microsoftActiveDirTenantID = microsoftCommonTenant
|
||||
}
|
||||
if microsoftClientID != "" && microsoftClientSecret != "" {
|
||||
if microsoftActiveDirTenantID == microsoftCommonTenant {
|
||||
ctx = oidc.InsecureIssuerURLContext(ctx, fmt.Sprintf("https://login.microsoftonline.com/%s/v2.0", microsoftActiveDirTenantID))
|
||||
}
|
||||
if microsoftClientID != "" && microsoftClientSecret != "" && microsoftActiveDirTenantID != "" {
|
||||
p, err := oidc.NewProvider(ctx, fmt.Sprintf("https://login.microsoftonline.com/%s/v2.0", microsoftActiveDirTenantID))
|
||||
if err != nil {
|
||||
log.Debugf(ctx, "Error while creating OIDC provider for Microsoft: %v", err)
|
||||
return err
|
||||
}
|
||||
OIDCProviders.MicrosoftOIDC = p
|
||||
|
@@ -113,16 +113,25 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
||||
// If email service is not enabled continue the process in any way
|
||||
if refs.BoolValue(user.IsMultiFactorAuthEnabled) && isEmailServiceEnabled && !isMFADisabled {
|
||||
otp := utils.GenerateOTP()
|
||||
expires := time.Now().Add(1 * time.Minute).Unix()
|
||||
otpData, err := db.Provider.UpsertOTP(ctx, &models.OTP{
|
||||
Email: user.Email,
|
||||
Otp: otp,
|
||||
ExpiresAt: time.Now().Add(1 * time.Minute).Unix(),
|
||||
ExpiresAt: expires,
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("Failed to add otp: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mfaSession := uuid.NewString()
|
||||
err = memorystore.Provider.SetMfaSession(user.ID, mfaSession, expires)
|
||||
if err != nil {
|
||||
log.Debug("Failed to add mfasession: ", err)
|
||||
return nil, err
|
||||
}
|
||||
cookie.SetMfaSession(gc, mfaSession)
|
||||
|
||||
go func() {
|
||||
// exec it as go routine so that we can reduce the api latency
|
||||
go email.SendEmail([]string{params.Email}, constants.VerificationTypeOTP, map[string]interface{}{
|
||||
@@ -162,7 +171,6 @@ 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)
|
||||
|
@@ -122,15 +122,25 @@ func MobileLoginResolver(ctx context.Context, params model.MobileLoginInput) (*m
|
||||
smsBody := strings.Builder{}
|
||||
smsBody.WriteString("Your verification code is: ")
|
||||
smsBody.WriteString(smsCode)
|
||||
expires := time.Now().Add(duration).Unix()
|
||||
_, err := db.Provider.UpsertOTP(ctx, &models.OTP{
|
||||
PhoneNumber: params.PhoneNumber,
|
||||
Otp: smsCode,
|
||||
ExpiresAt: time.Now().Add(duration).Unix(),
|
||||
ExpiresAt: expires,
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("error while upserting OTP: ", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mfaSession := uuid.NewString()
|
||||
err = memorystore.Provider.SetMfaSession(user.ID, mfaSession, expires)
|
||||
if err != nil {
|
||||
log.Debug("Failed to add mfasession: ", err)
|
||||
return nil, err
|
||||
}
|
||||
cookie.SetMfaSession(gc, mfaSession)
|
||||
|
||||
go func() {
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, user)
|
||||
smsproviders.SendSMS(params.PhoneNumber, smsBody.String())
|
||||
|
@@ -223,6 +223,7 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||
}
|
||||
go func() {
|
||||
smsproviders.SendSMS(mobile, smsBody.String())
|
||||
utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
||||
}()
|
||||
return &model.AuthResponse{
|
||||
Message: "Please check the OTP in your inbox",
|
||||
@@ -298,6 +299,8 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||
|
||||
go func() {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, user)
|
||||
// User is also logged in with signup
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, user)
|
||||
db.Provider.AddSession(ctx, &models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
|
@@ -2,6 +2,8 @@ package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -171,6 +173,17 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
||||
user.IsMultiFactorAuthEnabled = refs.NewBoolRef(true)
|
||||
}
|
||||
|
||||
if params.AppData != nil {
|
||||
appDataString := ""
|
||||
appDataBytes, err := json.Marshal(params.AppData)
|
||||
if err != nil {
|
||||
log.Debug("failed to marshall source app_data: ", err)
|
||||
return nil, errors.New("malformed app_data")
|
||||
}
|
||||
appDataString = string(appDataBytes)
|
||||
user.AppData = &appDataString
|
||||
}
|
||||
|
||||
user.SignupMethods = constants.AuthRecipeMethodBasicAuth
|
||||
isEmailVerificationDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification)
|
||||
if err != nil {
|
||||
@@ -301,6 +314,8 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
||||
|
||||
go func() {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
||||
// User is also logged in with signup
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
||||
db.Provider.AddSession(ctx, &models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
|
@@ -2,6 +2,7 @@ package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
@@ -47,7 +48,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
||||
}
|
||||
|
||||
// validate if all params are not empty
|
||||
if params.GivenName == nil && params.FamilyName == nil && params.Picture == nil && params.MiddleName == nil && params.Nickname == nil && params.OldPassword == nil && params.Email == nil && params.Birthdate == nil && params.Gender == nil && params.PhoneNumber == nil && params.NewPassword == nil && params.ConfirmNewPassword == nil && params.IsMultiFactorAuthEnabled == nil {
|
||||
if params.GivenName == nil && params.FamilyName == nil && params.Picture == nil && params.MiddleName == nil && params.Nickname == nil && params.OldPassword == nil && params.Email == nil && params.Birthdate == nil && params.Gender == nil && params.PhoneNumber == nil && params.NewPassword == nil && params.ConfirmNewPassword == nil && params.IsMultiFactorAuthEnabled == nil && params.AppData == nil {
|
||||
log.Debug("All params are empty")
|
||||
return res, fmt.Errorf("please enter at least one param to update")
|
||||
}
|
||||
@@ -56,7 +57,6 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
||||
log := log.WithFields(log.Fields{
|
||||
"user_id": userID,
|
||||
})
|
||||
|
||||
user, err := db.Provider.GetUserByID(ctx, userID)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by id: ", err)
|
||||
@@ -99,7 +99,16 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
||||
if params.Picture != nil && refs.StringValue(user.Picture) != refs.StringValue(params.Picture) {
|
||||
user.Picture = params.Picture
|
||||
}
|
||||
|
||||
if params.AppData != nil {
|
||||
appDataString := ""
|
||||
appDataBytes, err := json.Marshal(params.AppData)
|
||||
if err != nil {
|
||||
log.Debug("failed to marshall source app_data: ", err)
|
||||
return nil, errors.New("malformed app_data")
|
||||
}
|
||||
appDataString = string(appDataBytes)
|
||||
user.AppData = &appDataString
|
||||
}
|
||||
if params.IsMultiFactorAuthEnabled != nil && refs.BoolValue(user.IsMultiFactorAuthEnabled) != refs.BoolValue(params.IsMultiFactorAuthEnabled) {
|
||||
if refs.BoolValue(params.IsMultiFactorAuthEnabled) {
|
||||
isEnvServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
|
||||
|
@@ -2,6 +2,7 @@ package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
@@ -95,6 +96,17 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
||||
user.Picture = params.Picture
|
||||
}
|
||||
|
||||
if params.AppData != nil {
|
||||
appDataString := ""
|
||||
appDataBytes, err := json.Marshal(params.AppData)
|
||||
if err != nil {
|
||||
log.Debug("failed to marshall source app_data: ", err)
|
||||
return nil, errors.New("malformed app_data")
|
||||
}
|
||||
appDataString = string(appDataBytes)
|
||||
user.AppData = &appDataString
|
||||
}
|
||||
|
||||
if params.IsMultiFactorAuthEnabled != nil && refs.BoolValue(user.IsMultiFactorAuthEnabled) != refs.BoolValue(params.IsMultiFactorAuthEnabled) {
|
||||
user.IsMultiFactorAuthEnabled = params.IsMultiFactorAuthEnabled
|
||||
if refs.BoolValue(params.IsMultiFactorAuthEnabled) {
|
||||
|
@@ -125,6 +125,8 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
|
||||
go func() {
|
||||
if isSignUp {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, loginMethod, user)
|
||||
// User is also logged in with signup
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, loginMethod, user)
|
||||
} else {
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, loginMethod, user)
|
||||
}
|
||||
|
@@ -27,6 +27,13 @@ func VerifyOtpResolver(ctx context.Context, params model.VerifyOTPRequest) (*mod
|
||||
log.Debug("Failed to get GinContext: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
mfaSession, err := cookie.GetMfaSession(gc)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get otp request by email: ", err)
|
||||
return res, fmt.Errorf(`invalid session: %s`, err.Error())
|
||||
}
|
||||
|
||||
if refs.StringValue(params.Email) == "" && refs.StringValue(params.PhoneNumber) == "" {
|
||||
log.Debug("Email or phone number is required")
|
||||
return res, fmt.Errorf(`email or phone_number is required`)
|
||||
@@ -66,6 +73,12 @@ func VerifyOtpResolver(ctx context.Context, params model.VerifyOTPRequest) (*mod
|
||||
log.Debug("Failed to get user by email or phone number: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
if _, err := memorystore.Provider.GetMfaSession(user.ID, mfaSession); err != nil {
|
||||
log.Debug("Failed to get mfa session: ", err)
|
||||
return res, fmt.Errorf(`invalid session: %s`, err.Error())
|
||||
}
|
||||
|
||||
isSignUp := user.EmailVerifiedAt == nil && user.PhoneNumberVerifiedAt == nil
|
||||
// TODO - Add Login method in DB when we introduce OTP for social media login
|
||||
loginMethod := constants.AuthRecipeMethodBasicAuth
|
||||
@@ -112,6 +125,8 @@ func VerifyOtpResolver(ctx context.Context, params model.VerifyOTPRequest) (*mod
|
||||
db.Provider.DeleteOTP(gc, otp)
|
||||
if isSignUp {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, loginMethod, user)
|
||||
// User is also logged in with signup
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, loginMethod, user)
|
||||
} else {
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, loginMethod, user)
|
||||
}
|
||||
|
@@ -386,6 +386,7 @@ func CreateIDToken(user *models.User, roles []string, hostname, nonce, atHash, c
|
||||
userBytes, _ := json.Marshal(&resUser)
|
||||
var userMap map[string]interface{}
|
||||
json.Unmarshal(userBytes, &userMap)
|
||||
fmt.Println("=> userBytes", string(userBytes))
|
||||
claimKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtRoleClaim)
|
||||
if err != nil {
|
||||
claimKey = "roles"
|
||||
|
Reference in New Issue
Block a user