feat: add loggging to all resolvers

This commit is contained in:
Lakhan Samani 2022-05-24 12:42:29 +05:30
parent f5515bec28
commit d7bb10fd21
27 changed files with 350 additions and 68 deletions

View File

@ -3,12 +3,13 @@ package oauth
import ( import (
"context" "context"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/coreos/go-oidc/v3/oidc" "github.com/coreos/go-oidc/v3/oidc"
"golang.org/x/oauth2" "golang.org/x/oauth2"
facebookOAuth2 "golang.org/x/oauth2/facebook" facebookOAuth2 "golang.org/x/oauth2/facebook"
githubOAuth2 "golang.org/x/oauth2/github" githubOAuth2 "golang.org/x/oauth2/github"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore"
) )
// OAuthProviders is a struct that contains reference all the OAuth providers // OAuthProviders is a struct that contains reference all the OAuth providers

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto" "github.com/authorizerdev/authorizer/server/crypto"
@ -14,15 +16,17 @@ import (
// AdminLoginResolver is a resolver for admin login mutation // AdminLoginResolver is a resolver for admin login mutation
func AdminLoginResolver(ctx context.Context, params model.AdminLoginInput) (*model.Response, error) { func AdminLoginResolver(ctx context.Context, params model.AdminLoginInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
adminSecret := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) adminSecret := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
if params.AdminSecret != adminSecret { if params.AdminSecret != adminSecret {
log.Debug("Admin secret is not correct")
return res, fmt.Errorf(`invalid admin secret`) return res, fmt.Errorf(`invalid admin secret`)
} }

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/token"
@ -12,14 +14,16 @@ import (
// AdminLogoutResolver is a resolver for admin logout mutation // AdminLogoutResolver is a resolver for admin logout mutation
func AdminLogoutResolver(ctx context.Context) (*model.Response, error) { func AdminLogoutResolver(ctx context.Context) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Admin is not logged in")
return res, fmt.Errorf("unauthorized") return res, fmt.Errorf("unauthorized")
} }

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto" "github.com/authorizerdev/authorizer/server/crypto"
@ -15,19 +17,22 @@ import (
// AdminSessionResolver is a resolver for admin session query // AdminSessionResolver is a resolver for admin session query
func AdminSessionResolver(ctx context.Context) (*model.Response, error) { func AdminSessionResolver(ctx context.Context) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return res, fmt.Errorf("unauthorized") return res, fmt.Errorf("unauthorized")
} }
hashedKey, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)) hashedKey, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
if err != nil { if err != nil {
log.Debug("Failed to encrypt key:", err)
return res, err return res, err
} }
cookie.SetAdminCookie(gc, hashedKey) cookie.SetAdminCookie(gc, hashedKey)

View File

@ -6,6 +6,8 @@ import (
"fmt" "fmt"
"strings" "strings"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto" "github.com/authorizerdev/authorizer/server/crypto"
@ -17,19 +19,22 @@ import (
// AdminSignupResolver is a resolver for admin signup mutation // AdminSignupResolver is a resolver for admin signup mutation
func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*model.Response, error) { func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext:", err)
return res, err return res, err
} }
if strings.TrimSpace(params.AdminSecret) == "" { if strings.TrimSpace(params.AdminSecret) == "" {
log.Debug("Admin secret is empty")
err = fmt.Errorf("please select secure admin secret") err = fmt.Errorf("please select secure admin secret")
return res, err return res, err
} }
if len(params.AdminSecret) < 6 { if len(params.AdminSecret) < 6 {
log.Debug("Admin secret is too short")
err = fmt.Errorf("admin secret must be at least 6 characters") err = fmt.Errorf("admin secret must be at least 6 characters")
return res, err return res, err
} }
@ -37,6 +42,7 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
adminSecret := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) adminSecret := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
if adminSecret != "" { if adminSecret != "" {
log.Debug("Admin secret is already set")
err = fmt.Errorf("admin sign up already completed") err = fmt.Errorf("admin sign up already completed")
return res, err return res, err
} }
@ -47,30 +53,36 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
jsonBytes, err := json.Marshal(envstore.EnvStoreObj.GetEnvStoreClone()) jsonBytes, err := json.Marshal(envstore.EnvStoreObj.GetEnvStoreClone())
if err != nil { if err != nil {
log.Debug("Failed to marshal envstore:", err)
return res, err return res, err
} }
if err := json.Unmarshal(jsonBytes, &storeData); err != nil { if err := json.Unmarshal(jsonBytes, &storeData); err != nil {
log.Debug("Failed to unmarshal envstore:", err)
return res, err return res, err
} }
env, err := db.Provider.GetEnv() env, err := db.Provider.GetEnv()
if err != nil { if err != nil {
log.Debug("Failed to get env:", err)
return res, err return res, err
} }
envData, err := crypto.EncryptEnvData(storeData) envData, err := crypto.EncryptEnvData(storeData)
if err != nil { if err != nil {
log.Debug("Failed to encrypt envstore:", err)
return res, err return res, err
} }
env.EnvData = envData env.EnvData = envData
if _, err := db.Provider.UpdateEnv(env); err != nil { if _, err := db.Provider.UpdateEnv(env); err != nil {
log.Debug("Failed to update env:", err)
return res, err return res, err
} }
hashedKey, err := crypto.EncryptPassword(params.AdminSecret) hashedKey, err := crypto.EncryptPassword(params.AdminSecret)
if err != nil { if err != nil {
log.Debug("Failed to encrypt admin session key:", err)
return res, err return res, err
} }
cookie.SetAdminCookie(gc, hashedKey) cookie.SetAdminCookie(gc, hashedKey)

View File

@ -15,18 +15,26 @@ import (
// DeleteUserResolver is a resolver for delete user mutation // DeleteUserResolver is a resolver for delete user mutation
func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*model.Response, error) { func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return res, fmt.Errorf("unauthorized") return res, fmt.Errorf("unauthorized")
} }
log := log.WithFields(log.Fields{
"email": params.Email,
})
user, err := db.Provider.GetUserByEmail(params.Email) user, err := db.Provider.GetUserByEmail(params.Email)
if err != nil { if err != nil {
log.Debug("Failed to get user from DB:", err)
return res, err return res, err
} }
@ -34,7 +42,7 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod
err = db.Provider.DeleteUser(user) err = db.Provider.DeleteUser(user)
if err != nil { if err != nil {
log.Debug("Failed Deleting User:", err) log.Debug("Failed to delete user:", err)
return res, err return res, err
} }

View File

@ -3,7 +3,8 @@ package resolvers
import ( import (
"context" "context"
"fmt" "fmt"
"log"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
@ -13,18 +14,26 @@ import (
// EnableAccessResolver is a resolver for enabling user access // EnableAccessResolver is a resolver for enabling user access
func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) (*model.Response, error) { func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return res, fmt.Errorf("unauthorized") return res, fmt.Errorf("unauthorized")
} }
log := log.WithFields(log.Fields{
"user_id": params.UserID,
})
user, err := db.Provider.GetUserByID(params.UserID) user, err := db.Provider.GetUserByID(params.UserID)
if err != nil { if err != nil {
log.Debug("Failed to get user from DB:", err)
return res, err return res, err
} }
@ -32,7 +41,7 @@ func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) (
user, err = db.Provider.UpdateUser(user) user, err = db.Provider.UpdateUser(user)
if err != nil { if err != nil {
log.Println("error updating user:", err) log.Debug("Failed to update user:", err)
return res, err return res, err
} }

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore" "github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
@ -14,14 +16,16 @@ import (
// EnvResolver is a resolver for config query // EnvResolver is a resolver for config query
// This is admin only query // This is admin only query
func EnvResolver(ctx context.Context) (*model.Env, error) { func EnvResolver(ctx context.Context) (*model.Env, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Env var res *model.Env
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return res, fmt.Errorf("unauthorized") return res, fmt.Errorf("unauthorized")
} }

View File

@ -3,10 +3,11 @@ package resolvers
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
@ -19,20 +20,28 @@ import (
// ForgotPasswordResolver is a resolver for forgot password mutation // ForgotPasswordResolver is a resolver for forgot password mutation
func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInput) (*model.Response, error) { func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) { if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
log.Debug("Basic authentication is disabled.")
return res, fmt.Errorf(`basic authentication is disabled for this instance`) return res, fmt.Errorf(`basic authentication is disabled for this instance`)
} }
params.Email = strings.ToLower(params.Email) params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) { if !utils.IsValidEmail(params.Email) {
log.Debug("Invalid email address.")
return res, fmt.Errorf("invalid email") return res, fmt.Errorf("invalid email")
} }
log := log.WithFields(log.Fields{
"email": params.Email,
})
_, err = db.Provider.GetUserByEmail(params.Email) _, err = db.Provider.GetUserByEmail(params.Email)
if err != nil { if err != nil {
return res, fmt.Errorf(`user with this email not found`) return res, fmt.Errorf(`user with this email not found`)

View File

@ -10,16 +10,19 @@ import (
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils" "github.com/authorizerdev/authorizer/server/utils"
log "github.com/sirupsen/logrus"
) )
// GenerateJWTKeysResolver mutation to generate new jwt keys // GenerateJWTKeysResolver mutation to generate new jwt keys
func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysInput) (*model.GenerateJWTKeysResponse, error) { func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysInput) (*model.GenerateJWTKeysResponse, error) {
gc, err := utils.GinContextFromContext(ctx) gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return nil, err return nil, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return nil, fmt.Errorf("unauthorized") return nil, fmt.Errorf("unauthorized")
} }
@ -27,6 +30,7 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
if crypto.IsHMACA(params.Type) { if crypto.IsHMACA(params.Type) {
secret, _, err := crypto.NewHMACKey(params.Type, clientID) secret, _, err := crypto.NewHMACKey(params.Type, clientID)
if err != nil { if err != nil {
log.Debug("Failed to generate new HMAC key:", err)
return nil, err return nil, err
} }
return &model.GenerateJWTKeysResponse{ return &model.GenerateJWTKeysResponse{
@ -37,6 +41,7 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
if crypto.IsRSA(params.Type) { if crypto.IsRSA(params.Type) {
_, privateKey, publicKey, _, err := crypto.NewRSAKey(params.Type, clientID) _, privateKey, publicKey, _, err := crypto.NewRSAKey(params.Type, clientID)
if err != nil { if err != nil {
log.Debug("Failed to generate new RSA key:", err)
return nil, err return nil, err
} }
return &model.GenerateJWTKeysResponse{ return &model.GenerateJWTKeysResponse{
@ -48,6 +53,7 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
if crypto.IsECDSA(params.Type) { if crypto.IsECDSA(params.Type) {
_, privateKey, publicKey, _, err := crypto.NewECDSAKey(params.Type, clientID) _, privateKey, publicKey, _, err := crypto.NewECDSAKey(params.Type, clientID)
if err != nil { if err != nil {
log.Debug("Failed to generate new ECDSA key:", err)
return nil, err return nil, err
} }
return &model.GenerateJWTKeysResponse{ return &model.GenerateJWTKeysResponse{
@ -56,5 +62,6 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
}, nil }, nil
} }
log.Debug("Invalid algorithm:", params.Type)
return nil, fmt.Errorf("invalid algorithm") return nil, fmt.Errorf("invalid algorithm")
} }

View File

@ -4,10 +4,11 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"log"
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
@ -22,19 +23,23 @@ import (
func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput) (*model.Response, error) { func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx) gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return nil, err return nil, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return nil, errors.New("unauthorized") return nil, errors.New("unauthorized")
} }
// this feature is only allowed if email server is configured // this feature is only allowed if email server is configured
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) { if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
log.Debug("Email server is not configured.")
return nil, errors.New("email sending is disabled") return nil, errors.New("email sending is disabled")
} }
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) && envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) { if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) && envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) {
log.Debug("Basic authentication and Magic link login is disabled.")
return nil, errors.New("either basic authentication or magic link login is required") return nil, errors.New("either basic authentication or magic link login is required")
} }
@ -47,6 +52,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
} }
if len(emails) == 0 { if len(emails) == 0 {
log.Debug("No valid email addresses.")
return nil, errors.New("no valid emails found") return nil, errors.New("no valid emails found")
} }
@ -56,14 +62,15 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
for _, email := range emails { for _, email := range emails {
_, err := db.Provider.GetUserByEmail(email) _, err := db.Provider.GetUserByEmail(email)
if err != nil { if err != nil {
log.Printf("%s user not found. inviting user.", email) log.Info("User with this email not found, so inviting...")
newEmails = append(newEmails, email) newEmails = append(newEmails, email)
} else { } else {
log.Println("%s user already exists. skipping.", email) log.Info("User with this email already exists, so not inviting...")
} }
} }
if len(newEmails) == 0 { if len(newEmails) == 0 {
log.Debug("No new emails found.")
return nil, errors.New("all emails already exist") return nil, errors.New("all emails already exist")
} }
@ -90,7 +97,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
verificationToken, err := token.CreateVerificationToken(email, constants.VerificationTypeForgotPassword, hostname, nonceHash, redirectURL) verificationToken, err := token.CreateVerificationToken(email, constants.VerificationTypeForgotPassword, hostname, nonceHash, redirectURL)
if err != nil { if err != nil {
log.Println(`error generating token`, err) log.Debug("Failed to create verification token.", err)
} }
verificationRequest := models.VerificationRequest{ verificationRequest := models.VerificationRequest{
@ -116,13 +123,13 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
user, err = db.Provider.AddUser(user) user, err = db.Provider.AddUser(user)
if err != nil { if err != nil {
log.Printf("error inviting user: %s, err: %v", email, err) log.Debug("Error adding user: %s, err: %v", email, err)
return nil, err return nil, err
} }
_, err = db.Provider.AddVerificationRequest(verificationRequest) _, err = db.Provider.AddVerificationRequest(verificationRequest)
if err != nil { if err != nil {
log.Printf("error inviting user: %s, err: %v", email, err) log.Debug("Error adding verification request: %s, err: %v", email, err)
return nil, err return nil, err
} }

View File

@ -3,10 +3,12 @@ package resolvers
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/bcrypt"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
@ -16,49 +18,59 @@ import (
"github.com/authorizerdev/authorizer/server/sessionstore" "github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils" "github.com/authorizerdev/authorizer/server/utils"
"golang.org/x/crypto/bcrypt"
) )
// LoginResolver is a resolver for login mutation // LoginResolver is a resolver for login mutation
func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthResponse, error) { func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthResponse, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.AuthResponse var res *model.AuthResponse
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) { if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
log.Debug("Basic authentication is disabled.")
return res, fmt.Errorf(`basic authentication is disabled for this instance`) return res, fmt.Errorf(`basic authentication is disabled for this instance`)
} }
log := log.WithFields(log.Fields{
"email": params.Email,
})
params.Email = strings.ToLower(params.Email) params.Email = strings.ToLower(params.Email)
user, err := db.Provider.GetUserByEmail(params.Email) user, err := db.Provider.GetUserByEmail(params.Email)
if err != nil { if err != nil {
log.Debug("Failed to get user by email", err)
return res, fmt.Errorf(`user with this email not found`) return res, fmt.Errorf(`user with this email not found`)
} }
if user.RevokedTimestamp != nil { if user.RevokedTimestamp != nil {
log.Debug("User access is revoked")
return res, fmt.Errorf(`user access has been revoked`) return res, fmt.Errorf(`user access has been revoked`)
} }
if !strings.Contains(user.SignupMethods, constants.SignupMethodBasicAuth) { if !strings.Contains(user.SignupMethods, constants.SignupMethodBasicAuth) {
log.Debug("User signup method is not basic auth")
return res, fmt.Errorf(`user has not signed up email & password`) return res, fmt.Errorf(`user has not signed up email & password`)
} }
if user.EmailVerifiedAt == nil { if user.EmailVerifiedAt == nil {
log.Debug("User email is not verified")
return res, fmt.Errorf(`email not verified`) return res, fmt.Errorf(`email not verified`)
} }
err = bcrypt.CompareHashAndPassword([]byte(*user.Password), []byte(params.Password)) err = bcrypt.CompareHashAndPassword([]byte(*user.Password), []byte(params.Password))
if err != nil { if err != nil {
log.Println("compare password error:", err) log.Debug("Failed to compare password", err)
return res, fmt.Errorf(`invalid password`) return res, fmt.Errorf(`invalid password`)
} }
roles := envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles) roles := envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles)
currentRoles := strings.Split(user.Roles, ",") currentRoles := strings.Split(user.Roles, ",")
if len(params.Roles) > 0 { if len(params.Roles) > 0 {
if !utils.IsValidRoles(params.Roles, currentRoles) { if !utils.IsValidRoles(params.Roles, currentRoles) {
log.Debug("Invalid roles")
return res, fmt.Errorf(`invalid roles`) return res, fmt.Errorf(`invalid roles`)
} }
@ -72,6 +84,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
authToken, err := token.CreateAuthToken(gc, user, roles, scope) authToken, err := token.CreateAuthToken(gc, user, roles, scope)
if err != nil { if err != nil {
log.Debug("Failed to create auth token", err)
return res, err return res, err
} }

View File

@ -3,6 +3,8 @@ package resolvers
import ( import (
"context" "context"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto" "github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
@ -12,20 +14,24 @@ import (
// LogoutResolver is a resolver for logout mutation // LogoutResolver is a resolver for logout mutation
func LogoutResolver(ctx context.Context) (*model.Response, error) { func LogoutResolver(ctx context.Context) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
// get fingerprint hash // get fingerprint hash
fingerprintHash, err := cookie.GetSession(gc) fingerprintHash, err := cookie.GetSession(gc)
if err != nil { if err != nil {
log.Debug("Failed to get fingerprint hash:", err)
return res, err return res, err
} }
decryptedFingerPrint, err := crypto.DecryptAES(fingerprintHash) decryptedFingerPrint, err := crypto.DecryptAES(fingerprintHash)
if err != nil { if err != nil {
log.Debug("Failed to decrypt fingerprint hash:", err)
return res, err return res, err
} }

View File

@ -3,10 +3,11 @@ package resolvers
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
@ -20,21 +21,29 @@ import (
// MagicLinkLoginResolver is a resolver for magic link login mutation // MagicLinkLoginResolver is a resolver for magic link login mutation
func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) { func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) {
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx) gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) { if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) {
log.Debug("Magic link login is disabled.")
return res, fmt.Errorf(`magic link login is disabled for this instance`) return res, fmt.Errorf(`magic link login is disabled for this instance`)
} }
params.Email = strings.ToLower(params.Email) params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) { if !utils.IsValidEmail(params.Email) {
log.Debug("Invalid email")
return res, fmt.Errorf(`invalid email address`) return res, fmt.Errorf(`invalid email address`)
} }
log := log.WithFields(log.Fields{
"email": params.Email,
})
inputRoles := []string{} inputRoles := []string{}
user := models.User{ user := models.User{
@ -45,6 +54,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
existingUser, err := db.Provider.GetUserByEmail(params.Email) existingUser, err := db.Provider.GetUserByEmail(params.Email)
if err != nil { if err != nil {
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) { if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) {
log.Debug("Signup is disabled.")
return res, fmt.Errorf(`signup is disabled for this instance`) return res, fmt.Errorf(`signup is disabled for this instance`)
} }
@ -53,6 +63,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
if len(params.Roles) > 0 { if len(params.Roles) > 0 {
// check if roles exists // check if roles exists
if !utils.IsValidRoles(params.Roles, envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles)) { if !utils.IsValidRoles(params.Roles, envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles)) {
log.Debug("Invalid roles")
return res, fmt.Errorf(`invalid roles`) return res, fmt.Errorf(`invalid roles`)
} else { } else {
inputRoles = params.Roles inputRoles = params.Roles
@ -71,6 +82,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
// Need to modify roles in this case // Need to modify roles in this case
if user.RevokedTimestamp != nil { if user.RevokedTimestamp != nil {
log.Debug("User access is revoked")
return res, fmt.Errorf(`user access has been revoked`) return res, fmt.Errorf(`user access has been revoked`)
} }
@ -96,6 +108,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
} }
if hasProtectedRole { if hasProtectedRole {
log.Debug("User is not assigned one of the protected roles", unasignedRoles)
return res, fmt.Errorf(`invalid roles`) return res, fmt.Errorf(`invalid roles`)
} else { } else {
user.Roles = existingUser.Roles + "," + strings.Join(unasignedRoles, ",") user.Roles = existingUser.Roles + "," + strings.Join(unasignedRoles, ",")
@ -112,7 +125,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
user.SignupMethods = signupMethod user.SignupMethods = signupMethod
user, _ = db.Provider.UpdateUser(user) user, _ = db.Provider.UpdateUser(user)
if err != nil { if err != nil {
log.Println("error updating user:", err) log.Debug("Failed to update user", err)
} }
} }
@ -121,6 +134,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
// insert verification request // insert verification request
_, nonceHash, err := utils.GenerateNonce() _, nonceHash, err := utils.GenerateNonce()
if err != nil { if err != nil {
log.Debug("Failed to generate nonce", err)
return res, err return res, err
} }
redirectURLParams := "&roles=" + strings.Join(inputRoles, ",") redirectURLParams := "&roles=" + strings.Join(inputRoles, ",")
@ -144,7 +158,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
verificationType := constants.VerificationTypeMagicLinkLogin verificationType := constants.VerificationTypeMagicLinkLogin
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname, nonceHash, redirectURL) verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname, nonceHash, redirectURL)
if err != nil { if err != nil {
log.Println(`error generating token`, err) log.Debug("Failed to create verification token", err)
} }
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{ _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
Token: verificationToken, Token: verificationToken,
@ -155,6 +169,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
RedirectURI: redirectURL, RedirectURI: redirectURL,
}) })
if err != nil { if err != nil {
log.Debug("Failed to add verification request in db:", err)
return res, err return res, err
} }

View File

@ -3,6 +3,8 @@ package resolvers
import ( import (
"context" "context"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/token"
@ -11,25 +13,34 @@ import (
// ProfileResolver is a resolver for profile query // ProfileResolver is a resolver for profile query
func ProfileResolver(ctx context.Context) (*model.User, error) { func ProfileResolver(ctx context.Context) (*model.User, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.User var res *model.User
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
accessToken, err := token.GetAccessToken(gc) accessToken, err := token.GetAccessToken(gc)
if err != nil { if err != nil {
log.Debug("Failed to get access token:", err)
return res, err return res, err
} }
claims, err := token.ValidateAccessToken(gc, accessToken) claims, err := token.ValidateAccessToken(gc, accessToken)
if err != nil { if err != nil {
log.Debug("Failed to validate access token:", err)
return res, err return res, err
} }
userID := claims["sub"].(string) userID := claims["sub"].(string)
log := log.WithFields(log.Fields{
"user_id": userID,
})
user, err := db.Provider.GetUserByID(userID) user, err := db.Provider.GetUserByID(userID)
if err != nil { if err != nil {
log.Debug("Failed to get user:", err)
return res, err return res, err
} }

View File

@ -3,10 +3,11 @@ package resolvers
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/email" "github.com/authorizerdev/authorizer/server/email"
@ -18,42 +19,48 @@ import (
// ResendVerifyEmailResolver is a resolver for resend verify email mutation // ResendVerifyEmailResolver is a resolver for resend verify email mutation
func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEmailInput) (*model.Response, error) { func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEmailInput) (*model.Response, error) {
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx) gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
params.Email = strings.ToLower(params.Email) params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) { if !utils.IsValidEmail(params.Email) {
log.Debug("Invalid email", params.Email)
return res, fmt.Errorf("invalid email") return res, fmt.Errorf("invalid email")
} }
if !utils.IsValidVerificationIdentifier(params.Identifier) { if !utils.IsValidVerificationIdentifier(params.Identifier) {
log.Debug("Invalid verification identifier", params.Identifier)
return res, fmt.Errorf("invalid identifier") return res, fmt.Errorf("invalid identifier")
} }
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(params.Email, params.Identifier) verificationRequest, err := db.Provider.GetVerificationRequestByEmail(params.Email, params.Identifier)
if err != nil { if err != nil {
log.Debug("Failed to get verification request", err)
return res, fmt.Errorf(`verification request not found`) return res, fmt.Errorf(`verification request not found`)
} }
// delete current verification and create new one // delete current verification and create new one
err = db.Provider.DeleteVerificationRequest(verificationRequest) err = db.Provider.DeleteVerificationRequest(verificationRequest)
if err != nil { if err != nil {
log.Println("error deleting verification request:", err) log.Debug("Failed to delete verification request", err)
} }
hostname := utils.GetHost(gc) hostname := utils.GetHost(gc)
_, nonceHash, err := utils.GenerateNonce() _, nonceHash, err := utils.GenerateNonce()
if err != nil { if err != nil {
log.Debug("Failed to generate nonce", err)
return res, err return res, err
} }
verificationToken, err := token.CreateVerificationToken(params.Email, params.Identifier, hostname, nonceHash, verificationRequest.RedirectURI) verificationToken, err := token.CreateVerificationToken(params.Email, params.Identifier, hostname, nonceHash, verificationRequest.RedirectURI)
if err != nil { if err != nil {
log.Println(`error generating token`, err) log.Debug("Failed to create verification token", err)
} }
db.Provider.AddVerificationRequest(models.VerificationRequest{ _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
Token: verificationToken, Token: verificationToken,
Identifier: params.Identifier, Identifier: params.Identifier,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
@ -61,6 +68,9 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
Nonce: nonceHash, Nonce: nonceHash,
RedirectURI: verificationRequest.RedirectURI, RedirectURI: verificationRequest.RedirectURI,
}) })
if err != nil {
log.Debug("Failed to add verification request", err)
}
// exec it as go routin so that we can reduce the api latency // exec it as go routin so that we can reduce the api latency
go email.SendVerificationMail(params.Email, verificationToken, hostname) go email.SendVerificationMail(params.Email, verificationToken, hostname)

View File

@ -6,6 +6,8 @@ import (
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/crypto" "github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
@ -18,24 +20,30 @@ import (
// ResetPasswordResolver is a resolver for reset password mutation // ResetPasswordResolver is a resolver for reset password mutation
func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) { func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx) gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) { if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
log.Debug("Basic authentication is disabled")
return res, fmt.Errorf(`basic authentication is disabled for this instance`) return res, fmt.Errorf(`basic authentication is disabled for this instance`)
} }
verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token) verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token)
if err != nil { if err != nil {
log.Debug("Failed to get verification request", err)
return res, fmt.Errorf(`invalid token`) return res, fmt.Errorf(`invalid token`)
} }
if params.Password != params.ConfirmPassword { if params.Password != params.ConfirmPassword {
log.Debug("Passwords do not match")
return res, fmt.Errorf(`passwords don't match`) return res, fmt.Errorf(`passwords don't match`)
} }
if !utils.IsValidPassword(params.Password) { if !utils.IsValidPassword(params.Password) {
log.Debug("Invalid password")
return res, fmt.Errorf(`password is not valid. It needs to be at least 6 characters long and contain at least one number, one uppercase letter, one lowercase letter and one special character`) return res, fmt.Errorf(`password is not valid. It needs to be at least 6 characters long and contain at least one number, one uppercase letter, one lowercase letter and one special character`)
} }
@ -43,11 +51,17 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
hostname := utils.GetHost(gc) hostname := utils.GetHost(gc)
claim, err := token.ParseJWTToken(params.Token, hostname, verificationRequest.Nonce, verificationRequest.Email) claim, err := token.ParseJWTToken(params.Token, hostname, verificationRequest.Nonce, verificationRequest.Email)
if err != nil { if err != nil {
log.Debug("Failed to parse token", err)
return res, fmt.Errorf(`invalid token`) return res, fmt.Errorf(`invalid token`)
} }
user, err := db.Provider.GetUserByEmail(claim["sub"].(string)) email := claim["sub"].(string)
log := log.WithFields(log.Fields{
"email": email,
})
user, err := db.Provider.GetUserByEmail(email)
if err != nil { if err != nil {
log.Debug("Failed to get user", err)
return res, err return res, err
} }
@ -67,8 +81,17 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
} }
// delete from verification table // delete from verification table
db.Provider.DeleteVerificationRequest(verificationRequest) err = db.Provider.DeleteVerificationRequest(verificationRequest)
db.Provider.UpdateUser(user) if err != nil {
log.Debug("Failed to delete verification request", err)
return res, err
}
_, err = db.Provider.UpdateUser(user)
if err != nil {
log.Debug("Failed to update user", err)
return res, err
}
res = &model.Response{ res = &model.Response{
Message: `Password updated successfully.`, Message: `Password updated successfully.`,

View File

@ -3,9 +3,10 @@ package resolvers
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore" "github.com/authorizerdev/authorizer/server/sessionstore"
@ -15,18 +16,25 @@ import (
// RevokeAccessResolver is a resolver for revoking user access // RevokeAccessResolver is a resolver for revoking user access
func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) (*model.Response, error) { func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return res, fmt.Errorf("unauthorized") return res, fmt.Errorf("unauthorized")
} }
log := log.WithFields(log.Fields{
"user_id": params.UserID,
})
user, err := db.Provider.GetUserByID(params.UserID) user, err := db.Provider.GetUserByID(params.UserID)
if err != nil { if err != nil {
log.Debug("Failed to get user by ID", err)
return res, err return res, err
} }
@ -35,7 +43,7 @@ func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) (
user, err = db.Provider.UpdateUser(user) user, err = db.Provider.UpdateUser(user)
if err != nil { if err != nil {
log.Println("error updating user:", err) log.Debug("Failed to update user", err)
return res, err return res, err
} }

View File

@ -4,9 +4,10 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"log"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
@ -22,22 +23,28 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
gc, err := utils.GinContextFromContext(ctx) gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
sessionToken, err := cookie.GetSession(gc) sessionToken, err := cookie.GetSession(gc)
if err != nil { if err != nil {
log.Println("error getting session token:", err) log.Debug("Failed to get session token", err)
return res, errors.New("unauthorized") return res, errors.New("unauthorized")
} }
// get session from cookie // get session from cookie
claims, err := token.ValidateBrowserSession(gc, sessionToken) claims, err := token.ValidateBrowserSession(gc, sessionToken)
if err != nil { if err != nil {
log.Println("session validation failed:", err) log.Debug("Failed to validate session token", err)
return res, errors.New("unauthorized") return res, errors.New("unauthorized")
} }
userID := claims.Subject userID := claims.Subject
log := log.WithFields(log.Fields{
"user_id": userID,
})
user, err := db.Provider.GetUserByID(userID) user, err := db.Provider.GetUserByID(userID)
if err != nil { if err != nil {
return res, err return res, err
@ -46,13 +53,12 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
// refresh token has "roles" as claim // refresh token has "roles" as claim
claimRoleInterface := claims.Roles claimRoleInterface := claims.Roles
claimRoles := []string{} claimRoles := []string{}
for _, v := range claimRoleInterface { claimRoles = append(claimRoles, claimRoleInterface...)
claimRoles = append(claimRoles, v)
}
if params != nil && params.Roles != nil && len(params.Roles) > 0 { if params != nil && params.Roles != nil && len(params.Roles) > 0 {
for _, v := range params.Roles { for _, v := range params.Roles {
if !utils.StringSliceContains(claimRoles, v) { if !utils.StringSliceContains(claimRoles, v) {
log.Debug("User does not have required role:", claimRoles, v)
return res, fmt.Errorf(`unauthorized`) return res, fmt.Errorf(`unauthorized`)
} }
} }
@ -65,6 +71,7 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
authToken, err := token.CreateAuthToken(gc, user, claimRoles, scope) authToken, err := token.CreateAuthToken(gc, user, claimRoles, scope)
if err != nil { if err != nil {
log.Debug("Failed to create auth token", err)
return res, err return res, err
} }

View File

@ -3,10 +3,11 @@ package resolvers
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto" "github.com/authorizerdev/authorizer/server/crypto"
@ -22,44 +23,56 @@ import (
// SignupResolver is a resolver for signup mutation // SignupResolver is a resolver for signup mutation
func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, error) { func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.AuthResponse var res *model.AuthResponse
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) { if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) {
log.Debug("Signup is disabled.")
return res, fmt.Errorf(`signup is disabled for this instance`) return res, fmt.Errorf(`signup is disabled for this instance`)
} }
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) { if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
log.Debug("Basic authentication is disabled.")
return res, fmt.Errorf(`basic authentication is disabled for this instance`) return res, fmt.Errorf(`basic authentication is disabled for this instance`)
} }
if params.ConfirmPassword != params.Password { if params.ConfirmPassword != params.Password {
log.Debug("Passwords do not match.")
return res, fmt.Errorf(`password and confirm password does not match`) return res, fmt.Errorf(`password and confirm password does not match`)
} }
if !utils.IsValidPassword(params.Password) { if !utils.IsValidPassword(params.Password) {
log.Debug("Invalid password")
return res, fmt.Errorf(`password is not valid. It needs to be at least 6 characters long and contain at least one number, one uppercase letter, one lowercase letter and one special character`) return res, fmt.Errorf(`password is not valid. It needs to be at least 6 characters long and contain at least one number, one uppercase letter, one lowercase letter and one special character`)
} }
params.Email = strings.ToLower(params.Email) params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) { if !utils.IsValidEmail(params.Email) {
log.Debug("Invalid email:", params.Email)
return res, fmt.Errorf(`invalid email address`) return res, fmt.Errorf(`invalid email address`)
} }
log := log.WithFields(log.Fields{
"email": params.Email,
})
// find user with email // find user with email
existingUser, err := db.Provider.GetUserByEmail(params.Email) existingUser, err := db.Provider.GetUserByEmail(params.Email)
if err != nil { if err != nil {
log.Println("user with email " + params.Email + " not found") log.Debug("Failed to get user by email:", err)
} }
if existingUser.EmailVerifiedAt != nil { if existingUser.EmailVerifiedAt != nil {
// email is verified // email is verified
log.Debug("Email is already verified and signed up.")
return res, fmt.Errorf(`%s has already signed up`, params.Email) return res, fmt.Errorf(`%s has already signed up`, params.Email)
} else if existingUser.ID != "" && existingUser.EmailVerifiedAt == nil { } 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) return res, fmt.Errorf("%s has already signed up. please complete the email verification process or reset the password", params.Email)
} }
@ -68,6 +81,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
if len(params.Roles) > 0 { if len(params.Roles) > 0 {
// check if roles exists // check if roles exists
if !utils.IsValidRoles(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), params.Roles) { if !utils.IsValidRoles(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), params.Roles) {
log.Debug("Invalid roles", params.Roles)
return res, fmt.Errorf(`invalid roles`) return res, fmt.Errorf(`invalid roles`)
} else { } else {
inputRoles = params.Roles inputRoles = params.Roles
@ -124,6 +138,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
} }
user, err = db.Provider.AddUser(user) user, err = db.Provider.AddUser(user)
if err != nil { if err != nil {
log.Debug("Failed to add user:", err)
return res, err return res, err
} }
roles := strings.Split(user.Roles, ",") roles := strings.Split(user.Roles, ",")
@ -134,6 +149,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
// insert verification request // insert verification request
_, nonceHash, err := utils.GenerateNonce() _, nonceHash, err := utils.GenerateNonce()
if err != nil { if err != nil {
log.Debug("Failed to generate nonce:", err)
return res, err return res, err
} }
verificationType := constants.VerificationTypeBasicAuthSignup verificationType := constants.VerificationTypeBasicAuthSignup
@ -143,9 +159,10 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
} }
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname, nonceHash, redirectURL) verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname, nonceHash, redirectURL)
if err != nil { if err != nil {
log.Debug("Failed to create verification token:", err)
return res, err return res, err
} }
db.Provider.AddVerificationRequest(models.VerificationRequest{ _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
Token: verificationToken, Token: verificationToken,
Identifier: verificationType, Identifier: verificationType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
@ -153,6 +170,10 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
Nonce: nonceHash, Nonce: nonceHash,
RedirectURI: redirectURL, RedirectURI: redirectURL,
}) })
if err != nil {
log.Debug("Failed to add verification request:", err)
return res, err
}
// exec it as go routin so that we can reduce the api latency // exec it as go routin so that we can reduce the api latency
go email.SendVerificationMail(params.Email, verificationToken, hostname) go email.SendVerificationMail(params.Email, verificationToken, hostname)
@ -169,6 +190,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
authToken, err := token.CreateAuthToken(gc, user, roles, scope) authToken, err := token.CreateAuthToken(gc, user, roles, scope)
if err != nil { if err != nil {
log.Debug("Failed to create auth token:", err)
return res, err return res, err
} }

View File

@ -5,9 +5,10 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"log"
"reflect" "reflect"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto" "github.com/authorizerdev/authorizer/server/crypto"
@ -23,14 +24,16 @@ import (
// UpdateEnvResolver is a resolver for update config mutation // UpdateEnvResolver is a resolver for update config mutation
// This is admin only mutation // This is admin only mutation
func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model.Response, error) { func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return res, fmt.Errorf("unauthorized") return res, fmt.Errorf("unauthorized")
} }
@ -41,6 +44,7 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
if params.JwtType != nil { if params.JwtType != nil {
algo = *params.JwtType algo = *params.JwtType
if !crypto.IsHMACA(algo) && !crypto.IsECDSA(algo) && !crypto.IsRSA(algo) { if !crypto.IsHMACA(algo) && !crypto.IsECDSA(algo) && !crypto.IsRSA(algo) {
log.Debug("Invalid JWT type", algo)
return res, fmt.Errorf("invalid jwt type") return res, fmt.Errorf("invalid jwt type")
} }
@ -60,6 +64,7 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
// check if jwt secret is provided // check if jwt secret is provided
if crypto.IsHMACA(algo) { if crypto.IsHMACA(algo) {
if params.JwtSecret == nil { if params.JwtSecret == nil {
log.Debug("JWT secret is required for HMAC")
return res, fmt.Errorf("jwt secret is required for HMAC algorithm") return res, fmt.Errorf("jwt secret is required for HMAC algorithm")
} }
@ -70,6 +75,7 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
if crypto.IsRSA(algo) { if crypto.IsRSA(algo) {
if params.JwtPrivateKey == nil || params.JwtPublicKey == nil { if params.JwtPrivateKey == nil || params.JwtPublicKey == nil {
log.Debug("JWT private key and public key are required for RSA", params.JwtPrivateKey, params.JwtPublicKey)
return res, fmt.Errorf("jwt private and public key is required for RSA (PKCS1) / ECDSA algorithm") return res, fmt.Errorf("jwt private and public key is required for RSA (PKCS1) / ECDSA algorithm")
} }
@ -77,17 +83,20 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
params.JwtSecret = &defaultSecret params.JwtSecret = &defaultSecret
_, err = crypto.ParseRsaPrivateKeyFromPemStr(*params.JwtPrivateKey) _, err = crypto.ParseRsaPrivateKeyFromPemStr(*params.JwtPrivateKey)
if err != nil { if err != nil {
log.Debug("Invalid JWT private key", err)
return res, err return res, err
} }
_, err := crypto.ParseRsaPublicKeyFromPemStr(*params.JwtPublicKey) _, err := crypto.ParseRsaPublicKeyFromPemStr(*params.JwtPublicKey)
if err != nil { if err != nil {
log.Debug("Invalid JWT public key", err)
return res, err return res, err
} }
} }
if crypto.IsECDSA(algo) { if crypto.IsECDSA(algo) {
if params.JwtPrivateKey == nil || params.JwtPublicKey == nil { if params.JwtPrivateKey == nil || params.JwtPublicKey == nil {
log.Debug("JWT private key and public key are required for ECDSA", params.JwtPrivateKey, params.JwtPublicKey)
return res, fmt.Errorf("jwt private and public key is required for RSA (PKCS1) / ECDSA algorithm") return res, fmt.Errorf("jwt private and public key is required for RSA (PKCS1) / ECDSA algorithm")
} }
@ -95,11 +104,13 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
params.JwtSecret = &defaultSecret params.JwtSecret = &defaultSecret
_, err = crypto.ParseEcdsaPrivateKeyFromPemStr(*params.JwtPrivateKey) _, err = crypto.ParseEcdsaPrivateKeyFromPemStr(*params.JwtPrivateKey)
if err != nil { if err != nil {
log.Debug("Invalid JWT private key", err)
return res, err return res, err
} }
_, err := crypto.ParseEcdsaPublicKeyFromPemStr(*params.JwtPublicKey) _, err := crypto.ParseEcdsaPublicKeyFromPemStr(*params.JwtPublicKey)
if err != nil { if err != nil {
log.Debug("Invalid JWT public key", err)
return res, err return res, err
} }
} }
@ -109,25 +120,30 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
var data map[string]interface{} var data map[string]interface{}
byteData, err := json.Marshal(params) byteData, err := json.Marshal(params)
if err != nil { if err != nil {
log.Debug("Failed to marshal update env input", err)
return res, fmt.Errorf("error marshalling params: %t", err) return res, fmt.Errorf("error marshalling params: %t", err)
} }
err = json.Unmarshal(byteData, &data) err = json.Unmarshal(byteData, &data)
if err != nil { if err != nil {
log.Debug("Failed to unmarshal update env input", err)
return res, fmt.Errorf("error un-marshalling params: %t", err) return res, fmt.Errorf("error un-marshalling params: %t", err)
} }
// in case of admin secret change update the cookie with new hash // in case of admin secret change update the cookie with new hash
if params.AdminSecret != nil { if params.AdminSecret != nil {
if params.OldAdminSecret == nil { if params.OldAdminSecret == nil {
log.Debug("Old admin secret is required for admin secret update")
return res, errors.New("admin secret and old admin secret are required for secret change") return res, errors.New("admin secret and old admin secret are required for secret change")
} }
if *params.OldAdminSecret != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) { if *params.OldAdminSecret != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) {
log.Debug("Old admin secret is invalid")
return res, errors.New("old admin secret is not correct") return res, errors.New("old admin secret is not correct")
} }
if len(*params.AdminSecret) < 6 { if len(*params.AdminSecret) < 6 {
log.Debug("Admin secret is too short")
err = fmt.Errorf("admin secret must be at least 6 characters") err = fmt.Errorf("admin secret must be at least 6 characters")
return res, err return res, err
} }
@ -173,6 +189,7 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
// should be subset of roles // should be subset of roles
for _, role := range params.DefaultRoles { for _, role := range params.DefaultRoles {
if !utils.StringSliceContains(params.Roles, role) { if !utils.StringSliceContains(params.Roles, role) {
log.Debug("Default roles should be subset of roles")
return res, fmt.Errorf("default role %s is not in roles", role) return res, fmt.Errorf("default role %s is not in roles", role)
} }
} }
@ -182,6 +199,7 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
if len(params.ProtectedRoles) > 0 { if len(params.ProtectedRoles) > 0 {
for _, role := range params.ProtectedRoles { for _, role := range params.ProtectedRoles {
if utils.StringSliceContains(params.Roles, role) || utils.StringSliceContains(params.DefaultRoles, role) { if utils.StringSliceContains(params.Roles, role) || utils.StringSliceContains(params.DefaultRoles, role) {
log.Debug("Protected roles should not be in roles or default roles")
return res, fmt.Errorf("protected role %s found roles or default roles", role) return res, fmt.Errorf("protected role %s found roles or default roles", role)
} }
} }
@ -191,12 +209,14 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
envstore.EnvStoreObj.UpdateEnvStore(updatedData) envstore.EnvStoreObj.UpdateEnvStore(updatedData)
jwk, err := crypto.GenerateJWKBasedOnEnv() jwk, err := crypto.GenerateJWKBasedOnEnv()
if err != nil { if err != nil {
log.Debug("Failed to generate JWK", err)
return res, err return res, err
} }
// updating jwk // updating jwk
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJWK, jwk) envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJWK, jwk)
err = sessionstore.InitSession() err = sessionstore.InitSession()
if err != nil { if err != nil {
log.Debug("Failed to init session store", err)
return res, err return res, err
} }
err = oauth.InitOAuth() err = oauth.InitOAuth()
@ -207,12 +227,14 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
// Fetch the current db store and update it // Fetch the current db store and update it
env, err := db.Provider.GetEnv() env, err := db.Provider.GetEnv()
if err != nil { if err != nil {
log.Debug("Failed to get env", err)
return res, err return res, err
} }
if params.AdminSecret != nil { if params.AdminSecret != nil {
hashedKey, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)) hashedKey, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
if err != nil { if err != nil {
log.Debug("Failed to encrypt admin secret", err)
return res, err return res, err
} }
cookie.SetAdminCookie(gc, hashedKey) cookie.SetAdminCookie(gc, hashedKey)
@ -220,13 +242,14 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
encryptedConfig, err := crypto.EncryptEnvData(updatedData) encryptedConfig, err := crypto.EncryptEnvData(updatedData)
if err != nil { if err != nil {
log.Debug("Failed to encrypt env data", err)
return res, err return res, err
} }
env.EnvData = encryptedConfig env.EnvData = encryptedConfig
_, err = db.Provider.UpdateEnv(env) _, err = db.Provider.UpdateEnv(env)
if err != nil { if err != nil {
log.Println("error updating config:", err) log.Debug("Failed to update env", err)
return res, err return res, err
} }

View File

@ -3,10 +3,11 @@ package resolvers
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto" "github.com/authorizerdev/authorizer/server/crypto"
@ -23,18 +24,22 @@ import (
// UpdateProfileResolver is resolver for update profile mutation // UpdateProfileResolver is resolver for update profile mutation
func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error) { func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
accessToken, err := token.GetAccessToken(gc) accessToken, err := token.GetAccessToken(gc)
if err != nil { if err != nil {
log.Debug("Failed to get access token", err)
return res, err return res, err
} }
claims, err := token.ValidateAccessToken(gc, accessToken) claims, err := token.ValidateAccessToken(gc, accessToken)
if err != nil { if err != nil {
log.Debug("Failed to validate access token", err)
return res, err return res, err
} }
@ -44,8 +49,13 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
} }
userID := claims["sub"].(string) userID := claims["sub"].(string)
log := log.WithFields(log.Fields{
"user_id": userID,
})
user, err := db.Provider.GetUserByID(userID) user, err := db.Provider.GetUserByID(userID)
if err != nil { if err != nil {
log.Debug("Failed to get user by id", err)
return res, err return res, err
} }
@ -83,18 +93,22 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
if params.OldPassword != nil { if params.OldPassword != nil {
if err = bcrypt.CompareHashAndPassword([]byte(*user.Password), []byte(*params.OldPassword)); err != nil { if err = bcrypt.CompareHashAndPassword([]byte(*user.Password), []byte(*params.OldPassword)); err != nil {
log.Debug("Failed to compare hash and old password", err)
return res, fmt.Errorf("incorrect old password") return res, fmt.Errorf("incorrect old password")
} }
if params.NewPassword == nil { if params.NewPassword == nil {
log.Debug("Failed to get new password")
return res, fmt.Errorf("new password is required") return res, fmt.Errorf("new password is required")
} }
if params.ConfirmNewPassword == nil { if params.ConfirmNewPassword == nil {
log.Debug("Failed to get confirm new password")
return res, fmt.Errorf("confirm password is required") return res, fmt.Errorf("confirm password is required")
} }
if *params.ConfirmNewPassword != *params.NewPassword { if *params.ConfirmNewPassword != *params.NewPassword {
log.Debug("Failed to compare new password and confirm new password")
return res, fmt.Errorf(`password and confirm password does not match`) return res, fmt.Errorf(`password and confirm password does not match`)
} }
@ -108,6 +122,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
if params.Email != nil && user.Email != *params.Email { if params.Email != nil && user.Email != *params.Email {
// check if valid email // check if valid email
if !utils.IsValidEmail(*params.Email) { if !utils.IsValidEmail(*params.Email) {
log.Debug("Failed to validate email", *params.Email)
return res, fmt.Errorf("invalid email address") return res, fmt.Errorf("invalid email address")
} }
newEmail := strings.ToLower(*params.Email) newEmail := strings.ToLower(*params.Email)
@ -115,15 +130,14 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
_, err := db.Provider.GetUserByEmail(newEmail) _, err := db.Provider.GetUserByEmail(newEmail)
// err = nil means user exists // err = nil means user exists
if err == nil { if err == nil {
log.Debug("Failed to get user by email", newEmail)
return res, fmt.Errorf("user with this email address already exists") return res, fmt.Errorf("user with this email address already exists")
} }
// TODO figure out how to delete all user sessions
go sessionstore.DeleteAllUserSession(user.ID) go sessionstore.DeleteAllUserSession(user.ID)
go cookie.DeleteSession(gc)
cookie.DeleteSession(gc)
user.Email = newEmail user.Email = newEmail
if !envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) { if !envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
hostname := utils.GetHost(gc) hostname := utils.GetHost(gc)
user.EmailVerifiedAt = nil user.EmailVerifiedAt = nil
@ -131,15 +145,17 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
// insert verification request // insert verification request
_, nonceHash, err := utils.GenerateNonce() _, nonceHash, err := utils.GenerateNonce()
if err != nil { if err != nil {
log.Debug("Failed to generate nonce", err)
return res, err return res, err
} }
verificationType := constants.VerificationTypeUpdateEmail verificationType := constants.VerificationTypeUpdateEmail
redirectURL := utils.GetAppURL(gc) redirectURL := utils.GetAppURL(gc)
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash, redirectURL) verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash, redirectURL)
if err != nil { if err != nil {
log.Println(`error generating token`, err) log.Debug("Failed to create verification token", err)
return res, err
} }
db.Provider.AddVerificationRequest(models.VerificationRequest{ _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
Token: verificationToken, Token: verificationToken,
Identifier: verificationType, Identifier: verificationType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
@ -147,6 +163,10 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
Nonce: nonceHash, Nonce: nonceHash,
RedirectURI: redirectURL, RedirectURI: redirectURL,
}) })
if err != nil {
log.Debug("Failed to add verification request", err)
return res, err
}
// exec it as go routin so that we can reduce the api latency // exec it as go routin so that we can reduce the api latency
go email.SendVerificationMail(newEmail, verificationToken, hostname) go email.SendVerificationMail(newEmail, verificationToken, hostname)
@ -155,7 +175,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
} }
_, err = db.Provider.UpdateUser(user) _, err = db.Provider.UpdateUser(user)
if err != nil { if err != nil {
log.Println("error updating user:", err) log.Debug("Failed to update user", err)
return res, err return res, err
} }
message := `Profile details updated successfully.` message := `Profile details updated successfully.`

View File

@ -3,10 +3,11 @@ package resolvers
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
@ -21,22 +22,36 @@ import (
// UpdateUserResolver is a resolver for update user mutation // UpdateUserResolver is a resolver for update user mutation
// This is admin only mutation // This is admin only mutation
func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*model.User, error) { func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*model.User, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.User var res *model.User
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return res, fmt.Errorf("unauthorized") return res, fmt.Errorf("unauthorized")
} }
if params.ID == "" {
log.Debug("Invalid user id")
return res, fmt.Errorf("User ID is required")
}
log := log.WithFields(log.Fields{
"user_id": params.ID,
})
if params.GivenName == nil && params.FamilyName == nil && params.Picture == nil && params.MiddleName == nil && params.Nickname == nil && params.Email == nil && params.Birthdate == nil && params.Gender == nil && params.PhoneNumber == nil && params.Roles == nil { if params.GivenName == nil && params.FamilyName == nil && params.Picture == nil && params.MiddleName == nil && params.Nickname == nil && params.Email == nil && params.Birthdate == nil && params.Gender == nil && params.PhoneNumber == nil && params.Roles == nil {
log.Debug("No params to update")
return res, fmt.Errorf("please enter atleast one param to update") return res, fmt.Errorf("please enter atleast one param to update")
} }
user, err := db.Provider.GetUserByID(params.ID) user, err := db.Provider.GetUserByID(params.ID)
if err != nil { if err != nil {
log.Debug("Failed to get user by id", err)
return res, fmt.Errorf(`User not found`) return res, fmt.Errorf(`User not found`)
} }
@ -84,6 +99,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
if params.Email != nil && user.Email != *params.Email { if params.Email != nil && user.Email != *params.Email {
// check if valid email // check if valid email
if !utils.IsValidEmail(*params.Email) { if !utils.IsValidEmail(*params.Email) {
log.Debug("Invalid email", *params.Email)
return res, fmt.Errorf("invalid email address") return res, fmt.Errorf("invalid email address")
} }
newEmail := strings.ToLower(*params.Email) newEmail := strings.ToLower(*params.Email)
@ -91,6 +107,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
_, err = db.Provider.GetUserByEmail(newEmail) _, err = db.Provider.GetUserByEmail(newEmail)
// err = nil means user exists // err = nil means user exists
if err == nil { if err == nil {
log.Debug("User with email already exists", newEmail)
return res, fmt.Errorf("user with this email address already exists") return res, fmt.Errorf("user with this email address already exists")
} }
@ -103,15 +120,16 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
// insert verification request // insert verification request
_, nonceHash, err := utils.GenerateNonce() _, nonceHash, err := utils.GenerateNonce()
if err != nil { if err != nil {
log.Debug("Failed to generate nonce", err)
return res, err return res, err
} }
verificationType := constants.VerificationTypeUpdateEmail verificationType := constants.VerificationTypeUpdateEmail
redirectURL := utils.GetAppURL(gc) redirectURL := utils.GetAppURL(gc)
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash, redirectURL) verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash, redirectURL)
if err != nil { if err != nil {
log.Println(`error generating token`, err) log.Debug("Failed to create verification token", err)
} }
db.Provider.AddVerificationRequest(models.VerificationRequest{ _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
Token: verificationToken, Token: verificationToken,
Identifier: verificationType, Identifier: verificationType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
@ -119,6 +137,10 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
Nonce: nonceHash, Nonce: nonceHash,
RedirectURI: redirectURL, RedirectURI: redirectURL,
}) })
if err != nil {
log.Debug("Failed to add verification request", err)
return res, err
}
// exec it as go routin so that we can reduce the api latency // exec it as go routin so that we can reduce the api latency
go email.SendVerificationMail(newEmail, verificationToken, hostname) go email.SendVerificationMail(newEmail, verificationToken, hostname)
@ -134,6 +156,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
} }
if !utils.IsValidRoles(inputRoles, append([]string{}, append(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles)...)...)) { if !utils.IsValidRoles(inputRoles, append([]string{}, append(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles)...)...)) {
log.Debug("Invalid roles", params.Roles)
return res, fmt.Errorf("invalid list of roles") return res, fmt.Errorf("invalid list of roles")
} }
@ -150,7 +173,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
user, err = db.Provider.UpdateUser(user) user, err = db.Provider.UpdateUser(user)
if err != nil { if err != nil {
log.Println("error updating user:", err) log.Debug("Failed to update user", err)
return res, err return res, err
} }

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/token"
@ -15,10 +17,12 @@ import (
func UsersResolver(ctx context.Context, params *model.PaginatedInput) (*model.Users, error) { func UsersResolver(ctx context.Context, params *model.PaginatedInput) (*model.Users, error) {
gc, err := utils.GinContextFromContext(ctx) gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return nil, err return nil, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return nil, fmt.Errorf("unauthorized") return nil, fmt.Errorf("unauthorized")
} }
@ -26,6 +30,7 @@ func UsersResolver(ctx context.Context, params *model.PaginatedInput) (*model.Us
res, err := db.Provider.ListUsers(pagination) res, err := db.Provider.ListUsers(pagination)
if err != nil { if err != nil {
log.Debug("Failed to get users", err)
return nil, err return nil, err
} }

View File

@ -6,11 +6,13 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/golang-jwt/jwt"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore" "github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils" "github.com/authorizerdev/authorizer/server/utils"
"github.com/golang-jwt/jwt"
) )
// ValidateJwtTokenResolver is used to validate a jwt token without its rotation // ValidateJwtTokenResolver is used to validate a jwt token without its rotation
@ -22,11 +24,13 @@ import (
func ValidateJwtTokenResolver(ctx context.Context, params model.ValidateJWTTokenInput) (*model.ValidateJWTTokenResponse, error) { func ValidateJwtTokenResolver(ctx context.Context, params model.ValidateJWTTokenInput) (*model.ValidateJWTTokenResponse, error) {
gc, err := utils.GinContextFromContext(ctx) gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return nil, err return nil, err
} }
tokenType := params.TokenType tokenType := params.TokenType
if tokenType != "access_token" && tokenType != "refresh_token" && tokenType != "id_token" { if tokenType != "access_token" && tokenType != "refresh_token" && tokenType != "id_token" {
log.Debug("Invalid token type:", tokenType)
return nil, errors.New("invalid token type") return nil, errors.New("invalid token type")
} }
@ -53,6 +57,7 @@ func ValidateJwtTokenResolver(ctx context.Context, params model.ValidateJWTToken
if userID != "" && nonce != "" { if userID != "" && nonce != "" {
claims, err = token.ParseJWTToken(params.Token, hostname, nonce, userID) claims, err = token.ParseJWTToken(params.Token, hostname, nonce, userID)
if err != nil { if err != nil {
log.Debug("Failed to parse jwt token", err)
return &model.ValidateJWTTokenResponse{ return &model.ValidateJWTTokenResponse{
IsValid: false, IsValid: false,
}, nil }, nil
@ -60,6 +65,7 @@ func ValidateJwtTokenResolver(ctx context.Context, params model.ValidateJWTToken
} else { } else {
claims, err = token.ParseJWTTokenWithoutNonce(params.Token, hostname) claims, err = token.ParseJWTTokenWithoutNonce(params.Token, hostname)
if err != nil { if err != nil {
log.Debug("Failed to parse jwt token without nonce", err)
return &model.ValidateJWTTokenResponse{ return &model.ValidateJWTTokenResponse{
IsValid: false, IsValid: false,
}, nil }, nil
@ -76,6 +82,7 @@ func ValidateJwtTokenResolver(ctx context.Context, params model.ValidateJWTToken
if params.Roles != nil && len(params.Roles) > 0 { if params.Roles != nil && len(params.Roles) > 0 {
for _, v := range params.Roles { for _, v := range params.Roles {
if !utils.StringSliceContains(claimRoles, v) { if !utils.StringSliceContains(claimRoles, v) {
log.Debug("Token does not have required role:", v)
return nil, fmt.Errorf(`unauthorized`) return nil, fmt.Errorf(`unauthorized`)
} }
} }

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/token"
@ -15,10 +17,12 @@ import (
func VerificationRequestsResolver(ctx context.Context, params *model.PaginatedInput) (*model.VerificationRequests, error) { func VerificationRequestsResolver(ctx context.Context, params *model.PaginatedInput) (*model.VerificationRequests, error) {
gc, err := utils.GinContextFromContext(ctx) gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return nil, err return nil, err
} }
if !token.IsSuperAdmin(gc) { if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return nil, fmt.Errorf("unauthorized") return nil, fmt.Errorf("unauthorized")
} }
@ -26,6 +30,7 @@ func VerificationRequestsResolver(ctx context.Context, params *model.PaginatedIn
res, err := db.Provider.ListVerificationRequests(pagination) res, err := db.Provider.ListVerificationRequests(pagination)
if err != nil { if err != nil {
log.Debug("Failed to get verification requests", err)
return nil, err return nil, err
} }

View File

@ -6,6 +6,8 @@ import (
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
@ -17,14 +19,17 @@ import (
// VerifyEmailResolver is a resolver for verify email mutation // VerifyEmailResolver is a resolver for verify email mutation
func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*model.AuthResponse, error) { func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*model.AuthResponse, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.AuthResponse var res *model.AuthResponse
gc, err := utils.GinContextFromContext(ctx)
if err != nil { if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err return res, err
} }
verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token) verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token)
if err != nil { if err != nil {
log.Debug("Failed to get verification request by token", err)
return res, fmt.Errorf(`invalid token: %s`, err.Error()) return res, fmt.Errorf(`invalid token: %s`, err.Error())
} }
@ -32,11 +37,17 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
hostname := utils.GetHost(gc) hostname := utils.GetHost(gc)
claim, err := token.ParseJWTToken(params.Token, hostname, verificationRequest.Nonce, verificationRequest.Email) claim, err := token.ParseJWTToken(params.Token, hostname, verificationRequest.Nonce, verificationRequest.Email)
if err != nil { if err != nil {
log.Debug("Failed to parse token", err)
return res, fmt.Errorf(`invalid token: %s`, err.Error()) return res, fmt.Errorf(`invalid token: %s`, err.Error())
} }
user, err := db.Provider.GetUserByEmail(claim["sub"].(string)) email := claim["sub"].(string)
log := log.WithFields(log.Fields{
"email": email,
})
user, err := db.Provider.GetUserByEmail(email)
if err != nil { if err != nil {
log.Debug("Failed to get user by email", err)
return res, err return res, err
} }
@ -45,11 +56,13 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
user.EmailVerifiedAt = &now user.EmailVerifiedAt = &now
user, err = db.Provider.UpdateUser(user) user, err = db.Provider.UpdateUser(user)
if err != nil { if err != nil {
log.Debug("Failed to update user", err)
return res, err return res, err
} }
// delete from verification table // delete from verification table
err = db.Provider.DeleteVerificationRequest(verificationRequest) err = db.Provider.DeleteVerificationRequest(verificationRequest)
if err != nil { if err != nil {
log.Debug("Failed to delete verification request", err)
return res, err return res, err
} }
@ -57,6 +70,7 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
scope := []string{"openid", "email", "profile"} scope := []string{"openid", "email", "profile"}
authToken, err := token.CreateAuthToken(gc, user, roles, scope) authToken, err := token.CreateAuthToken(gc, user, roles, scope)
if err != nil { if err != nil {
log.Debug("Failed to create auth token", err)
return res, err return res, err
} }