feat: session v2 passkey authentication (#5952)

This commit is contained in:
Tim Möhlmann
2023-06-07 17:28:42 +02:00
committed by GitHub
parent f7157b65f4
commit f456168a74
39 changed files with 1261 additions and 162 deletions

View File

@@ -35,7 +35,7 @@ func AssertDetails[D DetailsMsg](t testing.TB, exptected, actual D) {
gotCD := gotDetails.GetChangeDate().AsTime()
now := time.Now()
assert.WithinRange(t, gotCD, now.Add(-time.Second), now.Add(time.Second))
assert.WithinRange(t, gotCD, now.Add(-time.Minute), now.Add(time.Minute))
assert.Equal(t, wantDetails.GetResourceOwner(), gotDetails.GetResourceOwner())
}

View File

@@ -0,0 +1,77 @@
package integration
import (
"context"
"fmt"
"time"
"github.com/zitadel/logging"
"google.golang.org/grpc"
"github.com/zitadel/zitadel/pkg/grpc/admin"
object "github.com/zitadel/zitadel/pkg/grpc/object/v2alpha"
session "github.com/zitadel/zitadel/pkg/grpc/session/v2alpha"
user "github.com/zitadel/zitadel/pkg/grpc/user/v2alpha"
)
type Client struct {
CC *grpc.ClientConn
Admin admin.AdminServiceClient
UserV2 user.UserServiceClient
SessionV2 session.SessionServiceClient
}
func newClient(cc *grpc.ClientConn) Client {
return Client{
CC: cc,
Admin: admin.NewAdminServiceClient(cc),
UserV2: user.NewUserServiceClient(cc),
SessionV2: session.NewSessionServiceClient(cc),
}
}
func (s *Tester) CreateHumanUser(ctx context.Context) *user.AddHumanUserResponse {
resp, err := s.Client.UserV2.AddHumanUser(ctx, &user.AddHumanUserRequest{
Organisation: &object.Organisation{
Org: &object.Organisation_OrgId{
OrgId: s.Organisation.ID,
},
},
Profile: &user.SetHumanProfile{
FirstName: "Mickey",
LastName: "Mouse",
},
Email: &user.SetHumanEmail{
Email: fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()),
Verification: &user.SetHumanEmail_ReturnCode{
ReturnCode: &user.ReturnEmailVerificationCode{},
},
},
})
logging.OnError(err).Fatal("create human user")
return resp
}
func (s *Tester) RegisterUserPasskey(ctx context.Context, userID string) {
reg, err := s.Client.UserV2.CreatePasskeyRegistrationLink(ctx, &user.CreatePasskeyRegistrationLinkRequest{
UserId: userID,
Medium: &user.CreatePasskeyRegistrationLinkRequest_ReturnCode{},
})
logging.OnError(err).Fatal("create user passkey")
pkr, err := s.Client.UserV2.RegisterPasskey(ctx, &user.RegisterPasskeyRequest{
UserId: userID,
Code: reg.GetCode(),
})
logging.OnError(err).Fatal("create user passkey")
attestationResponse, err := s.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions())
logging.OnError(err).Fatal("create user passkey")
_, err = s.Client.UserV2.VerifyPasskeyRegistration(ctx, &user.VerifyPasskeyRegistrationRequest{
UserId: userID,
PasskeyId: pkr.GetPasskeyId(),
PublicKeyCredential: attestationResponse,
PasskeyName: "nice name",
})
logging.OnError(err).Fatal("create user passkey")
}

View File

@@ -29,6 +29,7 @@ import (
caos_errs "github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
"github.com/zitadel/zitadel/internal/query"
"github.com/zitadel/zitadel/internal/webauthn"
"github.com/zitadel/zitadel/pkg/grpc/admin"
)
@@ -68,8 +69,9 @@ type Tester struct {
Organisation *query.Org
Users map[UserType]User
GRPCClientConn *grpc.ClientConn
wg sync.WaitGroup // used for shutdown
Client Client
WebAuthN *webauthn.Client
wg sync.WaitGroup // used for shutdown
}
const commandLine = `start --masterkeyFromEnv`
@@ -90,7 +92,7 @@ func (s *Tester) createClientConn(ctx context.Context) {
logging.OnError(err).Fatal("integration tester client dial")
logging.New().WithField("target", target).Info("finished dialing grpc client conn")
s.GRPCClientConn = cc
s.Client = newClient(cc)
err = s.pollHealth(ctx)
logging.OnError(err).Fatal("integration tester health")
}
@@ -99,14 +101,12 @@ func (s *Tester) createClientConn(ctx context.Context) {
// TODO: remove when we make the setup blocking on all
// projections completed.
func (s *Tester) pollHealth(ctx context.Context) (err error) {
client := admin.NewAdminServiceClient(s.GRPCClientConn)
for {
err = func(ctx context.Context) error {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
_, err := client.Healthz(ctx, &admin.HealthzRequest{})
_, err := s.Client.Admin.Healthz(ctx, &admin.HealthzRequest{})
return err
}(ctx)
if err == nil {
@@ -182,7 +182,7 @@ func (s *Tester) WithSystemAuthorization(ctx context.Context, u UserType) contex
// Done send an interrupt signal to cleanly shutdown the server.
func (s *Tester) Done() {
err := s.GRPCClientConn.Close()
err := s.Client.CC.Close()
logging.OnError(err).Error("integration tester client close")
s.Shutdown <- os.Interrupt
@@ -238,6 +238,7 @@ func NewTester(ctx context.Context) *Tester {
}
tester.createClientConn(ctx)
tester.createSystemUser(ctx)
tester.WebAuthN = webauthn.NewClient(tester.Config.WebAuthNName, tester.Config.ExternalDomain, "https://"+tester.Host())
return tester
}