mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:37:32 +00:00
fix: provide domain in session, passkey and u2f (#6097)
This fix provides a possibility to pass a domain on the session, which will be used (as rpID) to create a passkey / u2f assertion and attestation. This is useful in cases where the login UI is served under a different domain / origin than the ZITADEL API.
This commit is contained in:
@@ -157,7 +157,7 @@ func (s *SessionCommands) commands(ctx context.Context) (string, []eventstore.Co
|
||||
return token, s.sessionWriteModel.commands, nil
|
||||
}
|
||||
|
||||
func (c *Commands) CreateSession(ctx context.Context, cmds []SessionCommand, metadata map[string][]byte) (set *SessionChanged, err error) {
|
||||
func (c *Commands) CreateSession(ctx context.Context, cmds []SessionCommand, sessionDomain string, metadata map[string][]byte) (set *SessionChanged, err error) {
|
||||
sessionID, err := c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -167,8 +167,8 @@ func (c *Commands) CreateSession(ctx context.Context, cmds []SessionCommand, met
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sessionWriteModel.Start(ctx, sessionDomain)
|
||||
cmd := c.NewSessionCommands(cmds, sessionWriteModel)
|
||||
cmd.sessionWriteModel.Start(ctx)
|
||||
return c.updateSession(ctx, cmd, metadata)
|
||||
}
|
||||
|
||||
|
@@ -16,6 +16,7 @@ type PasskeyChallengeModel struct {
|
||||
Challenge string
|
||||
AllowedCrentialIDs [][]byte
|
||||
UserVerification domain.UserVerificationRequirement
|
||||
RPID string
|
||||
}
|
||||
|
||||
func (p *PasskeyChallengeModel) WebAuthNLogin(human *domain.Human, credentialAssertionData []byte) (*domain.WebAuthNLogin, error) {
|
||||
@@ -28,6 +29,7 @@ func (p *PasskeyChallengeModel) WebAuthNLogin(human *domain.Human, credentialAss
|
||||
Challenge: p.Challenge,
|
||||
AllowedCredentialIDs: p.AllowedCrentialIDs,
|
||||
UserVerification: p.UserVerification,
|
||||
RPID: p.RPID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -41,6 +43,7 @@ type SessionWriteModel struct {
|
||||
IntentCheckedAt time.Time
|
||||
PasskeyCheckedAt time.Time
|
||||
Metadata map[string][]byte
|
||||
Domain string
|
||||
State domain.SessionState
|
||||
|
||||
PasskeyChallenge *PasskeyChallengeModel
|
||||
@@ -109,6 +112,7 @@ func (wm *SessionWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
}
|
||||
|
||||
func (wm *SessionWriteModel) reduceAdded(e *session.AddedEvent) {
|
||||
wm.Domain = e.Domain
|
||||
wm.State = domain.SessionStateActive
|
||||
}
|
||||
|
||||
@@ -130,6 +134,7 @@ func (wm *SessionWriteModel) reducePasskeyChallenged(e *session.PasskeyChallenge
|
||||
Challenge: e.Challenge,
|
||||
AllowedCrentialIDs: e.AllowedCrentialIDs,
|
||||
UserVerification: e.UserVerification,
|
||||
RPID: wm.Domain,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,8 +151,10 @@ func (wm *SessionWriteModel) reduceTerminate() {
|
||||
wm.State = domain.SessionStateTerminated
|
||||
}
|
||||
|
||||
func (wm *SessionWriteModel) Start(ctx context.Context) {
|
||||
wm.commands = append(wm.commands, session.NewAddedEvent(ctx, wm.aggregate))
|
||||
func (wm *SessionWriteModel) Start(ctx context.Context, domain string) {
|
||||
wm.commands = append(wm.commands, session.NewAddedEvent(ctx, wm.aggregate, domain))
|
||||
// set the domain so checks can use it
|
||||
wm.Domain = domain
|
||||
}
|
||||
|
||||
func (wm *SessionWriteModel) UserChecked(ctx context.Context, userID string, checkedAt time.Time) error {
|
||||
|
@@ -43,7 +43,7 @@ func (c *Commands) CreatePasskeyChallenge(userVerification domain.UserVerificati
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
webAuthNLogin, err := c.webauthnConfig.BeginLogin(ctx, humanPasskeys.human, userVerification, humanPasskeys.tokens...)
|
||||
webAuthNLogin, err := c.webauthnConfig.BeginLogin(ctx, humanPasskeys.human, userVerification, cmd.sessionWriteModel.Domain, humanPasskeys.tokens...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -84,7 +84,7 @@ func TestSessionCommands_getHumanPasskeys(t *testing.T) {
|
||||
expectFilter(eventFromEventPusher(
|
||||
user.NewHumanWebAuthNAddedEvent(eventstore.NewBaseEventForPush(
|
||||
context.Background(), &org.NewAggregate("org1").Aggregate, user.HumanPasswordlessTokenAddedType,
|
||||
), "111", "challenge"),
|
||||
), "111", "challenge", "rpID"),
|
||||
)),
|
||||
),
|
||||
sessionWriteModel: &SessionWriteModel{
|
||||
@@ -112,6 +112,7 @@ func TestSessionCommands_getHumanPasskeys(t *testing.T) {
|
||||
WebAuthNTokenID: "111",
|
||||
State: domain.MFAStateNotReady,
|
||||
Challenge: "challenge",
|
||||
RPID: "rpID",
|
||||
}},
|
||||
},
|
||||
err: nil,
|
||||
|
@@ -147,6 +147,7 @@ func TestCommands_CreateSession(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
checks []SessionCommand
|
||||
domain string
|
||||
metadata map[string][]byte
|
||||
}
|
||||
type res struct {
|
||||
@@ -194,7 +195,7 @@ func TestCommands_CreateSession(t *testing.T) {
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
eventPusherToEvents(
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate),
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate, ""),
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"tokenID",
|
||||
),
|
||||
@@ -218,6 +219,39 @@ func TestCommands_CreateSession(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"empty session with domain",
|
||||
fields{
|
||||
idGenerator: mock.NewIDGeneratorExpectIDs(t, "sessionID"),
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
eventPusherToEvents(
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate, "domain.tld"),
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"tokenID",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenCreator: func(sessionID string) (string, string, error) {
|
||||
return "tokenID",
|
||||
"token",
|
||||
nil
|
||||
},
|
||||
},
|
||||
args{
|
||||
ctx: authz.NewMockContext("", "org1", ""),
|
||||
domain: "domain.tld",
|
||||
},
|
||||
res{
|
||||
want: &SessionChanged{
|
||||
ObjectDetails: &domain.ObjectDetails{ResourceOwner: "org1"},
|
||||
ID: "sessionID",
|
||||
NewToken: "token",
|
||||
},
|
||||
},
|
||||
},
|
||||
// the rest is tested in the Test_updateSession
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@@ -227,7 +261,7 @@ func TestCommands_CreateSession(t *testing.T) {
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
sessionTokenCreator: tt.fields.tokenCreator,
|
||||
}
|
||||
got, err := c.CreateSession(tt.args.ctx, tt.args.checks, tt.args.metadata)
|
||||
got, err := c.CreateSession(tt.args.ctx, tt.args.checks, tt.args.domain, tt.args.metadata)
|
||||
require.ErrorIs(t, err, tt.res.err)
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
})
|
||||
@@ -276,7 +310,7 @@ func TestCommands_UpdateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate, "domain.tld")),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"tokenID")),
|
||||
@@ -301,7 +335,7 @@ func TestCommands_UpdateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate, "domain.tld")),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"tokenID")),
|
||||
@@ -739,7 +773,7 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate, "domain.tld")),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"tokenID")),
|
||||
@@ -764,7 +798,7 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate, "domain.tld")),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"tokenID")),
|
||||
@@ -793,7 +827,7 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate, "domain.tld")),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"tokenID"),
|
||||
@@ -824,7 +858,7 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
|
||||
session.NewAddedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate, "domain.tld")),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"tokenID"),
|
||||
|
@@ -140,6 +140,7 @@ func writeModelToWebAuthN(wm *HumanWebAuthNWriteModel) *domain.WebAuthNToken {
|
||||
SignCount: wm.SignCount,
|
||||
WebAuthNTokenName: wm.WebAuthNTokenName,
|
||||
State: wm.State,
|
||||
RPID: wm.RPID,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -27,8 +27,8 @@ func (c *Commands) getHumanU2FTokens(ctx context.Context, userID, resourceowner
|
||||
return readModelToU2FTokens(tokenReadModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) getHumanPasswordlessTokens(ctx context.Context, userID, resourceowner string) ([]*domain.WebAuthNToken, error) {
|
||||
tokenReadModel := NewHumanPasswordlessTokensReadModel(userID, resourceowner)
|
||||
func (c *Commands) getHumanPasswordlessTokens(ctx context.Context, userID, resourceOwner string) ([]*domain.WebAuthNToken, error) {
|
||||
tokenReadModel := NewHumanPasswordlessTokensReadModel(userID, resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, tokenReadModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -82,12 +82,12 @@ func (c *Commands) HumanAddU2FSetup(ctx context.Context, userID, resourceowner s
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addWebAuthN, userAgg, webAuthN, err := c.addHumanWebAuthN(ctx, userID, resourceowner, isLoginUI, u2fTokens, domain.AuthenticatorAttachmentUnspecified, domain.UserVerificationRequirementDiscouraged)
|
||||
addWebAuthN, userAgg, webAuthN, err := c.addHumanWebAuthN(ctx, userID, resourceowner, "", u2fTokens, domain.AuthenticatorAttachmentUnspecified, domain.UserVerificationRequirementDiscouraged)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
events, err := c.eventstore.Push(ctx, usr_repo.NewHumanU2FAddedEvent(ctx, userAgg, addWebAuthN.WebauthNTokenID, webAuthN.Challenge))
|
||||
events, err := c.eventstore.Push(ctx, usr_repo.NewHumanU2FAddedEvent(ctx, userAgg, addWebAuthN.WebauthNTokenID, webAuthN.Challenge, ""))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -108,12 +108,12 @@ func (c *Commands) HumanAddPasswordlessSetup(ctx context.Context, userID, resour
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addWebAuthN, userAgg, webAuthN, err := c.addHumanWebAuthN(ctx, userID, resourceowner, isLoginUI, passwordlessTokens, authenticatorPlatform, domain.UserVerificationRequirementRequired)
|
||||
addWebAuthN, userAgg, webAuthN, err := c.addHumanWebAuthN(ctx, userID, resourceowner, "", passwordlessTokens, authenticatorPlatform, domain.UserVerificationRequirementRequired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
events, err := c.eventstore.Push(ctx, usr_repo.NewHumanPasswordlessAddedEvent(ctx, userAgg, addWebAuthN.WebauthNTokenID, webAuthN.Challenge))
|
||||
events, err := c.eventstore.Push(ctx, usr_repo.NewHumanPasswordlessAddedEvent(ctx, userAgg, addWebAuthN.WebauthNTokenID, webAuthN.Challenge, ""))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -137,7 +137,7 @@ func (c *Commands) HumanAddPasswordlessSetupInitCode(ctx context.Context, userID
|
||||
return c.HumanAddPasswordlessSetup(ctx, userID, resourceowner, true, preferredPlatformType)
|
||||
}
|
||||
|
||||
func (c *Commands) addHumanWebAuthN(ctx context.Context, userID, resourceowner string, isLoginUI bool, tokens []*domain.WebAuthNToken, authenticatorPlatform domain.AuthenticatorAttachment, userVerification domain.UserVerificationRequirement) (*HumanWebAuthNWriteModel, *eventstore.Aggregate, *domain.WebAuthNToken, error) {
|
||||
func (c *Commands) addHumanWebAuthN(ctx context.Context, userID, resourceowner, rpID string, tokens []*domain.WebAuthNToken, authenticatorPlatform domain.AuthenticatorAttachment, userVerification domain.UserVerificationRequirement) (*HumanWebAuthNWriteModel, *eventstore.Aggregate, *domain.WebAuthNToken, error) {
|
||||
if userID == "" {
|
||||
return nil, nil, nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-3M0od", "Errors.IDMissing")
|
||||
}
|
||||
@@ -157,7 +157,7 @@ func (c *Commands) addHumanWebAuthN(ctx context.Context, userID, resourceowner s
|
||||
if accountName == "" {
|
||||
accountName = string(user.EmailAddress)
|
||||
}
|
||||
webAuthN, err := c.webauthnConfig.BeginRegistration(ctx, user, accountName, authenticatorPlatform, userVerification, isLoginUI, tokens...)
|
||||
webAuthN, err := c.webauthnConfig.BeginRegistration(ctx, user, accountName, authenticatorPlatform, userVerification, rpID, tokens...)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
@@ -343,7 +343,7 @@ func (c *Commands) beginWebAuthNLogin(ctx context.Context, userID, resourceOwner
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
webAuthNLogin, err := c.webauthnConfig.BeginLogin(ctx, human, userVerification, tokens...)
|
||||
webAuthNLogin, err := c.webauthnConfig.BeginLogin(ctx, human, userVerification, "", tokens...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ type HumanWebAuthNWriteModel struct {
|
||||
AAGUID []byte
|
||||
SignCount uint32
|
||||
WebAuthNTokenName string
|
||||
RPID string
|
||||
|
||||
State domain.MFAState
|
||||
}
|
||||
@@ -113,6 +114,7 @@ func (wm *HumanWebAuthNWriteModel) Reduce() error {
|
||||
func (wm *HumanWebAuthNWriteModel) appendAddedEvent(e *user.HumanWebAuthNAddedEvent) {
|
||||
wm.WebauthNTokenID = e.WebAuthNTokenID
|
||||
wm.Challenge = e.Challenge
|
||||
wm.RPID = e.RPID
|
||||
wm.State = domain.MFAStateNotReady
|
||||
}
|
||||
|
||||
|
@@ -16,22 +16,22 @@ import (
|
||||
|
||||
// RegisterUserPasskey creates a passkey registration for the current authenticated user.
|
||||
// UserID, usually taken from the request is compared against the user ID in the context.
|
||||
func (c *Commands) RegisterUserPasskey(ctx context.Context, userID, resourceOwner string, authenticator domain.AuthenticatorAttachment) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
func (c *Commands) RegisterUserPasskey(ctx context.Context, userID, resourceOwner, rpID string, authenticator domain.AuthenticatorAttachment) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
if err := authz.UserIDInCTX(ctx, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.registerUserPasskey(ctx, userID, resourceOwner, authenticator)
|
||||
return c.registerUserPasskey(ctx, userID, resourceOwner, rpID, authenticator)
|
||||
}
|
||||
|
||||
// RegisterUserPasskeyWithCode registers a new passkey for a unauthenticated user id.
|
||||
// The resource is protected by the code, identified by the codeID.
|
||||
func (c *Commands) RegisterUserPasskeyWithCode(ctx context.Context, userID, resourceOwner string, authenticator domain.AuthenticatorAttachment, codeID, code string, alg crypto.EncryptionAlgorithm) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
func (c *Commands) RegisterUserPasskeyWithCode(ctx context.Context, userID, resourceOwner string, authenticator domain.AuthenticatorAttachment, codeID, code, rpID string, alg crypto.EncryptionAlgorithm) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
event, err := c.verifyUserPasskeyCode(ctx, userID, resourceOwner, codeID, code, alg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.registerUserPasskey(ctx, userID, resourceOwner, authenticator, event)
|
||||
return c.registerUserPasskey(ctx, userID, resourceOwner, rpID, authenticator, event)
|
||||
}
|
||||
|
||||
type eventCallback func(context.Context, *eventstore.Aggregate) eventstore.Command
|
||||
@@ -63,25 +63,25 @@ func (c *Commands) verifyUserPasskeyCodeFailed(ctx context.Context, wm *HumanPas
|
||||
logging.WithFields("userID", userAgg.ID).OnError(err).Error("RegisterUserPasskeyWithCode push failed")
|
||||
}
|
||||
|
||||
func (c *Commands) registerUserPasskey(ctx context.Context, userID, resourceOwner string, authenticator domain.AuthenticatorAttachment, events ...eventCallback) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
wm, userAgg, webAuthN, err := c.createUserPasskey(ctx, userID, resourceOwner, authenticator)
|
||||
func (c *Commands) registerUserPasskey(ctx context.Context, userID, resourceOwner, rpID string, authenticator domain.AuthenticatorAttachment, events ...eventCallback) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
wm, userAgg, webAuthN, err := c.createUserPasskey(ctx, userID, resourceOwner, rpID, authenticator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.pushUserPasskey(ctx, wm, userAgg, webAuthN, events...)
|
||||
}
|
||||
|
||||
func (c *Commands) createUserPasskey(ctx context.Context, userID, resourceOwner string, authenticator domain.AuthenticatorAttachment) (*HumanWebAuthNWriteModel, *eventstore.Aggregate, *domain.WebAuthNToken, error) {
|
||||
func (c *Commands) createUserPasskey(ctx context.Context, userID, resourceOwner, rpID string, authenticator domain.AuthenticatorAttachment) (*HumanWebAuthNWriteModel, *eventstore.Aggregate, *domain.WebAuthNToken, error) {
|
||||
passwordlessTokens, err := c.getHumanPasswordlessTokens(ctx, userID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return c.addHumanWebAuthN(ctx, userID, resourceOwner, false, passwordlessTokens, authenticator, domain.UserVerificationRequirementRequired)
|
||||
return c.addHumanWebAuthN(ctx, userID, resourceOwner, rpID, passwordlessTokens, authenticator, domain.UserVerificationRequirementRequired)
|
||||
}
|
||||
|
||||
func (c *Commands) pushUserPasskey(ctx context.Context, wm *HumanWebAuthNWriteModel, userAgg *eventstore.Aggregate, webAuthN *domain.WebAuthNToken, events ...eventCallback) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
cmds := make([]eventstore.Command, len(events)+1)
|
||||
cmds[0] = user.NewHumanPasswordlessAddedEvent(ctx, userAgg, wm.WebauthNTokenID, webAuthN.Challenge)
|
||||
cmds[0] = user.NewHumanPasswordlessAddedEvent(ctx, userAgg, wm.WebauthNTokenID, webAuthN.Challenge, webAuthN.RPID)
|
||||
for i, event := range events {
|
||||
cmds[i+1] = event(ctx, userAgg)
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ func TestCommands_RegisterUserPasskey(t *testing.T) {
|
||||
type args struct {
|
||||
userID string
|
||||
resourceOwner string
|
||||
rpID string
|
||||
authenticator domain.AuthenticatorAttachment
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -121,7 +122,7 @@ func TestCommands_RegisterUserPasskey(t *testing.T) {
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
webauthnConfig: webauthnConfig,
|
||||
}
|
||||
_, err := c.RegisterUserPasskey(ctx, tt.args.userID, tt.args.resourceOwner, tt.args.authenticator)
|
||||
_, err := c.RegisterUserPasskey(ctx, tt.args.userID, tt.args.resourceOwner, tt.args.rpID, tt.args.authenticator)
|
||||
require.ErrorIs(t, err, tt.wantErr)
|
||||
// successful case can't be tested due to random challenge.
|
||||
})
|
||||
@@ -148,6 +149,7 @@ func TestCommands_RegisterUserPasskeyWithCode(t *testing.T) {
|
||||
type args struct {
|
||||
userID string
|
||||
resourceOwner string
|
||||
rpID string
|
||||
authenticator domain.AuthenticatorAttachment
|
||||
codeID string
|
||||
code string
|
||||
@@ -222,7 +224,7 @@ func TestCommands_RegisterUserPasskeyWithCode(t *testing.T) {
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
webauthnConfig: webauthnConfig,
|
||||
}
|
||||
_, err := c.RegisterUserPasskeyWithCode(ctx, tt.args.userID, tt.args.resourceOwner, tt.args.authenticator, tt.args.codeID, tt.args.code, alg)
|
||||
_, err := c.RegisterUserPasskeyWithCode(ctx, tt.args.userID, tt.args.resourceOwner, tt.args.authenticator, tt.args.codeID, tt.args.code, tt.args.rpID, alg)
|
||||
require.ErrorIs(t, err, tt.wantErr)
|
||||
// successful case can't be tested due to random challenge.
|
||||
})
|
||||
@@ -376,7 +378,7 @@ func TestCommands_pushUserPasskey(t *testing.T) {
|
||||
expectFilter(eventFromEventPusher(
|
||||
user.NewHumanWebAuthNAddedEvent(eventstore.NewBaseEventForPush(
|
||||
ctx, &org.NewAggregate("org1").Aggregate, user.HumanPasswordlessTokenAddedType,
|
||||
), "111", "challenge"),
|
||||
), "111", "challenge", "rpID"),
|
||||
)),
|
||||
}
|
||||
|
||||
@@ -394,7 +396,7 @@ func TestCommands_pushUserPasskey(t *testing.T) {
|
||||
expectPush: func(challenge string) expect {
|
||||
return expectPushFailed(io.ErrClosedPipe, []*repository.Event{eventFromEventPusher(
|
||||
user.NewHumanPasswordlessAddedEvent(ctx,
|
||||
userAgg, "123", challenge,
|
||||
userAgg, "123", challenge, "rpID",
|
||||
),
|
||||
)})
|
||||
},
|
||||
@@ -406,7 +408,7 @@ func TestCommands_pushUserPasskey(t *testing.T) {
|
||||
expectPush: func(challenge string) expect {
|
||||
return expectPush([]*repository.Event{eventFromEventPusher(
|
||||
user.NewHumanPasswordlessAddedEvent(ctx,
|
||||
userAgg, "123", challenge,
|
||||
userAgg, "123", challenge, "rpID",
|
||||
),
|
||||
)})
|
||||
},
|
||||
@@ -418,7 +420,7 @@ func TestCommands_pushUserPasskey(t *testing.T) {
|
||||
return expectPush([]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
user.NewHumanPasswordlessAddedEvent(ctx,
|
||||
userAgg, "123", challenge,
|
||||
userAgg, "123", challenge, "rpID",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -440,7 +442,7 @@ func TestCommands_pushUserPasskey(t *testing.T) {
|
||||
webauthnConfig: webauthnConfig,
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "123"),
|
||||
}
|
||||
wm, userAgg, webAuthN, err := c.createUserPasskey(ctx, "user1", "org1", domain.AuthenticatorAttachmentCrossPlattform)
|
||||
wm, userAgg, webAuthN, err := c.createUserPasskey(ctx, "user1", "org1", "rpID", domain.AuthenticatorAttachmentCrossPlattform)
|
||||
require.NoError(t, err)
|
||||
|
||||
c.eventstore = eventstoreExpect(t, tt.expectPush(webAuthN.Challenge))
|
||||
|
@@ -9,31 +9,31 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
)
|
||||
|
||||
func (c *Commands) RegisterUserU2F(ctx context.Context, userID, resourceOwner string) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
func (c *Commands) RegisterUserU2F(ctx context.Context, userID, resourceOwner, rpID string) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
if err := authz.UserIDInCTX(ctx, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.registerUserU2F(ctx, userID, resourceOwner)
|
||||
return c.registerUserU2F(ctx, userID, resourceOwner, rpID)
|
||||
}
|
||||
|
||||
func (c *Commands) registerUserU2F(ctx context.Context, userID, resourceOwner string) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
wm, userAgg, webAuthN, err := c.createUserU2F(ctx, userID, resourceOwner)
|
||||
func (c *Commands) registerUserU2F(ctx context.Context, userID, resourceOwner, rpID string) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
wm, userAgg, webAuthN, err := c.createUserU2F(ctx, userID, resourceOwner, rpID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.pushUserU2F(ctx, wm, userAgg, webAuthN)
|
||||
}
|
||||
|
||||
func (c *Commands) createUserU2F(ctx context.Context, userID, resourceOwner string) (*HumanWebAuthNWriteModel, *eventstore.Aggregate, *domain.WebAuthNToken, error) {
|
||||
func (c *Commands) createUserU2F(ctx context.Context, userID, resourceOwner, rpID string) (*HumanWebAuthNWriteModel, *eventstore.Aggregate, *domain.WebAuthNToken, error) {
|
||||
tokens, err := c.getHumanU2FTokens(ctx, userID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return c.addHumanWebAuthN(ctx, userID, resourceOwner, false, tokens, domain.AuthenticatorAttachmentUnspecified, domain.UserVerificationRequirementRequired)
|
||||
return c.addHumanWebAuthN(ctx, userID, resourceOwner, rpID, tokens, domain.AuthenticatorAttachmentUnspecified, domain.UserVerificationRequirementRequired)
|
||||
}
|
||||
|
||||
func (c *Commands) pushUserU2F(ctx context.Context, wm *HumanWebAuthNWriteModel, userAgg *eventstore.Aggregate, webAuthN *domain.WebAuthNToken) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
cmd := user.NewHumanU2FAddedEvent(ctx, userAgg, wm.WebauthNTokenID, webAuthN.Challenge)
|
||||
cmd := user.NewHumanU2FAddedEvent(ctx, userAgg, wm.WebauthNTokenID, webAuthN.Challenge, webAuthN.RPID)
|
||||
err := c.pushAppendAndReduce(ctx, wm, cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -37,6 +37,7 @@ func TestCommands_RegisterUserU2F(t *testing.T) {
|
||||
type args struct {
|
||||
userID string
|
||||
resourceOwner string
|
||||
rpID string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -114,7 +115,7 @@ func TestCommands_RegisterUserU2F(t *testing.T) {
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
webauthnConfig: webauthnConfig,
|
||||
}
|
||||
_, err := c.RegisterUserU2F(ctx, tt.args.userID, tt.args.resourceOwner)
|
||||
_, err := c.RegisterUserU2F(ctx, tt.args.userID, tt.args.resourceOwner, tt.args.rpID)
|
||||
require.ErrorIs(t, err, tt.wantErr)
|
||||
// successful case can't be tested due to random challenge.
|
||||
})
|
||||
@@ -160,7 +161,7 @@ func TestCommands_pushUserU2F(t *testing.T) {
|
||||
expectFilter(eventFromEventPusher(
|
||||
user.NewHumanWebAuthNAddedEvent(eventstore.NewBaseEventForPush(
|
||||
ctx, &org.NewAggregate("org1").Aggregate, user.HumanPasswordlessTokenAddedType,
|
||||
), "111", "challenge"),
|
||||
), "111", "challenge", "rpID"),
|
||||
)),
|
||||
}
|
||||
|
||||
@@ -174,7 +175,7 @@ func TestCommands_pushUserU2F(t *testing.T) {
|
||||
expectPush: func(challenge string) expect {
|
||||
return expectPushFailed(io.ErrClosedPipe, []*repository.Event{eventFromEventPusher(
|
||||
user.NewHumanU2FAddedEvent(ctx,
|
||||
userAgg, "123", challenge,
|
||||
userAgg, "123", challenge, "rpID",
|
||||
),
|
||||
)})
|
||||
},
|
||||
@@ -185,7 +186,7 @@ func TestCommands_pushUserU2F(t *testing.T) {
|
||||
expectPush: func(challenge string) expect {
|
||||
return expectPush([]*repository.Event{eventFromEventPusher(
|
||||
user.NewHumanU2FAddedEvent(ctx,
|
||||
userAgg, "123", challenge,
|
||||
userAgg, "123", challenge, "rpID",
|
||||
),
|
||||
)})
|
||||
},
|
||||
@@ -198,7 +199,7 @@ func TestCommands_pushUserU2F(t *testing.T) {
|
||||
webauthnConfig: webauthnConfig,
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "123"),
|
||||
}
|
||||
wm, userAgg, webAuthN, err := c.createUserPasskey(ctx, "user1", "org1", domain.AuthenticatorAttachmentCrossPlattform)
|
||||
wm, userAgg, webAuthN, err := c.createUserPasskey(ctx, "user1", "org1", "rpID", domain.AuthenticatorAttachmentCrossPlattform)
|
||||
require.NoError(t, err)
|
||||
|
||||
c.eventstore = eventstoreExpect(t, tt.expectPush(webAuthN.Challenge))
|
||||
|
Reference in New Issue
Block a user