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 (
"context"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/coreos/go-oidc/v3/oidc"
"golang.org/x/oauth2"
facebookOAuth2 "golang.org/x/oauth2/facebook"
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,10 +3,11 @@ package resolvers
import (
"context"
"fmt"
"log"
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
@ -19,20 +20,28 @@ import (
// ForgotPasswordResolver is a resolver for forgot password mutation
func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err
}
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
log.Debug("Basic authentication is disabled.")
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
}
params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) {
log.Debug("Invalid email address.")
return res, fmt.Errorf("invalid email")
}
log := log.WithFields(log.Fields{
"email": params.Email,
})
_, err = db.Provider.GetUserByEmail(params.Email)
if err != nil {
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/token"
"github.com/authorizerdev/authorizer/server/utils"
log "github.com/sirupsen/logrus"
)
// GenerateJWTKeysResolver mutation to generate new jwt keys
func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysInput) (*model.GenerateJWTKeysResponse, error) {
gc, err := utils.GinContextFromContext(ctx)
if err != nil {
log.Debug("Failed to get GinContext", err)
return nil, err
}
if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return nil, fmt.Errorf("unauthorized")
}
@ -27,6 +30,7 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
if crypto.IsHMACA(params.Type) {
secret, _, err := crypto.NewHMACKey(params.Type, clientID)
if err != nil {
log.Debug("Failed to generate new HMAC key:", err)
return nil, err
}
return &model.GenerateJWTKeysResponse{
@ -37,6 +41,7 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
if crypto.IsRSA(params.Type) {
_, privateKey, publicKey, _, err := crypto.NewRSAKey(params.Type, clientID)
if err != nil {
log.Debug("Failed to generate new RSA key:", err)
return nil, err
}
return &model.GenerateJWTKeysResponse{
@ -48,6 +53,7 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
if crypto.IsECDSA(params.Type) {
_, privateKey, publicKey, _, err := crypto.NewECDSAKey(params.Type, clientID)
if err != nil {
log.Debug("Failed to generate new ECDSA key:", err)
return nil, err
}
return &model.GenerateJWTKeysResponse{
@ -56,5 +62,6 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
}, nil
}
log.Debug("Invalid algorithm:", params.Type)
return nil, fmt.Errorf("invalid algorithm")
}

View File

@ -4,10 +4,11 @@ import (
"context"
"errors"
"fmt"
"log"
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
@ -22,19 +23,23 @@ import (
func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
if err != nil {
log.Debug("Failed to get GinContext", err)
return nil, err
}
if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
return nil, errors.New("unauthorized")
}
// this feature is only allowed if email server is configured
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
log.Debug("Email server is not configured.")
return nil, errors.New("email sending is disabled")
}
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")
}
@ -47,6 +52,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
}
if len(emails) == 0 {
log.Debug("No valid email addresses.")
return nil, errors.New("no valid emails found")
}
@ -56,14 +62,15 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
for _, email := range emails {
_, err := db.Provider.GetUserByEmail(email)
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)
} else {
log.Println("%s user already exists. skipping.", email)
log.Info("User with this email already exists, so not inviting...")
}
}
if len(newEmails) == 0 {
log.Debug("No new emails found.")
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)
if err != nil {
log.Println(`error generating token`, err)
log.Debug("Failed to create verification token.", err)
}
verificationRequest := models.VerificationRequest{
@ -116,13 +123,13 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
user, err = db.Provider.AddUser(user)
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
}
_, err = db.Provider.AddVerificationRequest(verificationRequest)
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
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,6 +6,8 @@ import (
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/db"
@ -18,24 +20,30 @@ import (
// ResetPasswordResolver is a resolver for reset password mutation
func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err
}
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
log.Debug("Basic authentication is disabled")
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
}
verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token)
if err != nil {
log.Debug("Failed to get verification request", err)
return res, fmt.Errorf(`invalid token`)
}
if params.Password != params.ConfirmPassword {
log.Debug("Passwords do not match")
return res, fmt.Errorf(`passwords don't match`)
}
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`)
}
@ -43,11 +51,17 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
hostname := utils.GetHost(gc)
claim, err := token.ParseJWTToken(params.Token, hostname, verificationRequest.Nonce, verificationRequest.Email)
if err != nil {
log.Debug("Failed to parse token", err)
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 {
log.Debug("Failed to get user", err)
return res, err
}
@ -67,8 +81,17 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
}
// delete from verification table
db.Provider.DeleteVerificationRequest(verificationRequest)
db.Provider.UpdateUser(user)
err = db.Provider.DeleteVerificationRequest(verificationRequest)
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{
Message: `Password updated successfully.`,

View File

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

View File

@ -4,9 +4,10 @@ import (
"context"
"errors"
"fmt"
"log"
"time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db"
"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)
if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err
}
sessionToken, err := cookie.GetSession(gc)
if err != nil {
log.Println("error getting session token:", err)
log.Debug("Failed to get session token", err)
return res, errors.New("unauthorized")
}
// get session from cookie
claims, err := token.ValidateBrowserSession(gc, sessionToken)
if err != nil {
log.Println("session validation failed:", err)
log.Debug("Failed to validate session token", err)
return res, errors.New("unauthorized")
}
userID := claims.Subject
log := log.WithFields(log.Fields{
"user_id": userID,
})
user, err := db.Provider.GetUserByID(userID)
if err != nil {
return res, err
@ -46,13 +53,12 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
// refresh token has "roles" as claim
claimRoleInterface := claims.Roles
claimRoles := []string{}
for _, v := range claimRoleInterface {
claimRoles = append(claimRoles, v)
}
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 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)
if err != nil {
log.Debug("Failed to create auth token", err)
return res, err
}

View File

@ -3,10 +3,11 @@ package resolvers
import (
"context"
"fmt"
"log"
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto"
@ -22,44 +23,56 @@ import (
// SignupResolver is a resolver for signup mutation
func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.AuthResponse
gc, err := utils.GinContextFromContext(ctx)
if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err
}
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) {
log.Debug("Signup is disabled.")
return res, fmt.Errorf(`signup is disabled for this instance`)
}
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
log.Debug("Basic authentication is disabled.")
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
}
if params.ConfirmPassword != params.Password {
log.Debug("Passwords do not match.")
return res, fmt.Errorf(`password and confirm password does not match`)
}
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`)
}
params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) {
log.Debug("Invalid email:", params.Email)
return res, fmt.Errorf(`invalid email address`)
}
log := log.WithFields(log.Fields{
"email": params.Email,
})
// find user with email
existingUser, err := db.Provider.GetUserByEmail(params.Email)
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 {
// 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)
}
@ -68,6 +81,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
if len(params.Roles) > 0 {
// check if roles exists
if !utils.IsValidRoles(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), params.Roles) {
log.Debug("Invalid roles", params.Roles)
return res, fmt.Errorf(`invalid roles`)
} else {
inputRoles = params.Roles
@ -124,6 +138,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
}
user, err = db.Provider.AddUser(user)
if err != nil {
log.Debug("Failed to add user:", err)
return res, err
}
roles := strings.Split(user.Roles, ",")
@ -134,6 +149,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
// insert verification request
_, nonceHash, err := utils.GenerateNonce()
if err != nil {
log.Debug("Failed to generate nonce:", err)
return res, err
}
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)
if err != nil {
log.Debug("Failed to create verification token:", err)
return res, err
}
db.Provider.AddVerificationRequest(models.VerificationRequest{
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
Token: verificationToken,
Identifier: verificationType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
@ -153,6 +170,10 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
Nonce: nonceHash,
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
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)
if err != nil {
log.Debug("Failed to create auth token:", err)
return res, err
}

View File

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

View File

@ -3,10 +3,11 @@ package resolvers
import (
"context"
"fmt"
"log"
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto"
@ -23,18 +24,22 @@ import (
// UpdateProfileResolver is resolver for update profile mutation
func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response
gc, err := utils.GinContextFromContext(ctx)
if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err
}
accessToken, err := token.GetAccessToken(gc)
if err != nil {
log.Debug("Failed to get access token", err)
return res, err
}
claims, err := token.ValidateAccessToken(gc, accessToken)
if err != nil {
log.Debug("Failed to validate access token", err)
return res, err
}
@ -44,8 +49,13 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
}
userID := claims["sub"].(string)
log := log.WithFields(log.Fields{
"user_id": userID,
})
user, err := db.Provider.GetUserByID(userID)
if err != nil {
log.Debug("Failed to get user by id", err)
return res, err
}
@ -83,18 +93,22 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
if params.OldPassword != 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")
}
if params.NewPassword == nil {
log.Debug("Failed to get new password")
return res, fmt.Errorf("new password is required")
}
if params.ConfirmNewPassword == nil {
log.Debug("Failed to get confirm new password")
return res, fmt.Errorf("confirm password is required")
}
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`)
}
@ -108,6 +122,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
if params.Email != nil && user.Email != *params.Email {
// check if valid email
if !utils.IsValidEmail(*params.Email) {
log.Debug("Failed to validate email", *params.Email)
return res, fmt.Errorf("invalid email address")
}
newEmail := strings.ToLower(*params.Email)
@ -115,15 +130,14 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
_, err := db.Provider.GetUserByEmail(newEmail)
// err = nil means user exists
if err == nil {
log.Debug("Failed to get user by email", newEmail)
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 cookie.DeleteSession(gc)
cookie.DeleteSession(gc)
user.Email = newEmail
if !envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
hostname := utils.GetHost(gc)
user.EmailVerifiedAt = nil
@ -131,15 +145,17 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
// insert verification request
_, nonceHash, err := utils.GenerateNonce()
if err != nil {
log.Debug("Failed to generate nonce", err)
return res, err
}
verificationType := constants.VerificationTypeUpdateEmail
redirectURL := utils.GetAppURL(gc)
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash, redirectURL)
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,
Identifier: verificationType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
@ -147,6 +163,10 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
Nonce: nonceHash,
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
go email.SendVerificationMail(newEmail, verificationToken, hostname)
@ -155,7 +175,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
}
_, err = db.Provider.UpdateUser(user)
if err != nil {
log.Println("error updating user:", err)
log.Debug("Failed to update user", err)
return res, err
}
message := `Profile details updated successfully.`

View File

@ -3,10 +3,11 @@ package resolvers
import (
"context"
"fmt"
"log"
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
@ -21,22 +22,36 @@ import (
// UpdateUserResolver is a resolver for update user mutation
// This is admin only mutation
func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*model.User, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.User
gc, err := utils.GinContextFromContext(ctx)
if err != nil {
log.Debug("Failed to get GinContext", err)
return res, err
}
if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin.")
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 {
log.Debug("No params to update")
return res, fmt.Errorf("please enter atleast one param to update")
}
user, err := db.Provider.GetUserByID(params.ID)
if err != nil {
log.Debug("Failed to get user by id", err)
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 {
// check if valid email
if !utils.IsValidEmail(*params.Email) {
log.Debug("Invalid email", *params.Email)
return res, fmt.Errorf("invalid email address")
}
newEmail := strings.ToLower(*params.Email)
@ -91,6 +107,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
_, err = db.Provider.GetUserByEmail(newEmail)
// err = nil means user exists
if err == nil {
log.Debug("User with email already exists", newEmail)
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
_, nonceHash, err := utils.GenerateNonce()
if err != nil {
log.Debug("Failed to generate nonce", err)
return res, err
}
verificationType := constants.VerificationTypeUpdateEmail
redirectURL := utils.GetAppURL(gc)
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash, redirectURL)
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,
Identifier: verificationType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
@ -119,6 +137,10 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
Nonce: nonceHash,
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
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)...)...)) {
log.Debug("Invalid roles", params.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)
if err != nil {
log.Println("error updating user:", err)
log.Debug("Failed to update user", err)
return res, err
}

View File

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

View File

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

View File

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

View File

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