Add VerifyPassword to API
It takes in an email and plain text password to verify. If it fails to find a password stored for email, it returns not_found. If it finds the password hash stored but that hash doesn't match the password passed via the API, it returns verified = false, else it returns verified = true. Co-authored-by: Alban Seurat <alban.seurat@me.com>
This commit is contained in:
committed by
Alban Seurat
parent
92920c86ea
commit
dd84e73c0e
@@ -254,6 +254,37 @@ func (d dexAPI) ListPasswords(ctx context.Context, req *api.ListPasswordReq) (*a
|
||||
|
||||
}
|
||||
|
||||
func (d dexAPI) VerifyPassword(ctx context.Context, req *api.VerifyPasswordReq) (*api.VerifyPasswordResp, error) {
|
||||
if req.Email == "" {
|
||||
return nil, errors.New("no email supplied")
|
||||
}
|
||||
|
||||
if req.Password == "" {
|
||||
return nil, errors.New("no password to verify supplied")
|
||||
}
|
||||
|
||||
password, err := d.s.GetPassword(req.Email)
|
||||
if err != nil {
|
||||
if err == storage.ErrNotFound {
|
||||
return &api.VerifyPasswordResp{
|
||||
NotFound: true,
|
||||
}, nil
|
||||
}
|
||||
d.logger.Errorf("api: there was an error retrieving the password: %v", err)
|
||||
return nil, fmt.Errorf("verify password: %v", err)
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword(password.Hash, []byte(req.Password)); err != nil {
|
||||
d.logger.Info("api: password check failed : %v", err)
|
||||
return &api.VerifyPasswordResp{
|
||||
Verified: false,
|
||||
}, nil
|
||||
}
|
||||
return &api.VerifyPasswordResp{
|
||||
Verified: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d dexAPI) ListRefresh(ctx context.Context, req *api.ListRefreshReq) (*api.ListRefreshResp, error) {
|
||||
id := new(internal.IDTokenSubject)
|
||||
if err := internal.Unmarshal(req.UserId, id); err != nil {
|
||||
|
@@ -69,8 +69,9 @@ func TestPassword(t *testing.T) {
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
email := "test@example.com"
|
||||
p := api.Password{
|
||||
Email: "test@example.com",
|
||||
Email: email,
|
||||
// bcrypt hash of the value "test1" with cost 10
|
||||
Hash: []byte("$2a$10$XVMN/Fid.Ks4CXgzo8fpR.iU1khOMsP5g9xQeXuBm1wXjRX8pjUtO"),
|
||||
Username: "test",
|
||||
@@ -93,8 +94,56 @@ func TestPassword(t *testing.T) {
|
||||
t.Fatalf("Created password %s twice", createReq.Password.Email)
|
||||
}
|
||||
|
||||
// Attempt to verify valid password and email
|
||||
goodVerifyReq := &api.VerifyPasswordReq{
|
||||
Email: email,
|
||||
Password: "test1",
|
||||
}
|
||||
goodVerifyResp, err := client.VerifyPassword(ctx, goodVerifyReq)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to run verify password we expected to be valid for correct email: %v", err)
|
||||
}
|
||||
if !goodVerifyResp.Verified {
|
||||
t.Fatalf("verify password failed for password expected to be valid for correct email. expected %t, found %t", true, goodVerifyResp.Verified)
|
||||
}
|
||||
if goodVerifyResp.NotFound {
|
||||
t.Fatalf("verify password failed to return not found response. expected %t, found %t", false, goodVerifyResp.NotFound)
|
||||
}
|
||||
|
||||
// Check not found response for valid password with wrong email
|
||||
badEmailVerifyReq := &api.VerifyPasswordReq{
|
||||
Email: "somewrongaddress@email.com",
|
||||
Password: "test1",
|
||||
}
|
||||
badEmailVerifyResp, err := client.VerifyPassword(ctx, badEmailVerifyReq)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to run verify password for incorrect email: %v", err)
|
||||
}
|
||||
if badEmailVerifyResp.Verified {
|
||||
t.Fatalf("verify password passed for password expected to be not found. expected %t, found %t", false, badEmailVerifyResp.Verified)
|
||||
}
|
||||
if !badEmailVerifyResp.NotFound {
|
||||
t.Fatalf("expected not found response for verify password with bad email. expected %t, found %t", true, badEmailVerifyResp.NotFound)
|
||||
}
|
||||
|
||||
// Check that wrong password fails
|
||||
badPassVerifyReq := &api.VerifyPasswordReq{
|
||||
Email: email,
|
||||
Password: "wrong_password",
|
||||
}
|
||||
badPassVerifyResp, err := client.VerifyPassword(ctx, badPassVerifyReq)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to run verify password for password we expected to be invalid: %v", err)
|
||||
}
|
||||
if badPassVerifyResp.Verified {
|
||||
t.Fatalf("verify password passed for password we expected to fail. expected %t, found %t", false, badPassVerifyResp.Verified)
|
||||
}
|
||||
if badPassVerifyResp.NotFound {
|
||||
t.Fatalf("did not expect expected not found response for verify password with bad email. expected %t, found %t", false, badPassVerifyResp.NotFound)
|
||||
}
|
||||
|
||||
updateReq := api.UpdatePasswordReq{
|
||||
Email: "test@example.com",
|
||||
Email: email,
|
||||
NewUsername: "test1",
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user