mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 23:37:23 +00:00
fix: idp usage (#4571)
* fix: send email verification instead of init code for idp users * fix: select single idp of external only users * fix: use single idp on login
This commit is contained in:
parent
e7bc887a47
commit
3270a94291
@ -16,6 +16,7 @@ import (
|
|||||||
"google.golang.org/protobuf/types/known/durationpb"
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
|
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
action_grpc "github.com/zitadel/zitadel/internal/api/grpc/action"
|
action_grpc "github.com/zitadel/zitadel/internal/api/grpc/action"
|
||||||
"github.com/zitadel/zitadel/internal/api/grpc/management"
|
"github.com/zitadel/zitadel/internal/api/grpc/management"
|
||||||
@ -306,6 +307,10 @@ func (s *Server) importData(ctx context.Context, orgs []*admin_pb.DataOrg) (*adm
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
emailCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyEmailCode, s.userCodeAlg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.userCodeAlg)
|
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.userCodeAlg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -521,7 +526,7 @@ func (s *Server) importData(ctx context.Context, orgs []*admin_pb.DataOrg) (*adm
|
|||||||
logging.Debugf("import user: %s", user.GetUserId())
|
logging.Debugf("import user: %s", user.GetUserId())
|
||||||
human, passwordless := management.ImportHumanUserRequestToDomain(user.User)
|
human, passwordless := management.ImportHumanUserRequestToDomain(user.User)
|
||||||
human.AggregateID = user.UserId
|
human.AggregateID = user.UserId
|
||||||
_, _, err := s.command.ImportHuman(ctx, org.GetOrgId(), human, passwordless, initCodeGenerator, phoneCodeGenerator, passwordlessInitCode)
|
_, _, err := s.command.ImportHuman(ctx, org.GetOrgId(), human, passwordless, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessInitCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors = append(errors, &admin_pb.ImportDataError{Type: "human_user", Id: user.GetUserId(), Message: err.Error()})
|
errors = append(errors, &admin_pb.ImportDataError{Type: "human_user", Id: user.GetUserId(), Message: err.Error()})
|
||||||
if isCtxTimeout(ctx) {
|
if isCtxTimeout(ctx) {
|
||||||
|
@ -235,6 +235,10 @@ func (s *Server) ImportHumanUser(ctx context.Context, req *mgmt_pb.ImportHumanUs
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
emailCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyEmailCode, s.userCodeAlg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.userCodeAlg)
|
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.userCodeAlg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -243,7 +247,7 @@ func (s *Server) ImportHumanUser(ctx context.Context, req *mgmt_pb.ImportHumanUs
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
addedHuman, code, err := s.command.ImportHuman(ctx, authz.GetCtxData(ctx).OrgID, human, passwordless, initCodeGenerator, phoneCodeGenerator, passwordlessInitCode)
|
addedHuman, code, err := s.command.ImportHuman(ctx, authz.GetCtxData(ctx).OrgID, human, passwordless, initCodeGenerator, phoneCodeGenerator, emailCodeGenerator, passwordlessInitCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -155,12 +155,17 @@ func (l *Login) registerExternalUser(w http.ResponseWriter, r *http.Request, aut
|
|||||||
l.renderRegisterOption(w, r, authReq, err)
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
emailCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyEmailCode, l.userCodeAlg)
|
||||||
|
if err != nil {
|
||||||
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
phoneCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyPhoneCode, l.userCodeAlg)
|
phoneCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyPhoneCode, l.userCodeAlg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegisterOption(w, r, authReq, err)
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, user, externalIDP, nil, initCodeGenerator, phoneCodeGenerator)
|
_, err = l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, user, externalIDP, nil, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegisterOption(w, r, authReq, err)
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
@ -230,12 +235,17 @@ func (l *Login) handleExternalRegisterCheck(w http.ResponseWriter, r *http.Reque
|
|||||||
l.renderRegisterOption(w, r, authReq, err)
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
emailCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyEmailCode, l.userCodeAlg)
|
||||||
|
if err != nil {
|
||||||
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
phoneCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyPhoneCode, l.userCodeAlg)
|
phoneCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyPhoneCode, l.userCodeAlg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegisterOption(w, r, authReq, err)
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, user, externalIDP, nil, initCodeGenerator, phoneCodeGenerator)
|
_, err = l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, user, externalIDP, nil, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegisterOption(w, r, authReq, err)
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
|
@ -95,6 +95,10 @@ func (l *Login) renderLogin(w http.ResponseWriter, r *http.Request, authReq *dom
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
errID, errMessage = l.getErrorMessage(r, err)
|
errID, errMessage = l.getErrorMessage(r, err)
|
||||||
}
|
}
|
||||||
|
if singleIDPAllowed(authReq) {
|
||||||
|
l.handleIDP(w, r, authReq, authReq.AllowedExternalIDPs[0].IDPConfigID)
|
||||||
|
return
|
||||||
|
}
|
||||||
data := l.getUserData(r, authReq, "Login", errID, errMessage)
|
data := l.getUserData(r, authReq, "Login", errID, errMessage)
|
||||||
funcs := map[string]interface{}{
|
funcs := map[string]interface{}{
|
||||||
"hasUsernamePasswordLogin": func() bool {
|
"hasUsernamePasswordLogin": func() bool {
|
||||||
@ -109,3 +113,7 @@ func (l *Login) renderLogin(w http.ResponseWriter, r *http.Request, authReq *dom
|
|||||||
}
|
}
|
||||||
l.renderer.RenderTemplate(w, r, l.getTranslator(r.Context(), authReq), l.renderer.Templates[tmplLogin], data, funcs)
|
l.renderer.RenderTemplate(w, r, l.getTranslator(r.Context(), authReq), l.renderer.Templates[tmplLogin], data, funcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func singleIDPAllowed(authReq *domain.AuthRequest) bool {
|
||||||
|
return authReq != nil && authReq.LoginPolicy != nil && !authReq.LoginPolicy.AllowUsernamePassword && authReq.LoginPolicy.AllowExternalIDP && len(authReq.AllowedExternalIDPs) == 1
|
||||||
|
}
|
||||||
|
@ -73,12 +73,17 @@ func (l *Login) handleRegisterCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
l.renderRegister(w, r, authRequest, data, err)
|
l.renderRegister(w, r, authRequest, data, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
emailCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyEmailCode, l.userCodeAlg)
|
||||||
|
if err != nil {
|
||||||
|
l.renderRegister(w, r, authRequest, data, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
phoneCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyPhoneCode, l.userCodeAlg)
|
phoneCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyPhoneCode, l.userCodeAlg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegister(w, r, authRequest, data, err)
|
l.renderRegister(w, r, authRequest, data, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, err := l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, data.toHumanDomain(), nil, nil, initCodeGenerator, phoneCodeGenerator)
|
user, err := l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, data.toHumanDomain(), nil, nil, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegister(w, r, authRequest, data, err)
|
l.renderRegister(w, r, authRequest, data, err)
|
||||||
return
|
return
|
||||||
|
@ -48,6 +48,7 @@ type AuthRequestRepo struct {
|
|||||||
LockoutPolicyViewProvider lockoutPolicyViewProvider
|
LockoutPolicyViewProvider lockoutPolicyViewProvider
|
||||||
PrivacyPolicyProvider privacyPolicyProvider
|
PrivacyPolicyProvider privacyPolicyProvider
|
||||||
IDPProviderViewProvider idpProviderViewProvider
|
IDPProviderViewProvider idpProviderViewProvider
|
||||||
|
IDPUserLinksProvider idpUserLinksProvider
|
||||||
UserGrantProvider userGrantProvider
|
UserGrantProvider userGrantProvider
|
||||||
ProjectProvider projectProvider
|
ProjectProvider projectProvider
|
||||||
ApplicationProvider applicationProvider
|
ApplicationProvider applicationProvider
|
||||||
@ -83,6 +84,10 @@ type idpProviderViewProvider interface {
|
|||||||
IDPProvidersByAggregateIDAndState(string, string, iam_model.IDPConfigState) ([]*iam_view_model.IDPProviderView, error)
|
IDPProvidersByAggregateIDAndState(string, string, iam_model.IDPConfigState) ([]*iam_view_model.IDPProviderView, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type idpUserLinksProvider interface {
|
||||||
|
IDPUserLinks(ctx context.Context, queries *query.IDPUserLinksSearchQuery) (*query.IDPUserLinks, error)
|
||||||
|
}
|
||||||
|
|
||||||
type userEventProvider interface {
|
type userEventProvider interface {
|
||||||
UserEventsByID(ctx context.Context, id string, sequence uint64) ([]*es_models.Event, error)
|
UserEventsByID(ctx context.Context, id string, sequence uint64) ([]*es_models.Event, error)
|
||||||
}
|
}
|
||||||
@ -469,11 +474,15 @@ func (repo *AuthRequestRepo) AutoRegisterExternalUser(ctx context.Context, regis
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
emailCodeGenerator, err := repo.Query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyEmailCode, repo.UserCodeAlg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
phoneCodeGenerator, err := repo.Query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, repo.UserCodeAlg)
|
phoneCodeGenerator, err := repo.Query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, repo.UserCodeAlg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
human, err := repo.Command.RegisterHuman(ctx, resourceOwner, registerUser, externalIDP, orgMemberRoles, initCodeGenerator, phoneCodeGenerator)
|
human, err := repo.Command.RegisterHuman(ctx, resourceOwner, registerUser, externalIDP, orgMemberRoles, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -909,11 +918,18 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *domain.Auth
|
|||||||
}
|
}
|
||||||
|
|
||||||
isInternalLogin := request.SelectedIDPConfigID == "" && userSession.SelectedIDPConfigID == ""
|
isInternalLogin := request.SelectedIDPConfigID == "" && userSession.SelectedIDPConfigID == ""
|
||||||
if !isInternalLogin && len(request.LinkingUsers) == 0 && !checkVerificationTimeMaxAge(userSession.ExternalLoginVerification, request.LoginPolicy.ExternalLoginCheckLifetime, request) {
|
idps, err := checkExternalIDPsOfUser(ctx, repo.IDPUserLinksProvider, user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if (!isInternalLogin || len(idps.Links) > 0) && len(request.LinkingUsers) == 0 && !checkVerificationTimeMaxAge(userSession.ExternalLoginVerification, request.LoginPolicy.ExternalLoginCheckLifetime, request) {
|
||||||
selectedIDPConfigID := request.SelectedIDPConfigID
|
selectedIDPConfigID := request.SelectedIDPConfigID
|
||||||
if selectedIDPConfigID == "" {
|
if selectedIDPConfigID == "" {
|
||||||
selectedIDPConfigID = userSession.SelectedIDPConfigID
|
selectedIDPConfigID = userSession.SelectedIDPConfigID
|
||||||
}
|
}
|
||||||
|
if selectedIDPConfigID == "" {
|
||||||
|
selectedIDPConfigID = idps.Links[0].IDPID
|
||||||
|
}
|
||||||
return append(steps, &domain.ExternalLoginStep{SelectedIDPConfigID: selectedIDPConfigID}), nil
|
return append(steps, &domain.ExternalLoginStep{SelectedIDPConfigID: selectedIDPConfigID}), nil
|
||||||
}
|
}
|
||||||
if isInternalLogin || (!isInternalLogin && len(request.LinkingUsers) > 0) {
|
if isInternalLogin || (!isInternalLogin && len(request.LinkingUsers) > 0) {
|
||||||
@ -976,6 +992,14 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *domain.Auth
|
|||||||
return append(steps, &domain.RedirectToCallbackStep{}), nil
|
return append(steps, &domain.RedirectToCallbackStep{}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkExternalIDPsOfUser(ctx context.Context, idpUserLinksProvider idpUserLinksProvider, userID string) (*query.IDPUserLinks, error) {
|
||||||
|
userIDQuery, err := query.NewIDPUserLinksUserIDSearchQuery(userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return idpUserLinksProvider.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: []query.SearchQuery{userIDQuery}})
|
||||||
|
}
|
||||||
|
|
||||||
func (repo *AuthRequestRepo) usersForUserSelection(request *domain.AuthRequest) ([]domain.UserSelection, error) {
|
func (repo *AuthRequestRepo) usersForUserSelection(request *domain.AuthRequest) ([]domain.UserSelection, error) {
|
||||||
userSessions, err := userSessionsByUserAgentID(repo.UserSessionViewProvider, request.AgentID, request.InstanceID)
|
userSessions, err := userSessionsByUserAgentID(repo.UserSessionViewProvider, request.AgentID, request.InstanceID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -234,6 +234,14 @@ func (m *mockApp) AppByOIDCClientID(ctx context.Context, id string) (*query.App,
|
|||||||
return nil, errors.ThrowNotFound(nil, "ERROR", "error")
|
return nil, errors.ThrowNotFound(nil, "ERROR", "error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mockIDPUserLinks struct {
|
||||||
|
idps []*query.IDPUserLink
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockIDPUserLinks) IDPUserLinks(ctx context.Context, queries *query.IDPUserLinksSearchQuery) (*query.IDPUserLinks, error) {
|
||||||
|
return &query.IDPUserLinks{Links: m.idps}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
AuthRequests *cache.AuthRequestCache
|
AuthRequests *cache.AuthRequestCache
|
||||||
@ -247,6 +255,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
applicationProvider applicationProvider
|
applicationProvider applicationProvider
|
||||||
loginPolicyProvider loginPolicyViewProvider
|
loginPolicyProvider loginPolicyViewProvider
|
||||||
lockoutPolicyProvider lockoutPolicyViewProvider
|
lockoutPolicyProvider lockoutPolicyViewProvider
|
||||||
|
idpUserLinksProvider idpUserLinksProvider
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
request *domain.AuthRequest
|
request *domain.AuthRequest
|
||||||
@ -498,6 +507,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
||||||
[]domain.NextStep{&domain.PasswordStep{}},
|
[]domain.NextStep{&domain.PasswordStep{}},
|
||||||
@ -515,6 +525,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
||||||
nil,
|
nil,
|
||||||
@ -535,6 +546,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
||||||
[]domain.NextStep{&domain.InitUserStep{
|
[]domain.NextStep{&domain.InitUserStep{
|
||||||
@ -561,6 +573,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
MultiFactorCheckLifetime: 10 * time.Hour,
|
MultiFactorCheckLifetime: 10 * time.Hour,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{PasswordlessType: domain.PasswordlessTypeAllowed}}, false},
|
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{PasswordlessType: domain.PasswordlessTypeAllowed}}, false},
|
||||||
[]domain.NextStep{&domain.PasswordlessRegistrationPromptStep{}},
|
[]domain.NextStep{&domain.PasswordlessRegistrationPromptStep{}},
|
||||||
@ -585,6 +598,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
MultiFactorCheckLifetime: 10 * time.Hour,
|
MultiFactorCheckLifetime: 10 * time.Hour,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{PasswordlessType: domain.PasswordlessTypeAllowed}}, false},
|
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{PasswordlessType: domain.PasswordlessTypeAllowed}}, false},
|
||||||
[]domain.NextStep{&domain.PasswordlessStep{}},
|
[]domain.NextStep{&domain.PasswordlessStep{}},
|
||||||
@ -610,6 +624,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
MultiFactorCheckLifetime: 10 * time.Hour,
|
MultiFactorCheckLifetime: 10 * time.Hour,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{PasswordlessType: domain.PasswordlessTypeAllowed}}, false},
|
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{PasswordlessType: domain.PasswordlessTypeAllowed}}, false},
|
||||||
[]domain.NextStep{&domain.PasswordlessStep{PasswordSet: true}},
|
[]domain.NextStep{&domain.PasswordlessStep{PasswordSet: true}},
|
||||||
@ -636,6 +651,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -662,13 +678,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
||||||
[]domain.NextStep{&domain.InitPasswordStep{}},
|
[]domain.NextStep{&domain.InitPasswordStep{}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"external user (no external verification), external login step",
|
"external user (idp selected, no external verification), external login step",
|
||||||
fields{
|
fields{
|
||||||
userSessionViewProvider: &mockViewUserSession{
|
userSessionViewProvider: &mockViewUserSession{
|
||||||
SecondFactorVerification: testNow.Add(-5 * time.Minute),
|
SecondFactorVerification: testNow.Add(-5 * time.Minute),
|
||||||
@ -689,6 +706,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -699,6 +717,40 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
[]domain.NextStep{&domain.ExternalLoginStep{SelectedIDPConfigID: "IDPConfigID"}},
|
[]domain.NextStep{&domain.ExternalLoginStep{SelectedIDPConfigID: "IDPConfigID"}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"external user (only idp available, no external verification), external login step",
|
||||||
|
fields{
|
||||||
|
userSessionViewProvider: &mockViewUserSession{
|
||||||
|
SecondFactorVerification: testNow.Add(-5 * time.Minute),
|
||||||
|
},
|
||||||
|
userViewProvider: &mockViewUser{
|
||||||
|
IsEmailVerified: true,
|
||||||
|
MFAMaxSetUp: int32(domain.MFALevelSecondFactor),
|
||||||
|
},
|
||||||
|
userEventProvider: &mockEventUser{},
|
||||||
|
lockoutPolicyProvider: &mockLockoutPolicy{
|
||||||
|
policy: &query.LockoutPolicy{
|
||||||
|
ShowFailures: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||||
|
loginPolicyProvider: &mockLoginPolicy{
|
||||||
|
policy: &query.LoginPolicy{
|
||||||
|
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{
|
||||||
|
idps: []*query.IDPUserLink{{IDPID: "IDPConfigID"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args{&domain.AuthRequest{
|
||||||
|
UserID: "UserID",
|
||||||
|
LoginPolicy: &domain.LoginPolicy{
|
||||||
|
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||||
|
}}, false},
|
||||||
|
[]domain.NextStep{&domain.ExternalLoginStep{SelectedIDPConfigID: "IDPConfigID"}},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"external user (external verification set), callback",
|
"external user (external verification set), callback",
|
||||||
fields{
|
fields{
|
||||||
@ -720,6 +772,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
&domain.AuthRequest{
|
&domain.AuthRequest{
|
||||||
@ -754,6 +807,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
||||||
[]domain.NextStep{&domain.PasswordStep{}},
|
[]domain.NextStep{&domain.PasswordStep{}},
|
||||||
@ -781,6 +835,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
&domain.AuthRequest{
|
&domain.AuthRequest{
|
||||||
@ -814,6 +869,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
&domain.AuthRequest{
|
&domain.AuthRequest{
|
||||||
@ -847,6 +903,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
&domain.AuthRequest{
|
&domain.AuthRequest{
|
||||||
@ -881,6 +938,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
&domain.AuthRequest{
|
&domain.AuthRequest{
|
||||||
@ -918,6 +976,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
&domain.AuthRequest{
|
&domain.AuthRequest{
|
||||||
@ -949,6 +1008,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -980,6 +1040,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -1014,6 +1075,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -1049,6 +1111,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -1085,6 +1148,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -1123,6 +1187,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -1162,6 +1227,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -1200,6 +1266,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -1239,6 +1306,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{&domain.AuthRequest{
|
args{&domain.AuthRequest{
|
||||||
UserID: "UserID",
|
UserID: "UserID",
|
||||||
@ -1276,6 +1344,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
},
|
},
|
||||||
userEventProvider: &mockEventUser{},
|
userEventProvider: &mockEventUser{},
|
||||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
&domain.AuthRequest{
|
&domain.AuthRequest{
|
||||||
@ -1306,6 +1375,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ShowFailures: true,
|
ShowFailures: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
&domain.AuthRequest{
|
&domain.AuthRequest{
|
||||||
@ -1336,6 +1406,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|||||||
ApplicationProvider: tt.fields.applicationProvider,
|
ApplicationProvider: tt.fields.applicationProvider,
|
||||||
LoginPolicyViewProvider: tt.fields.loginPolicyProvider,
|
LoginPolicyViewProvider: tt.fields.loginPolicyProvider,
|
||||||
LockoutPolicyViewProvider: tt.fields.lockoutPolicyProvider,
|
LockoutPolicyViewProvider: tt.fields.lockoutPolicyProvider,
|
||||||
|
IDPUserLinksProvider: tt.fields.idpUserLinksProvider,
|
||||||
}
|
}
|
||||||
got, err := repo.nextSteps(context.Background(), tt.args.request, tt.args.checkLoggedIn)
|
got, err := repo.nextSteps(context.Background(), tt.args.request, tt.args.checkLoggedIn)
|
||||||
if (err != nil && tt.wantErr == nil) || (tt.wantErr != nil && !tt.wantErr(err)) {
|
if (err != nil && tt.wantErr == nil) || (tt.wantErr != nil && !tt.wantErr(err)) {
|
||||||
|
@ -80,6 +80,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, command *command.Comma
|
|||||||
UserCommandProvider: command,
|
UserCommandProvider: command,
|
||||||
UserEventProvider: &userRepo,
|
UserEventProvider: &userRepo,
|
||||||
IDPProviderViewProvider: view,
|
IDPProviderViewProvider: view,
|
||||||
|
IDPUserLinksProvider: queries,
|
||||||
LockoutPolicyViewProvider: queries,
|
LockoutPolicyViewProvider: queries,
|
||||||
LoginPolicyViewProvider: queries,
|
LoginPolicyViewProvider: queries,
|
||||||
UserGrantProvider: queryView,
|
UserGrantProvider: queryView,
|
||||||
|
@ -272,7 +272,7 @@ func (h *AddHuman) ensureDisplayName() {
|
|||||||
h.DisplayName = h.FirstName + " " + h.LastName
|
h.DisplayName = h.FirstName + " " + h.LastName
|
||||||
}
|
}
|
||||||
|
|
||||||
//shouldAddInitCode returns true for all added Humans which:
|
// shouldAddInitCode returns true for all added Humans which:
|
||||||
// - were not added from an external IDP
|
// - were not added from an external IDP
|
||||||
// - and either:
|
// - and either:
|
||||||
// - have no verified email
|
// - have no verified email
|
||||||
@ -285,7 +285,7 @@ func (h *AddHuman) shouldAddInitCode() bool {
|
|||||||
h.Password == ""
|
h.Password == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.Human, passwordless bool, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator, passwordlessCodeGenerator crypto.Generator) (_ *domain.Human, passwordlessCode *domain.PasswordlessInitCode, err error) {
|
func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.Human, passwordless bool, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessCodeGenerator crypto.Generator) (_ *domain.Human, passwordlessCode *domain.PasswordlessInitCode, err error) {
|
||||||
if orgID == "" {
|
if orgID == "" {
|
||||||
return nil, nil, errors.ThrowInvalidArgument(nil, "COMMAND-5N8fs", "Errors.ResourceOwnerMissing")
|
return nil, nil, errors.ThrowInvalidArgument(nil, "COMMAND-5N8fs", "Errors.ResourceOwnerMissing")
|
||||||
}
|
}
|
||||||
@ -309,7 +309,7 @@ func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
events, addedHuman, addedCode, code, err := c.importHuman(ctx, orgID, human, passwordless, domainPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator, passwordlessCodeGenerator)
|
events, addedHuman, addedCode, code, err := c.importHuman(ctx, orgID, human, passwordless, domainPolicy, pwPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessCodeGenerator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -333,7 +333,7 @@ func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.
|
|||||||
return writeModelToHuman(addedHuman), passwordlessCode, nil
|
return writeModelToHuman(addedHuman), passwordlessCode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) RegisterHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, orgMemberRoles []string, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator) (*domain.Human, error) {
|
func (c *Commands) RegisterHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, orgMemberRoles []string, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator crypto.Generator) (*domain.Human, error) {
|
||||||
if orgID == "" {
|
if orgID == "" {
|
||||||
return nil, errors.ThrowInvalidArgument(nil, "COMMAND-GEdf2", "Errors.ResourceOwnerMissing")
|
return nil, errors.ThrowInvalidArgument(nil, "COMMAND-GEdf2", "Errors.ResourceOwnerMissing")
|
||||||
}
|
}
|
||||||
@ -352,7 +352,7 @@ func (c *Commands) RegisterHuman(ctx context.Context, orgID string, human *domai
|
|||||||
if !loginPolicy.AllowRegister {
|
if !loginPolicy.AllowRegister {
|
||||||
return nil, errors.ThrowPreconditionFailed(err, "COMMAND-SAbr3", "Errors.Org.LoginPolicy.RegistrationNotAllowed")
|
return nil, errors.ThrowPreconditionFailed(err, "COMMAND-SAbr3", "Errors.Org.LoginPolicy.RegistrationNotAllowed")
|
||||||
}
|
}
|
||||||
userEvents, registeredHuman, err := c.registerHuman(ctx, orgID, human, link, domainPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
userEvents, registeredHuman, err := c.registerHuman(ctx, orgID, human, link, domainPolicy, pwPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -386,21 +386,21 @@ func (c *Commands) RegisterHuman(ctx context.Context, orgID string, human *domai
|
|||||||
return writeModelToHuman(registeredHuman), nil
|
return writeModelToHuman(registeredHuman), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) addHuman(ctx context.Context, orgID string, human *domain.Human, domainPolicy *domain.DomainPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator) ([]eventstore.Command, *HumanWriteModel, error) {
|
func (c *Commands) addHuman(ctx context.Context, orgID string, human *domain.Human, domainPolicy *domain.DomainPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator crypto.Generator) ([]eventstore.Command, *HumanWriteModel, error) {
|
||||||
if orgID == "" || !human.IsValid() {
|
if orgID == "" || !human.IsValid() {
|
||||||
return nil, nil, errors.ThrowInvalidArgument(nil, "COMMAND-67Ms8", "Errors.User.Invalid")
|
return nil, nil, errors.ThrowInvalidArgument(nil, "COMMAND-67Ms8", "Errors.User.Invalid")
|
||||||
}
|
}
|
||||||
if human.Password != nil && human.Password.SecretString != "" {
|
if human.Password != nil && human.Password.SecretString != "" {
|
||||||
human.Password.ChangeRequired = true
|
human.Password.ChangeRequired = true
|
||||||
}
|
}
|
||||||
return c.createHuman(ctx, orgID, human, nil, false, false, domainPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
return c.createHuman(ctx, orgID, human, nil, false, false, domainPolicy, pwPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.Human, passwordless bool, domainPolicy *domain.DomainPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator, passwordlessCodeGenerator crypto.Generator) (events []eventstore.Command, humanWriteModel *HumanWriteModel, passwordlessCodeWriteModel *HumanPasswordlessInitCodeWriteModel, code string, err error) {
|
func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.Human, passwordless bool, domainPolicy *domain.DomainPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessCodeGenerator crypto.Generator) (events []eventstore.Command, humanWriteModel *HumanWriteModel, passwordlessCodeWriteModel *HumanPasswordlessInitCodeWriteModel, code string, err error) {
|
||||||
if orgID == "" || !human.IsValid() {
|
if orgID == "" || !human.IsValid() {
|
||||||
return nil, nil, nil, "", errors.ThrowInvalidArgument(nil, "COMMAND-00p2b", "Errors.User.Invalid")
|
return nil, nil, nil, "", errors.ThrowInvalidArgument(nil, "COMMAND-00p2b", "Errors.User.Invalid")
|
||||||
}
|
}
|
||||||
events, humanWriteModel, err = c.createHuman(ctx, orgID, human, nil, false, passwordless, domainPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
events, humanWriteModel, err = c.createHuman(ctx, orgID, human, nil, false, passwordless, domainPolicy, pwPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, "", err
|
return nil, nil, nil, "", err
|
||||||
}
|
}
|
||||||
@ -415,7 +415,7 @@ func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.
|
|||||||
return events, humanWriteModel, passwordlessCodeWriteModel, code, nil
|
return events, humanWriteModel, passwordlessCodeWriteModel, code, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) registerHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, domainPolicy *domain.DomainPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator) ([]eventstore.Command, *HumanWriteModel, error) {
|
func (c *Commands) registerHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, domainPolicy *domain.DomainPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator crypto.Generator) ([]eventstore.Command, *HumanWriteModel, error) {
|
||||||
if human == nil {
|
if human == nil {
|
||||||
return nil, nil, errors.ThrowInvalidArgument(nil, "COMMAND-JKefw", "Errors.User.Invalid")
|
return nil, nil, errors.ThrowInvalidArgument(nil, "COMMAND-JKefw", "Errors.User.Invalid")
|
||||||
}
|
}
|
||||||
@ -428,10 +428,10 @@ func (c *Commands) registerHuman(ctx context.Context, orgID string, human *domai
|
|||||||
if human.Password != nil && human.Password.SecretString != "" {
|
if human.Password != nil && human.Password.SecretString != "" {
|
||||||
human.Password.ChangeRequired = false
|
human.Password.ChangeRequired = false
|
||||||
}
|
}
|
||||||
return c.createHuman(ctx, orgID, human, link, true, false, domainPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
return c.createHuman(ctx, orgID, human, link, true, false, domainPolicy, pwPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, selfregister, passwordless bool, domainPolicy *domain.DomainPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator) (events []eventstore.Command, addedHuman *HumanWriteModel, err error) {
|
func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, selfregister, passwordless bool, domainPolicy *domain.DomainPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator crypto.Generator) (events []eventstore.Command, addedHuman *HumanWriteModel, err error) {
|
||||||
if err := human.CheckDomainPolicy(domainPolicy); err != nil {
|
if err := human.CheckDomainPolicy(domainPolicy); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -490,10 +490,16 @@ func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
events = append(events, user.NewHumanInitialCodeAddedEvent(ctx, userAgg, initCode.Code, initCode.Expiry))
|
events = append(events, user.NewHumanInitialCodeAddedEvent(ctx, userAgg, initCode.Code, initCode.Expiry))
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if human.Email != nil && human.EmailAddress != "" && human.IsEmailVerified {
|
if human.Email != nil && human.EmailAddress != "" && human.IsEmailVerified {
|
||||||
events = append(events, user.NewHumanEmailVerifiedEvent(ctx, userAgg))
|
events = append(events, user.NewHumanEmailVerifiedEvent(ctx, userAgg))
|
||||||
|
} else {
|
||||||
|
emailCode, err := domain.NewEmailCode(emailCodeGenerator)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
events = append(events, user.NewHumanEmailCodeAddedEvent(ctx, userAgg, emailCode.Code, emailCode.Expiry))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if human.Phone != nil && human.PhoneNumber != "" && !human.IsPhoneVerified {
|
if human.Phone != nil && human.PhoneNumber != "" && !human.IsPhoneVerified {
|
||||||
@ -527,7 +533,7 @@ func (c *Commands) HumanSkipMFAInit(ctx context.Context, userID, resourceowner s
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
///TODO: adlerhurst maybe we can simplify createAddHumanEvent and createRegisterHumanEvent
|
// TODO: adlerhurst maybe we can simplify createAddHumanEvent and createRegisterHumanEvent
|
||||||
func createAddHumanEvent(ctx context.Context, aggregate *eventstore.Aggregate, human *domain.Human, userLoginMustBeDomain bool) *user.HumanAddedEvent {
|
func createAddHumanEvent(ctx context.Context, aggregate *eventstore.Aggregate, human *domain.Human, userLoginMustBeDomain bool) *user.HumanAddedEvent {
|
||||||
addEvent := user.NewHumanAddedEvent(
|
addEvent := user.NewHumanAddedEvent(
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -1460,7 +1460,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
|||||||
idGenerator: tt.fields.idGenerator,
|
idGenerator: tt.fields.idGenerator,
|
||||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||||
}
|
}
|
||||||
gotHuman, gotCode, err := r.ImportHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.passwordless, tt.args.secretGenerator, tt.args.secretGenerator, tt.args.secretGenerator)
|
gotHuman, gotCode, err := r.ImportHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.passwordless, tt.args.secretGenerator, tt.args.secretGenerator, tt.args.secretGenerator, tt.args.secretGenerator)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
@ -2487,7 +2487,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
|||||||
idGenerator: tt.fields.idGenerator,
|
idGenerator: tt.fields.idGenerator,
|
||||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||||
}
|
}
|
||||||
got, err := r.RegisterHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.link, tt.args.orgMemberRoles, tt.args.secretGenerator, tt.args.secretGenerator)
|
got, err := r.RegisterHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.link, tt.args.orgMemberRoles, tt.args.secretGenerator, tt.args.secretGenerator, tt.args.secretGenerator)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,10 @@ func (u *Human) HashPasswordIfExisting(policy *PasswordComplexityPolicy, passwor
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *Human) IsInitialState(passwordless, externalIDPs bool) bool {
|
func (u *Human) IsInitialState(passwordless, externalIDPs bool) bool {
|
||||||
return u.Email == nil || !u.IsEmailVerified || !externalIDPs && !passwordless && (u.Password == nil || u.Password.SecretString == "") && (u.HashedPassword == nil || u.HashedPassword.SecretString == "")
|
if externalIDPs {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return u.Email == nil || !u.IsEmailVerified || !passwordless && (u.Password == nil || u.Password.SecretString == "") && (u.HashedPassword == nil || u.HashedPassword.SecretString == "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInitUserCode(generator crypto.Generator) (*InitUserCode, error) {
|
func NewInitUserCode(generator crypto.Generator) (*InitUserCode, error) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user