mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-12 02:54:20 +00:00
feat(login): reuse existing session if no prompt is provided and only single session exists (#6272)
* feat: reuse existing session if no prompt is provided and only single session exists * fix tests
This commit is contained in:
parent
782f7ad647
commit
dd480f8a8d
@ -921,11 +921,15 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *domain.Auth
|
||||
steps = append(steps, new(domain.ExternalNotFoundOptionStep))
|
||||
return steps, nil
|
||||
}
|
||||
steps = append(steps, new(domain.LoginStep))
|
||||
if domain.IsPrompt(request.Prompt, domain.PromptCreate) {
|
||||
return append(steps, &domain.RegistrationStep{}), nil
|
||||
}
|
||||
if len(request.Prompt) == 0 || domain.IsPrompt(request.Prompt, domain.PromptSelectAccount) {
|
||||
// if there's a login or consent prompt, but not select account, just return the login step
|
||||
if len(request.Prompt) > 0 && !domain.IsPrompt(request.Prompt, domain.PromptSelectAccount) {
|
||||
return append(steps, new(domain.LoginStep)), nil
|
||||
} else {
|
||||
// if no user was specified, no prompt or select_account was provided,
|
||||
// then check the active user sessions (of the user agent)
|
||||
users, err := repo.usersForUserSelection(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -936,11 +940,19 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *domain.Auth
|
||||
if request.SelectedIDPConfigID != "" {
|
||||
steps = append(steps, &domain.RedirectToExternalIDPStep{})
|
||||
}
|
||||
if len(request.Prompt) == 0 && len(users) > 0 {
|
||||
if len(request.Prompt) == 0 && len(users) == 0 {
|
||||
steps = append(steps, new(domain.LoginStep))
|
||||
}
|
||||
// if no prompt was provided, but there are multiple user sessions, then the user must decide which to use
|
||||
if len(request.Prompt) == 0 && len(users) > 1 {
|
||||
steps = append(steps, &domain.SelectUserStep{Users: users})
|
||||
}
|
||||
if len(steps) > 0 {
|
||||
return steps, nil
|
||||
}
|
||||
// a single user session was found, use that automatically
|
||||
request.UserID = users[0].UserID
|
||||
}
|
||||
return steps, nil
|
||||
}
|
||||
user, err := activeUserByID(ctx, repo.UserViewProvider, repo.UserEventProvider, repo.OrgViewProvider, repo.LockoutPolicyViewProvider, request.UserID, request.LoginPolicy.IgnoreUnknownUsernames)
|
||||
if err != nil {
|
||||
|
@ -296,6 +296,28 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"user not set prompt create, registration step",
|
||||
fields{
|
||||
userSessionViewProvider: &mockViewNoUserSession{},
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
Prompt: []domain.Prompt{domain.PromptCreate},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.RegistrationStep{}},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"user not set, prompts other than select account, create step",
|
||||
fields{
|
||||
userSessionViewProvider: &mockViewNoUserSession{},
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
Prompt: []domain.Prompt{domain.PromptLogin, domain.PromptConsent},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.LoginStep{}},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"user not set no active session, login step",
|
||||
fields{
|
||||
@ -333,7 +355,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
errors.IsInternal,
|
||||
},
|
||||
{
|
||||
"user not set, prompt select account, login and select account steps",
|
||||
"user not set, prompt select account, select account step",
|
||||
fields{
|
||||
userSessionViewProvider: &mockViewUserSession{
|
||||
Users: []mockUser{
|
||||
@ -353,7 +375,6 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
},
|
||||
args{&domain.AuthRequest{Prompt: []domain.Prompt{domain.PromptSelectAccount}}, false},
|
||||
[]domain.NextStep{
|
||||
&domain.LoginStep{},
|
||||
&domain.SelectUserStep{
|
||||
Users: []domain.UserSelection{
|
||||
{
|
||||
@ -373,7 +394,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"user not set, primary domain set, prompt select account, login and select account steps",
|
||||
"user not set, primary domain set, prompt select account, select account step",
|
||||
fields{
|
||||
userSessionViewProvider: &mockViewUserSession{
|
||||
Users: []mockUser{
|
||||
@ -393,7 +414,6 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
},
|
||||
args{&domain.AuthRequest{Prompt: []domain.Prompt{domain.PromptSelectAccount}, RequestedOrgID: "orgID1"}, false},
|
||||
[]domain.NextStep{
|
||||
&domain.LoginStep{},
|
||||
&domain.SelectUserStep{
|
||||
Users: []domain.UserSelection{
|
||||
{
|
||||
@ -407,7 +427,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"user not set, prompt select account, no active session, login and select account steps",
|
||||
"user not set, prompt select account, no active session, select account step",
|
||||
fields{
|
||||
userSessionViewProvider: &mockViewUserSession{
|
||||
Users: nil,
|
||||
@ -416,12 +436,113 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
},
|
||||
args{&domain.AuthRequest{Prompt: []domain.Prompt{domain.PromptSelectAccount}}, false},
|
||||
[]domain.NextStep{
|
||||
&domain.LoginStep{},
|
||||
&domain.SelectUserStep{
|
||||
Users: []domain.UserSelection{},
|
||||
}},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"user not set single active session, callback step",
|
||||
fields{
|
||||
userSessionViewProvider: &mockViewUserSession{
|
||||
PasswordVerification: time.Now().Add(-5 * time.Minute),
|
||||
SecondFactorVerification: time.Now().Add(-5 * time.Minute),
|
||||
Users: []mockUser{
|
||||
{
|
||||
"id1",
|
||||
"loginname1",
|
||||
"orgID1",
|
||||
},
|
||||
},
|
||||
},
|
||||
userViewProvider: &mockViewUser{
|
||||
PasswordSet: true,
|
||||
IsEmailVerified: true,
|
||||
MFAMaxSetUp: int32(domain.MFALevelSecondFactor),
|
||||
},
|
||||
userEventProvider: &mockEventUser{},
|
||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||
userGrantProvider: &mockUserGrants{},
|
||||
projectProvider: &mockProject{},
|
||||
applicationProvider: &mockApp{app: &query.App{OIDCConfig: &query.OIDCApp{AppType: domain.OIDCApplicationTypeWeb}}},
|
||||
lockoutPolicyProvider: &mockLockoutPolicy{
|
||||
policy: &query.LockoutPolicy{
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"user not set multiple active sessions, select account step",
|
||||
fields{
|
||||
userSessionViewProvider: &mockViewUserSession{
|
||||
Users: []mockUser{
|
||||
{
|
||||
"id1",
|
||||
"loginname1",
|
||||
"orgID1",
|
||||
},
|
||||
{
|
||||
"id2",
|
||||
"loginname2",
|
||||
"orgID2",
|
||||
},
|
||||
},
|
||||
},
|
||||
userViewProvider: &mockViewUser{
|
||||
PasswordSet: true,
|
||||
IsEmailVerified: true,
|
||||
MFAMaxSetUp: int32(domain.MFALevelSecondFactor),
|
||||
},
|
||||
userEventProvider: &mockEventUser{},
|
||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||
userGrantProvider: &mockUserGrants{},
|
||||
projectProvider: &mockProject{},
|
||||
applicationProvider: &mockApp{app: &query.App{OIDCConfig: &query.OIDCApp{AppType: domain.OIDCApplicationTypeWeb}}},
|
||||
lockoutPolicyProvider: &mockLockoutPolicy{
|
||||
policy: &query.LockoutPolicy{
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
idpUserLinksProvider: &mockIDPUserLinks{},
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.SelectUserStep{
|
||||
Users: []domain.UserSelection{
|
||||
{
|
||||
UserID: "id1",
|
||||
LoginName: "loginname1",
|
||||
SelectionPossible: true,
|
||||
ResourceOwner: "orgID1",
|
||||
},
|
||||
{
|
||||
UserID: "id2",
|
||||
LoginName: "loginname2",
|
||||
SelectionPossible: true,
|
||||
ResourceOwner: "orgID2",
|
||||
},
|
||||
},
|
||||
}},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"user not found, not found error",
|
||||
fields{
|
||||
|
Loading…
Reference in New Issue
Block a user