verifyUserAndToken verifies the token associated to the user based on the verify type
(conn *storage.Connection, params *VerifyParams, aud string)
| 697 | |
| 698 | // verifyUserAndToken verifies the token associated to the user based on the verify type |
| 699 | func (a *API) verifyUserAndToken(conn *storage.Connection, params *VerifyParams, aud string) (*models.User, error) { |
| 700 | config := a.config |
| 701 | |
| 702 | var user *models.User |
| 703 | var err error |
| 704 | tokenHash := params.TokenHash |
| 705 | |
| 706 | switch params.Type { |
| 707 | case phoneChangeVerification: |
| 708 | user, err = models.FindUserByPhoneChangeAndAudience(conn, params.Phone, aud) |
| 709 | case smsVerification: |
| 710 | user, err = models.FindUserByPhoneAndAudience(conn, params.Phone, aud) |
| 711 | case mail.EmailChangeVerification: |
| 712 | // Since the email change could be trigger via the implicit or PKCE flow, |
| 713 | // the query used has to also check if the token saved in the db contains the pkce_ prefix |
| 714 | user, err = models.FindUserForEmailChange(conn, params.Email, tokenHash, aud, config.Mailer.SecureEmailChangeEnabled) |
| 715 | default: |
| 716 | user, err = models.FindUserByEmailAndAudience(conn, params.Email, aud) |
| 717 | } |
| 718 | |
| 719 | if err != nil { |
| 720 | if models.IsNotFoundError(err) { |
| 721 | return nil, apierrors.NewForbiddenError(apierrors.ErrorCodeOTPExpired, "Token has expired or is invalid").WithInternalError(err) |
| 722 | } |
| 723 | return nil, apierrors.NewInternalServerError("Database error finding user").WithInternalError(err) |
| 724 | } |
| 725 | |
| 726 | if user.IsBanned() { |
| 727 | return nil, apierrors.NewForbiddenError(apierrors.ErrorCodeUserBanned, "User is banned") |
| 728 | } |
| 729 | |
| 730 | var isValid bool |
| 731 | |
| 732 | smsProvider, _ := sms_provider.GetSmsProvider(*config) |
| 733 | switch params.Type { |
| 734 | case mail.EmailOTPVerification: |
| 735 | // if the type is emailOTPVerification, we'll check both the confirmation_token and recovery_token columns |
| 736 | if isOtpValid(tokenHash, user.ConfirmationToken, user.ConfirmationSentAt, config.Mailer.OtpExp) { |
| 737 | isValid = true |
| 738 | params.Type = mail.SignupVerification |
| 739 | } else if isOtpValid(tokenHash, user.RecoveryToken, user.RecoverySentAt, config.Mailer.OtpExp) { |
| 740 | isValid = true |
| 741 | params.Type = mail.MagicLinkVerification |
| 742 | } else { |
| 743 | isValid = false |
| 744 | } |
| 745 | case mail.SignupVerification, mail.InviteVerification: |
| 746 | isValid = isOtpValid(tokenHash, user.ConfirmationToken, user.ConfirmationSentAt, config.Mailer.OtpExp) |
| 747 | case mail.RecoveryVerification, mail.MagicLinkVerification: |
| 748 | isValid = isOtpValid(tokenHash, user.RecoveryToken, user.RecoverySentAt, config.Mailer.OtpExp) |
| 749 | case mail.EmailChangeVerification: |
| 750 | isValid = isOtpValid(tokenHash, user.EmailChangeTokenCurrent, user.EmailChangeSentAt, config.Mailer.OtpExp) || |
| 751 | isOtpValid(tokenHash, user.EmailChangeTokenNew, user.EmailChangeSentAt, config.Mailer.OtpExp) |
| 752 | case phoneChangeVerification, smsVerification: |
| 753 | if testOTP, ok := config.Sms.GetTestOTP(params.Phone, time.Now()); ok { |
| 754 | if params.Token == testOTP { |
| 755 | return user, nil |
| 756 | } |
no test coverage detected