Gate password sign-in on email verification
Unverified password identities were able to open sessions after signing out. Reject sign-in with EMAIL_NOT_VERIFIED and add a resend-confirmation flow so users can complete verification. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -17,6 +17,9 @@ extend type Mutation {
|
||||
@authentication(required: NONE)
|
||||
verifyEmail(input: VerifyEmailInput!): VerifyEmailPayload
|
||||
@authentication(required: OPTIONAL)
|
||||
resendVerificationEmail(
|
||||
input: ResendVerificationEmailInput!
|
||||
): ResendVerificationEmailPayload @authentication(required: NONE)
|
||||
changePassword(input: ChangePasswordInput!): ChangePasswordPayload
|
||||
@authentication(required: PRESENT) @sessionOnly
|
||||
changeEmail(input: ChangeEmailInput!): ChangeEmailPayload
|
||||
@@ -102,6 +105,10 @@ input VerifyEmailInput {
|
||||
token: String!
|
||||
}
|
||||
|
||||
input ResendVerificationEmailInput {
|
||||
email: EmailAddr!
|
||||
}
|
||||
|
||||
input ChangePasswordInput {
|
||||
currentPassword: String!
|
||||
newPassword: String!
|
||||
@@ -152,6 +159,10 @@ type VerifyEmailPayload {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type ResendVerificationEmailPayload {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type ChangePasswordPayload {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
@@ -40,6 +40,15 @@ func (r *mutationResolver) SignIn(ctx context.Context, input types.SignInInput)
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
if !identity.EmailAddressVerified {
|
||||
return nil, &gqlerror.Error{
|
||||
Message: iam.NewEmailNotVerifiedError().Error(),
|
||||
Extensions: map[string]any{
|
||||
"code": "EMAIL_NOT_VERIFIED",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
session := authn.SessionFromContext(ctx)
|
||||
|
||||
switch {
|
||||
@@ -311,6 +320,19 @@ func (r *mutationResolver) VerifyEmail(ctx context.Context, input types.VerifyEm
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ResendVerificationEmail is the resolver for the resendVerificationEmail field.
|
||||
func (r *mutationResolver) ResendVerificationEmail(ctx context.Context, input types.ResendVerificationEmailInput) (*types.ResendVerificationEmailPayload, error) {
|
||||
err := r.iam.AccountService.ResendVerificationEmail(ctx, input.Email)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot resend verification email", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return &types.ResendVerificationEmailPayload{
|
||||
Success: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ChangePassword is the resolver for the changePassword field.
|
||||
func (r *mutationResolver) ChangePassword(ctx context.Context, input types.ChangePasswordInput) (*types.ChangePasswordPayload, error) {
|
||||
identity := authn.IdentityFromContext(ctx)
|
||||
|
||||
Reference in New Issue
Block a user