passkey existing
This commit is contained in:
@@ -190,6 +190,57 @@ func (s *Service) FinishPasskeyRegistration(ctx context.Context, challengeID str
|
||||
return s.repo.GetUserByID(ctx, user.ID)
|
||||
}
|
||||
|
||||
func (s *Service) BeginCurrentUserPasskeyRegistration(ctx context.Context, principal Principal) (any, string, error) {
|
||||
if principal.UserID == "" {
|
||||
return nil, "", fmt.Errorf("authentication required")
|
||||
}
|
||||
user, err := s.repo.GetUserByID(ctx, principal.UserID)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if user.Disabled {
|
||||
return nil, "", fmt.Errorf("account disabled")
|
||||
}
|
||||
creation, session, err := s.webauthn.BeginRegistration(user)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
challengeID, err := s.repo.SaveChallenge(ctx, user.ID, "webauthn_registration", *session, challengeTTL)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return creation, challengeID, nil
|
||||
}
|
||||
|
||||
func (s *Service) FinishCurrentUserPasskeyRegistration(ctx context.Context, principal Principal, challengeID string, r *http.Request) (User, error) {
|
||||
if principal.UserID == "" {
|
||||
return User{}, fmt.Errorf("authentication required")
|
||||
}
|
||||
session, userID, err := s.repo.ConsumeChallenge(ctx, challengeID, "webauthn_registration")
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
if userID != principal.UserID {
|
||||
return User{}, fmt.Errorf("challenge does not belong to the current user")
|
||||
}
|
||||
user, err := s.repo.GetUserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
if user.Disabled {
|
||||
return User{}, fmt.Errorf("account disabled")
|
||||
}
|
||||
credential, err := s.webauthn.FinishRegistration(user, session, r)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
if err := s.repo.SaveCredential(ctx, user.ID, *credential); err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
s.repo.Audit(ctx, user.ID, "auth.passkey.add", "user", user.ID, clientIP(r), r.UserAgent(), nil)
|
||||
return s.repo.GetUserByID(ctx, user.ID)
|
||||
}
|
||||
|
||||
func (s *Service) BeginPasskeyLogin(ctx context.Context, email string) (any, string, error) {
|
||||
user, err := s.repo.GetUserByEmail(ctx, normalizeEmail(email))
|
||||
if err != nil {
|
||||
|
||||
@@ -315,6 +315,21 @@ func TestPublicRegistrationCannotAttachCredentialsToExistingUser(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentUserCanBeginPasskeyRegistrationForExistingAccount(t *testing.T) {
|
||||
service := setupAuthTestService(t)
|
||||
ctx := context.Background()
|
||||
|
||||
user := setupInitialAdmin(t, service, false)
|
||||
principal := principalFromUser(user, "session", "sess:test", "", nil, time.Now().Add(time.Hour))
|
||||
options, challengeID, err := service.BeginCurrentUserPasskeyRegistration(ctx, principal)
|
||||
if err != nil {
|
||||
t.Fatalf("BeginCurrentUserPasskeyRegistration() error = %v", err)
|
||||
}
|
||||
if options == nil || challengeID == "" {
|
||||
t.Fatalf("options = %#v, challengeID = %q; want registration options and challenge", options, challengeID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitialSetupCanDisablePublicRegistration(t *testing.T) {
|
||||
service := setupAuthTestService(t)
|
||||
ctx := context.Background()
|
||||
|
||||
Reference in New Issue
Block a user