Merge branch 'main' into feat/disable_playground
# Conflicts: # app/yarn.lock # dashboard/yarn.lock # server/constants/env.go # server/env/env.go # server/env/persist_env.go # server/graph/model/models_gen.go # server/memorystore/providers/redis/store.go
This commit is contained in:
@@ -47,7 +47,7 @@ func AddEmailTemplateResolver(ctx context.Context, params model.AddEmailTemplate
|
||||
design = ""
|
||||
}
|
||||
|
||||
_, err = db.Provider.AddEmailTemplate(ctx, models.EmailTemplate{
|
||||
_, err = db.Provider.AddEmailTemplate(ctx, &models.EmailTemplate{
|
||||
EventName: params.EventName,
|
||||
Template: params.Template,
|
||||
Subject: params.Subject,
|
||||
|
@@ -43,7 +43,7 @@ func AddWebhookResolver(ctx context.Context, params model.AddWebhookRequest) (*m
|
||||
if params.EventDescription == nil {
|
||||
params.EventDescription = refs.NewStringRef(strings.Join(strings.Split(params.EventName, "."), " "))
|
||||
}
|
||||
_, err = db.Provider.AddWebhook(ctx, models.Webhook{
|
||||
_, err = db.Provider.AddWebhook(ctx, &models.Webhook{
|
||||
EventDescription: refs.StringValue(params.EventDescription),
|
||||
EventName: params.EventName,
|
||||
EndPoint: params.Endpoint,
|
||||
|
@@ -25,7 +25,6 @@ func EmailTemplatesResolver(ctx context.Context, params *model.PaginatedInput) (
|
||||
}
|
||||
|
||||
pagination := utils.GetPagination(params)
|
||||
|
||||
emailTemplates, err := db.Provider.ListEmailTemplate(ctx, pagination)
|
||||
if err != nil {
|
||||
log.Debug("failed to get email templates: ", err)
|
||||
|
@@ -81,7 +81,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
||||
log.Debug("Failed to create verification token", err)
|
||||
return res, err
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, &models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: constants.VerificationTypeForgotPassword,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
@@ -105,7 +105,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
|
||||
defaultRoles = strings.Split(defaultRolesString, ",")
|
||||
}
|
||||
|
||||
user := models.User{
|
||||
user := &models.User{
|
||||
Email: email,
|
||||
Roles: strings.Join(defaultRoles, ","),
|
||||
}
|
||||
@@ -128,7 +128,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
|
||||
log.Debug("Failed to create verification token: ", err)
|
||||
}
|
||||
|
||||
verificationRequest := models.VerificationRequest{
|
||||
verificationRequest := &models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
Email: email,
|
||||
|
@@ -106,23 +106,32 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
||||
}
|
||||
|
||||
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
|
||||
if err != nil || !isEmailServiceEnabled {
|
||||
if err != nil || !isMFADisabled {
|
||||
log.Debug("MFA service not enabled: ", err)
|
||||
}
|
||||
|
||||
// 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{}{
|
||||
@@ -136,8 +145,8 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
||||
}()
|
||||
|
||||
return &model.AuthResponse{
|
||||
Message: "Please check the OTP in your inbox",
|
||||
ShouldShowOtpScreen: refs.NewBoolRef(true),
|
||||
Message: "Please check the OTP in your inbox",
|
||||
ShouldShowEmailOtpScreen: refs.NewBoolRef(true),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -203,7 +211,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
||||
|
||||
go func() {
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
||||
db.Provider.AddSession(ctx, models.Session{
|
||||
db.Provider.AddSession(ctx, &models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
|
@@ -55,7 +55,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
||||
|
||||
inputRoles := []string{}
|
||||
|
||||
user := models.User{
|
||||
user := &models.User{
|
||||
Email: params.Email,
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
||||
if err != nil {
|
||||
log.Debug("Failed to create verification token: ", err)
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, &models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: verificationType,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
@@ -101,12 +101,6 @@ func MetaResolver(ctx context.Context) (*model.Meta, error) {
|
||||
microsoftClientSecret = ""
|
||||
}
|
||||
|
||||
microsoftActiveDirTenantID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyMicrosoftActiveDirectoryTenantID)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get Microsoft Active Directory Tenant ID from environment variable", err)
|
||||
microsoftActiveDirTenantID = ""
|
||||
}
|
||||
|
||||
isBasicAuthDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get Disable Basic Authentication from environment variable", err)
|
||||
@@ -152,7 +146,7 @@ func MetaResolver(ctx context.Context) (*model.Meta, error) {
|
||||
IsLinkedinLoginEnabled: linkedClientID != "" && linkedInClientSecret != "",
|
||||
IsAppleLoginEnabled: appleClientID != "" && appleClientSecret != "",
|
||||
IsTwitterLoginEnabled: twitterClientID != "" && twitterClientSecret != "",
|
||||
IsMicrosoftLoginEnabled: microsoftClientID != "" && microsoftClientSecret != "" && microsoftActiveDirTenantID != "",
|
||||
IsMicrosoftLoginEnabled: microsoftClientID != "" && microsoftClientSecret != "",
|
||||
IsBasicAuthenticationEnabled: !isBasicAuthDisabled,
|
||||
IsEmailVerificationEnabled: !isEmailVerificationDisabled,
|
||||
IsMagicLinkLoginEnabled: !isMagicLinkLoginDisabled,
|
||||
|
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/refs"
|
||||
"github.com/authorizerdev/authorizer/server/smsproviders"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/authorizerdev/authorizer/server/validators"
|
||||
@@ -94,55 +95,67 @@ func MobileLoginResolver(ctx context.Context, params model.MobileLoginInput) (*m
|
||||
roles = params.Roles
|
||||
}
|
||||
|
||||
disablePhoneVerification, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisablePhoneVerification)
|
||||
if err != nil {
|
||||
log.Debug("Error getting disable phone verification: ", err)
|
||||
}
|
||||
if disablePhoneVerification {
|
||||
now := time.Now().Unix()
|
||||
user.PhoneNumberVerifiedAt = &now
|
||||
}
|
||||
isSMSServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsSMSServiceEnabled)
|
||||
if err != nil || !isSMSServiceEnabled {
|
||||
log.Debug("SMS service not enabled: ", err)
|
||||
}
|
||||
if disablePhoneVerification {
|
||||
now := time.Now().Unix()
|
||||
user.PhoneNumberVerifiedAt = &now
|
||||
}
|
||||
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
|
||||
if err != nil || !isMFADisabled {
|
||||
log.Debug("MFA service not enabled: ", err)
|
||||
}
|
||||
if !disablePhoneVerification && isSMSServiceEnabled && !isMFADisabled {
|
||||
duration, _ := time.ParseDuration("10m")
|
||||
smsCode := utils.GenerateOTP()
|
||||
|
||||
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: 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())
|
||||
}()
|
||||
return &model.AuthResponse{
|
||||
Message: "Please check the OTP",
|
||||
ShouldShowMobileOtpScreen: refs.NewBoolRef(true),
|
||||
}, nil
|
||||
}
|
||||
|
||||
scope := []string{"openid", "email", "profile"}
|
||||
if params.Scope != nil && len(scope) > 0 {
|
||||
scope = params.Scope
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO use sms authentication for MFA
|
||||
isEmailServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
|
||||
if err != nil || !isEmailServiceEnabled {
|
||||
log.Debug("Email service not enabled: ", err)
|
||||
}
|
||||
|
||||
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
|
||||
if err != nil || !isEmailServiceEnabled {
|
||||
log.Debug("MFA service not enabled: ", err)
|
||||
}
|
||||
|
||||
// If email service is not enabled continue the process in any way
|
||||
if refs.BoolValue(user.IsMultiFactorAuthEnabled) && isEmailServiceEnabled && !isMFADisabled {
|
||||
otp := utils.GenerateOTP()
|
||||
otpData, err := db.Provider.UpsertOTP(ctx, &models.OTP{
|
||||
Email: user.Email,
|
||||
Otp: otp,
|
||||
ExpiresAt: time.Now().Add(1 * time.Minute).Unix(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("Failed to add otp: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
// exec it as go routine so that we can reduce the api latency
|
||||
go email.SendEmail([]string{params.PhoneNumber}, constants.VerificationTypeOTP, map[string]interface{}{
|
||||
"user": user.ToMap(),
|
||||
"organization": utils.GetOrganization(),
|
||||
"otp": otpData.Otp,
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("Failed to send otp email: ", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return &model.AuthResponse{
|
||||
Message: "Please check the OTP in your inbox",
|
||||
ShouldShowOtpScreen: refs.NewBoolRef(true),
|
||||
}, nil
|
||||
}
|
||||
*/
|
||||
|
||||
code := ""
|
||||
codeChallenge := ""
|
||||
nonce := ""
|
||||
@@ -165,7 +178,7 @@ func MobileLoginResolver(ctx context.Context, params model.MobileLoginInput) (*m
|
||||
nonce = uuid.New().String()
|
||||
}
|
||||
|
||||
authToken, err := token.CreateAuthToken(gc, *user, roles, scope, constants.AuthRecipeMethodMobileBasicAuth, nonce, code)
|
||||
authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodMobileBasicAuth, nonce, code)
|
||||
if err != nil {
|
||||
log.Debug("Failed to create auth token", err)
|
||||
return res, err
|
||||
@@ -204,8 +217,8 @@ func MobileLoginResolver(ctx context.Context, params model.MobileLoginInput) (*m
|
||||
}
|
||||
|
||||
go func() {
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, *user)
|
||||
db.Provider.AddSession(ctx, models.Session{
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, user)
|
||||
db.Provider.AddSession(ctx, &models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/cookie"
|
||||
"github.com/authorizerdev/authorizer/server/crypto"
|
||||
@@ -17,9 +17,9 @@ import (
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/refs"
|
||||
"github.com/authorizerdev/authorizer/server/smsproviders"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/authorizerdev/authorizer/server/smsproviders"
|
||||
"github.com/authorizerdev/authorizer/server/validators"
|
||||
)
|
||||
|
||||
@@ -92,7 +92,6 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by email: ", err)
|
||||
}
|
||||
|
||||
if existingUser != nil {
|
||||
if existingUser.PhoneNumberVerifiedAt != nil {
|
||||
// email is verified
|
||||
@@ -105,7 +104,6 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||
}
|
||||
|
||||
inputRoles := []string{}
|
||||
|
||||
if len(params.Roles) > 0 {
|
||||
// check if roles exists
|
||||
rolesString, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyRoles)
|
||||
@@ -132,9 +130,9 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||
}
|
||||
}
|
||||
|
||||
user := models.User{
|
||||
Email: emailInput,
|
||||
PhoneNumber: &mobile,
|
||||
user := &models.User{
|
||||
Email: emailInput,
|
||||
PhoneNumber: &mobile,
|
||||
}
|
||||
|
||||
user.Roles = strings.Join(inputRoles, ",")
|
||||
@@ -179,7 +177,7 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||
log.Debug("MFA service not enabled: ", err)
|
||||
isMFAEnforced = false
|
||||
}
|
||||
|
||||
|
||||
if isMFAEnforced {
|
||||
user.IsMultiFactorAuthEnabled = refs.NewBoolRef(true)
|
||||
}
|
||||
@@ -189,6 +187,10 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||
now := time.Now().Unix()
|
||||
user.PhoneNumberVerifiedAt = &now
|
||||
}
|
||||
isSMSServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsSMSServiceEnabled)
|
||||
if err != nil || !isSMSServiceEnabled {
|
||||
log.Debug("SMS service not enabled: ", err)
|
||||
}
|
||||
|
||||
user.SignupMethods = constants.AuthRecipeMethodMobileBasicAuth
|
||||
user, err = db.Provider.AddUser(ctx, user)
|
||||
@@ -197,11 +199,10 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||
log.Debug("Failed to add user: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
if !disablePhoneVerification {
|
||||
if !disablePhoneVerification && isSMSServiceEnabled {
|
||||
duration, _ := time.ParseDuration("10m")
|
||||
smsCode := utils.GenerateOTP()
|
||||
|
||||
|
||||
smsBody := strings.Builder{}
|
||||
smsBody.WriteString("Your verification code is: ")
|
||||
smsBody.WriteString(smsCode)
|
||||
@@ -211,15 +212,23 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||
log.Debug("error while upserting user: ", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = db.Provider.UpsertOTP(ctx, &models.OTP{
|
||||
PhoneNumber: mobile,
|
||||
Otp: smsCode,
|
||||
ExpiresAt: time.Now().Add(duration).Unix(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("error while upserting OTP: ", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
go func() {
|
||||
db.Provider.UpsertSMSRequest(ctx, &models.SMSVerificationRequest{
|
||||
PhoneNumber: mobile,
|
||||
Code: smsCode,
|
||||
CodeExpiresAt: time.Now().Add(duration).Unix(),
|
||||
})
|
||||
smsproviders.SendSMS(mobile, smsBody.String())
|
||||
utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
||||
}()
|
||||
return &model.AuthResponse{
|
||||
Message: "Please check the OTP in your inbox",
|
||||
ShouldShowMobileOtpScreen: refs.NewBoolRef(true),
|
||||
}, nil
|
||||
}
|
||||
|
||||
roles := strings.Split(user.Roles, ",")
|
||||
@@ -290,7 +299,9 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||
|
||||
go func() {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, user)
|
||||
db.Provider.AddSession(ctx, models.Session{
|
||||
// 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),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
|
@@ -12,23 +12,46 @@ import (
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/email"
|
||||
emailHelper "github.com/authorizerdev/authorizer/server/email"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/refs"
|
||||
"github.com/authorizerdev/authorizer/server/smsproviders"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
// ResendOTPResolver is a resolver for resend otp mutation
|
||||
func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*model.Response, error) {
|
||||
email := strings.ToLower(strings.Trim(refs.StringValue(params.Email), " "))
|
||||
phoneNumber := strings.Trim(refs.StringValue(params.PhoneNumber), " ")
|
||||
log := log.WithFields(log.Fields{
|
||||
"email": params.Email,
|
||||
"email": email,
|
||||
"phone_number": phoneNumber,
|
||||
})
|
||||
params.Email = strings.ToLower(params.Email)
|
||||
user, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
||||
if email == "" && phoneNumber == "" {
|
||||
log.Debug("Email or phone number is required")
|
||||
return nil, errors.New("email or phone number is required")
|
||||
}
|
||||
var user *models.User
|
||||
var err error
|
||||
if email != "" {
|
||||
isEmailServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
|
||||
if err != nil || !isEmailServiceEnabled {
|
||||
log.Debug("Email service not enabled: ", err)
|
||||
return nil, errors.New("email service not enabled")
|
||||
}
|
||||
user, err = db.Provider.GetUserByEmail(ctx, email)
|
||||
} else {
|
||||
isSMSServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
|
||||
if err != nil || !isSMSServiceEnabled {
|
||||
log.Debug("Email service not enabled: ", err)
|
||||
return nil, errors.New("email service not enabled")
|
||||
}
|
||||
user, err = db.Provider.GetUserByPhoneNumber(ctx, phoneNumber)
|
||||
}
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by email: ", err)
|
||||
return nil, fmt.Errorf(`user with this email not found`)
|
||||
return nil, fmt.Errorf(`user with this email/phone not found`)
|
||||
}
|
||||
|
||||
if user.RevokedTimestamp != nil {
|
||||
@@ -36,35 +59,38 @@ func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*mod
|
||||
return nil, fmt.Errorf(`user access has been revoked`)
|
||||
}
|
||||
|
||||
if user.EmailVerifiedAt == nil {
|
||||
if email != "" && user.EmailVerifiedAt == nil {
|
||||
log.Debug("User email is not verified")
|
||||
return nil, fmt.Errorf(`email not verified`)
|
||||
}
|
||||
|
||||
if phoneNumber != "" && user.PhoneNumberVerifiedAt == nil {
|
||||
log.Debug("User phone number is not verified")
|
||||
return nil, fmt.Errorf(`phone number not verified`)
|
||||
}
|
||||
|
||||
if !refs.BoolValue(user.IsMultiFactorAuthEnabled) {
|
||||
log.Debug("User multi factor authentication is not enabled")
|
||||
return nil, fmt.Errorf(`multi factor authentication not enabled`)
|
||||
}
|
||||
|
||||
isEmailServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
|
||||
if err != nil || !isEmailServiceEnabled {
|
||||
log.Debug("Email service not enabled: ", err)
|
||||
return nil, errors.New("email service not enabled")
|
||||
}
|
||||
|
||||
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
|
||||
if err != nil || isMFADisabled {
|
||||
log.Debug("MFA service not enabled: ", err)
|
||||
return nil, errors.New("multi factor authentication is disabled for this instance")
|
||||
}
|
||||
|
||||
// get otp by email
|
||||
otpData, err := db.Provider.GetOTPByEmail(ctx, params.Email)
|
||||
// get otp by email or phone number
|
||||
var otpData *models.OTP
|
||||
if email != "" {
|
||||
otpData, err = db.Provider.GetOTPByEmail(ctx, refs.StringValue(params.Email))
|
||||
} else {
|
||||
otpData, err = db.Provider.GetOTPByPhoneNumber(ctx, refs.StringValue(params.PhoneNumber))
|
||||
}
|
||||
if err != nil {
|
||||
log.Debug("Failed to get otp for given email: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if otpData == nil {
|
||||
log.Debug("No otp found for given email: ", params.Email)
|
||||
return &model.Response{
|
||||
@@ -73,28 +99,30 @@ func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*mod
|
||||
}
|
||||
|
||||
otp := utils.GenerateOTP()
|
||||
otpData, err = db.Provider.UpsertOTP(ctx, &models.OTP{
|
||||
if _, err := db.Provider.UpsertOTP(ctx, &models.OTP{
|
||||
Email: user.Email,
|
||||
Otp: otp,
|
||||
ExpiresAt: time.Now().Add(1 * time.Minute).Unix(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("Error generating new otp: ", err)
|
||||
}); err != nil {
|
||||
log.Debug("Error upserting otp: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
if email != "" {
|
||||
// exec it as go routine so that we can reduce the api latency
|
||||
go email.SendEmail([]string{params.Email}, constants.VerificationTypeOTP, map[string]interface{}{
|
||||
go emailHelper.SendEmail([]string{email}, constants.VerificationTypeOTP, map[string]interface{}{
|
||||
"user": user.ToMap(),
|
||||
"organization": utils.GetOrganization(),
|
||||
"otp": otp,
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("Error sending otp email: ", otp)
|
||||
}
|
||||
}()
|
||||
|
||||
} else {
|
||||
smsBody := strings.Builder{}
|
||||
smsBody.WriteString("Your verification code is: ")
|
||||
smsBody.WriteString(otp)
|
||||
// exec it as go routine so that we can reduce the api latency
|
||||
go smsproviders.SendSMS(phoneNumber, smsBody.String())
|
||||
}
|
||||
log.Info("OTP has been resent")
|
||||
return &model.Response{
|
||||
Message: `OTP has been sent. Please check your inbox`,
|
||||
}, nil
|
||||
|
@@ -67,7 +67,7 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
|
||||
if err != nil {
|
||||
log.Debug("Failed to create verification token: ", err)
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, &models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: params.Identifier,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
@@ -2,6 +2,8 @@ package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -81,13 +83,15 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
||||
log.Debug("Failed to get user by email: ", err)
|
||||
}
|
||||
|
||||
if existingUser.EmailVerifiedAt != nil {
|
||||
// email is verified
|
||||
log.Debug("Email is already verified and signed up.")
|
||||
return res, fmt.Errorf(`%s has already signed up`, params.Email)
|
||||
} else if existingUser.ID != "" && existingUser.EmailVerifiedAt == nil {
|
||||
log.Debug("Email is already signed up. Verification pending...")
|
||||
return res, fmt.Errorf("%s has already signed up. please complete the email verification process or reset the password", params.Email)
|
||||
if existingUser != nil {
|
||||
if existingUser.EmailVerifiedAt != nil {
|
||||
// email is verified
|
||||
log.Debug("Email is already verified and signed up.")
|
||||
return res, fmt.Errorf(`%s has already signed up`, params.Email)
|
||||
} else if existingUser.ID != "" && existingUser.EmailVerifiedAt == nil {
|
||||
log.Debug("Email is already signed up. Verification pending...")
|
||||
return res, fmt.Errorf("%s has already signed up. please complete the email verification process or reset the password", params.Email)
|
||||
}
|
||||
}
|
||||
|
||||
inputRoles := []string{}
|
||||
@@ -116,13 +120,10 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
||||
inputRoles = strings.Split(inputRolesString, ",")
|
||||
}
|
||||
}
|
||||
|
||||
user := models.User{
|
||||
user := &models.User{
|
||||
Email: params.Email,
|
||||
}
|
||||
|
||||
user.Roles = strings.Join(inputRoles, ",")
|
||||
|
||||
password, _ := crypto.EncryptPassword(params.Password)
|
||||
user.Password = &password
|
||||
|
||||
@@ -172,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 {
|
||||
@@ -208,7 +220,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
||||
log.Debug("Failed to create verification token: ", err)
|
||||
return res, err
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, &models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: verificationType,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
@@ -302,7 +314,9 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
||||
|
||||
go func() {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
||||
db.Provider.AddSession(ctx, models.Session{
|
||||
// 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),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
|
@@ -34,7 +34,7 @@ func UpdateEmailTemplateResolver(ctx context.Context, params model.UpdateEmailTe
|
||||
return nil, err
|
||||
}
|
||||
|
||||
emailTemplateDetails := models.EmailTemplate{
|
||||
emailTemplateDetails := &models.EmailTemplate{
|
||||
ID: emailTemplate.ID,
|
||||
Key: emailTemplate.ID,
|
||||
EventName: emailTemplate.EventName,
|
||||
|
@@ -33,7 +33,7 @@ func clearSessionIfRequired(currentData, updatedData map[string]interface{}) {
|
||||
isCurrentGithubLoginEnabled := currentData[constants.EnvKeyGithubClientID] != nil && currentData[constants.EnvKeyGithubClientSecret] != nil && currentData[constants.EnvKeyGithubClientID].(string) != "" && currentData[constants.EnvKeyGithubClientSecret].(string) != ""
|
||||
isCurrentLinkedInLoginEnabled := currentData[constants.EnvKeyLinkedInClientID] != nil && currentData[constants.EnvKeyLinkedInClientSecret] != nil && currentData[constants.EnvKeyLinkedInClientID].(string) != "" && currentData[constants.EnvKeyLinkedInClientSecret].(string) != ""
|
||||
isCurrentTwitterLoginEnabled := currentData[constants.EnvKeyTwitterClientID] != nil && currentData[constants.EnvKeyTwitterClientSecret] != nil && currentData[constants.EnvKeyTwitterClientID].(string) != "" && currentData[constants.EnvKeyTwitterClientSecret].(string) != ""
|
||||
isCurrentMicrosoftLoginEnabled := currentData[constants.EnvKeyMicrosoftClientID] != nil && currentData[constants.EnvKeyMicrosoftClientSecret] != nil && currentData[constants.EnvKeyMicrosoftActiveDirectoryTenantID] != nil && currentData[constants.EnvKeyMicrosoftClientID].(string) != "" && currentData[constants.EnvKeyMicrosoftClientSecret].(string) != "" && currentData[constants.EnvKeyMicrosoftActiveDirectoryTenantID].(string) != ""
|
||||
isCurrentMicrosoftLoginEnabled := currentData[constants.EnvKeyMicrosoftClientID] != nil && currentData[constants.EnvKeyMicrosoftClientSecret] != nil && currentData[constants.EnvKeyMicrosoftClientID].(string) != "" && currentData[constants.EnvKeyMicrosoftClientSecret].(string) != ""
|
||||
|
||||
isUpdatedBasicAuthEnabled := !updatedData[constants.EnvKeyDisableBasicAuthentication].(bool)
|
||||
isUpdatedMobileBasicAuthEnabled := !updatedData[constants.EnvKeyDisableMobileBasicAuthentication].(bool)
|
||||
@@ -44,7 +44,7 @@ func clearSessionIfRequired(currentData, updatedData map[string]interface{}) {
|
||||
isUpdatedGithubLoginEnabled := updatedData[constants.EnvKeyGithubClientID] != nil && updatedData[constants.EnvKeyGithubClientSecret] != nil && updatedData[constants.EnvKeyGithubClientID].(string) != "" && updatedData[constants.EnvKeyGithubClientSecret].(string) != ""
|
||||
isUpdatedLinkedInLoginEnabled := updatedData[constants.EnvKeyLinkedInClientID] != nil && updatedData[constants.EnvKeyLinkedInClientSecret] != nil && updatedData[constants.EnvKeyLinkedInClientID].(string) != "" && updatedData[constants.EnvKeyLinkedInClientSecret].(string) != ""
|
||||
isUpdatedTwitterLoginEnabled := updatedData[constants.EnvKeyTwitterClientID] != nil && updatedData[constants.EnvKeyTwitterClientSecret] != nil && updatedData[constants.EnvKeyTwitterClientID].(string) != "" && updatedData[constants.EnvKeyTwitterClientSecret].(string) != ""
|
||||
isUpdatedMicrosoftLoginEnabled := updatedData[constants.EnvKeyMicrosoftClientID] != nil && updatedData[constants.EnvKeyMicrosoftClientSecret] != nil && updatedData[constants.EnvKeyMicrosoftActiveDirectoryTenantID] != nil && updatedData[constants.EnvKeyMicrosoftClientID].(string) != "" && updatedData[constants.EnvKeyMicrosoftClientSecret].(string) != "" && updatedData[constants.EnvKeyMicrosoftActiveDirectoryTenantID].(string) != ""
|
||||
isUpdatedMicrosoftLoginEnabled := updatedData[constants.EnvKeyMicrosoftClientID] != nil && updatedData[constants.EnvKeyMicrosoftClientSecret] != nil && updatedData[constants.EnvKeyMicrosoftClientID].(string) != "" && updatedData[constants.EnvKeyMicrosoftClientSecret].(string) != ""
|
||||
|
||||
if isCurrentBasicAuthEnabled && !isUpdatedBasicAuthEnabled {
|
||||
memorystore.Provider.DeleteSessionForNamespace(constants.AuthRecipeMethodBasicAuth)
|
||||
@@ -267,6 +267,13 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
|
||||
updatedData[constants.EnvKeyIsEmailServiceEnabled] = true
|
||||
}
|
||||
|
||||
if updatedData[constants.EnvKeyTwilioAPIKey] == "" || updatedData[constants.EnvKeyTwilioAPISecret] == "" || updatedData[constants.EnvKeyTwilioAccountSID] == "" || updatedData[constants.EnvKeyTwilioSender] == "" {
|
||||
updatedData[constants.EnvKeyIsSMSServiceEnabled] = false
|
||||
if !updatedData[constants.EnvKeyIsSMSServiceEnabled].(bool) {
|
||||
updatedData[constants.EnvKeyDisablePhoneVerification] = true
|
||||
}
|
||||
}
|
||||
|
||||
if !currentData[constants.EnvKeyEnforceMultiFactorAuthentication].(bool) && updatedData[constants.EnvKeyEnforceMultiFactorAuthentication].(bool) && !updatedData[constants.EnvKeyDisableMultiFactorAuthentication].(bool) {
|
||||
go db.Provider.UpdateUsers(ctx, map[string]interface{}{
|
||||
"is_multi_factor_auth_enabled": true,
|
||||
|
@@ -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)
|
||||
@@ -242,7 +251,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
||||
log.Debug("Failed to create verification token: ", err)
|
||||
return res, err
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, &models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: verificationType,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
@@ -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) {
|
||||
@@ -147,7 +159,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
||||
if err != nil {
|
||||
log.Debug("Failed to create verification token: ", err)
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, &models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: verificationType,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
@@ -41,7 +41,7 @@ func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookReques
|
||||
}
|
||||
headersString = string(headerBytes)
|
||||
}
|
||||
webhookDetails := models.Webhook{
|
||||
webhookDetails := &models.Webhook{
|
||||
ID: webhook.ID,
|
||||
Key: webhook.ID,
|
||||
EventName: refs.StringValue(webhook.EventName),
|
||||
|
61
server/resolvers/validate_session.go
Normal file
61
server/resolvers/validate_session.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/cookie"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ValidateSessionResolver is used to validate a cookie session without its rotation
|
||||
func ValidateSessionResolver(ctx context.Context, params *model.ValidateSessionInput) (*model.ValidateSessionResponse, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get GinContext: ", err)
|
||||
return nil, err
|
||||
}
|
||||
sessionToken := params.Cookie
|
||||
if sessionToken == "" {
|
||||
sessionToken, err = cookie.GetSession(gc)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get session token: ", err)
|
||||
return nil, errors.New("unauthorized")
|
||||
}
|
||||
}
|
||||
claims, err := token.ValidateBrowserSession(gc, sessionToken)
|
||||
if err != nil {
|
||||
log.Debug("Failed to validate session token", err)
|
||||
return nil, errors.New("unauthorized")
|
||||
}
|
||||
userID := claims.Subject
|
||||
log := log.WithFields(log.Fields{
|
||||
"user_id": userID,
|
||||
})
|
||||
user, err := db.Provider.GetUserByID(ctx, userID)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user: ", err)
|
||||
return nil, err
|
||||
}
|
||||
// refresh token has "roles" as claim
|
||||
claimRoleInterface := claims.Roles
|
||||
claimRoles := []string{}
|
||||
claimRoles = append(claimRoles, claimRoleInterface...)
|
||||
if params != nil && params.Roles != nil && len(params.Roles) > 0 {
|
||||
for _, v := range params.Roles {
|
||||
if !utils.StringSliceContains(claimRoles, v) {
|
||||
log.Debug("User does not have required role: ", claimRoles, v)
|
||||
return nil, fmt.Errorf(`unauthorized`)
|
||||
}
|
||||
}
|
||||
}
|
||||
return &model.ValidateSessionResponse{
|
||||
IsValid: true,
|
||||
User: user.AsAPIUser(),
|
||||
}, nil
|
||||
}
|
@@ -27,7 +27,6 @@ func VerificationRequestsResolver(ctx context.Context, params *model.PaginatedIn
|
||||
}
|
||||
|
||||
pagination := utils.GetPagination(params)
|
||||
|
||||
res, err := db.Provider.ListVerificationRequests(ctx, pagination)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get verification requests: ", err)
|
||||
|
@@ -125,11 +125,13 @@ 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)
|
||||
}
|
||||
|
||||
db.Provider.AddSession(ctx, models.Session{
|
||||
db.Provider.AddSession(ctx, &models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
|
@@ -1,62 +0,0 @@
|
||||
package resolvers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func VerifyMobileResolver(ctx context.Context, params model.VerifyMobileRequest) (*model.AuthResponse, error) {
|
||||
var res *model.AuthResponse
|
||||
|
||||
_, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get GinContext: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
smsVerificationRequest, err := db.Provider.GetCodeByPhone(ctx, params.PhoneNumber)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get sms request by phone: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
if smsVerificationRequest.Code != params.Code {
|
||||
log.Debug("Failed to verify request: bad credentials")
|
||||
return res, fmt.Errorf(`bad credentials`)
|
||||
}
|
||||
|
||||
expiresIn := smsVerificationRequest.CodeExpiresAt - time.Now().Unix()
|
||||
if expiresIn < 0 {
|
||||
log.Debug("Failed to verify sms request: Timeout")
|
||||
return res, fmt.Errorf("time expired")
|
||||
}
|
||||
|
||||
res = &model.AuthResponse{
|
||||
Message: "successful",
|
||||
}
|
||||
|
||||
user, err := db.Provider.GetUserByPhoneNumber(ctx, params.PhoneNumber)
|
||||
if user.PhoneNumberVerifiedAt == nil {
|
||||
now := time.Now().Unix()
|
||||
user.PhoneNumberVerifiedAt = &now
|
||||
}
|
||||
|
||||
_, err = db.Provider.UpdateUser(ctx, *user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update user: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = db.Provider.DeleteSMSRequest(ctx, smsVerificationRequest)
|
||||
if err != nil {
|
||||
log.Debug("Failed to delete sms request: ", err.Error())
|
||||
}
|
||||
|
||||
return res, err
|
||||
}
|
@@ -28,35 +28,62 @@ func VerifyOtpResolver(ctx context.Context, params model.VerifyOTPRequest) (*mod
|
||||
return res, err
|
||||
}
|
||||
|
||||
otp, err := db.Provider.GetOTPByEmail(ctx, params.Email)
|
||||
mfaSession, err := cookie.GetMfaSession(gc)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get otp request by email: ", err)
|
||||
return res, fmt.Errorf(`invalid email: %s`, err.Error())
|
||||
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`)
|
||||
}
|
||||
|
||||
currentField := models.FieldNameEmail
|
||||
if refs.StringValue(params.Email) == "" {
|
||||
currentField = models.FieldNamePhoneNumber
|
||||
}
|
||||
var otp *models.OTP
|
||||
if currentField == models.FieldNameEmail {
|
||||
otp, err = db.Provider.GetOTPByEmail(ctx, refs.StringValue(params.Email))
|
||||
} else {
|
||||
otp, err = db.Provider.GetOTPByPhoneNumber(ctx, refs.StringValue(params.PhoneNumber))
|
||||
}
|
||||
if otp == nil && err != nil {
|
||||
log.Debugf("Failed to get otp request for %s: %s", currentField, err.Error())
|
||||
return res, fmt.Errorf(`invalid %s: %s`, currentField, err.Error())
|
||||
}
|
||||
if params.Otp != otp.Otp {
|
||||
log.Debug("Failed to verify otp request: Incorrect value")
|
||||
return res, fmt.Errorf(`invalid otp`)
|
||||
}
|
||||
|
||||
expiresIn := otp.ExpiresAt - time.Now().Unix()
|
||||
|
||||
if expiresIn < 0 {
|
||||
log.Debug("Failed to verify otp request: Timeout")
|
||||
return res, fmt.Errorf("otp expired")
|
||||
}
|
||||
|
||||
user, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by email: ", err)
|
||||
var user *models.User
|
||||
if currentField == models.FieldNameEmail {
|
||||
user, err = db.Provider.GetUserByEmail(ctx, refs.StringValue(params.Email))
|
||||
} else {
|
||||
user, err = db.Provider.GetUserByPhoneNumber(ctx, refs.StringValue(params.PhoneNumber))
|
||||
}
|
||||
if user == nil || err != nil {
|
||||
log.Debug("Failed to get user by email or phone number: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
isSignUp := user.EmailVerifiedAt == nil
|
||||
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
|
||||
|
||||
if currentField == models.FieldNamePhoneNumber {
|
||||
loginMethod = constants.AuthRecipeMethodMobileOTP
|
||||
}
|
||||
roles := strings.Split(user.Roles, ",")
|
||||
scope := []string{"openid", "email", "profile"}
|
||||
code := ""
|
||||
@@ -97,11 +124,13 @@ 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)
|
||||
}
|
||||
|
||||
db.Provider.AddSession(ctx, models.Session{
|
||||
db.Provider.AddSession(ctx, &models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
|
@@ -25,7 +25,7 @@ func WebhookLogsResolver(ctx context.Context, params *model.ListWebhookLogReques
|
||||
return nil, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
var pagination model.Pagination
|
||||
var pagination *model.Pagination
|
||||
var webhookID string
|
||||
|
||||
if params != nil {
|
||||
@@ -37,7 +37,7 @@ func WebhookLogsResolver(ctx context.Context, params *model.ListWebhookLogReques
|
||||
pagination = utils.GetPagination(nil)
|
||||
webhookID = ""
|
||||
}
|
||||
|
||||
// TODO fix
|
||||
webhookLogs, err := db.Provider.ListWebhookLogs(ctx, pagination, webhookID)
|
||||
if err != nil {
|
||||
log.Debug("failed to get webhook logs: ", err)
|
||||
|
@@ -25,7 +25,6 @@ func WebhooksResolver(ctx context.Context, params *model.PaginatedInput) (*model
|
||||
}
|
||||
|
||||
pagination := utils.GetPagination(params)
|
||||
|
||||
webhooks, err := db.Provider.ListWebhook(ctx, pagination)
|
||||
if err != nil {
|
||||
log.Debug("failed to get webhooks: ", err)
|
||||
|
Reference in New Issue
Block a user