fix: handle reauth correctly (max_age=0 or prompt=login) (#1870)

* max age

* merge main

* fix when no prompt is set

* fix: update oidc pkg

* fix tests
This commit is contained in:
Livio Amstutz
2021-06-16 10:02:15 +02:00
committed by GitHub
parent 1e1ded440c
commit 4a2ca5a1e8
7 changed files with 86 additions and 48 deletions

View File

@@ -523,7 +523,7 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *domain.Auth
return nil, errors.ThrowInvalidArgument(nil, "EVENT-ds27a", "Errors.Internal")
}
steps := make([]domain.NextStep, 0)
if !checkLoggedIn && request.Prompt == domain.PromptNone {
if !checkLoggedIn && domain.IsPrompt(request.Prompt, domain.PromptNone) {
return append(steps, &domain.RedirectToCallbackStep{}), nil
}
if request.UserID == "" {
@@ -532,15 +532,15 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *domain.Auth
return steps, nil
}
steps = append(steps, new(domain.LoginStep))
if request.Prompt == domain.PromptCreate {
if domain.IsPrompt(request.Prompt, domain.PromptCreate) {
return append(steps, &domain.RegistrationStep{}), nil
}
if request.Prompt == domain.PromptSelectAccount || request.Prompt == domain.PromptUnspecified {
if len(request.Prompt) == 0 || domain.IsPrompt(request.Prompt, domain.PromptSelectAccount) {
users, err := repo.usersForUserSelection(request)
if err != nil {
return nil, err
}
if len(users) > 0 || request.Prompt == domain.PromptSelectAccount {
if len(users) > 0 || domain.IsPrompt(request.Prompt, domain.PromptSelectAccount) {
steps = append(steps, &domain.SelectUserStep{Users: users})
}
}
@@ -557,7 +557,7 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *domain.Auth
}
isInternalLogin := request.SelectedIDPConfigID == "" && userSession.SelectedIDPConfigID == ""
if !isInternalLogin && len(request.LinkingUsers) == 0 && !checkVerificationTime(userSession.ExternalLoginVerification, repo.ExternalLoginCheckLifeTime) {
if !isInternalLogin && len(request.LinkingUsers) == 0 && !checkVerificationTimeMaxAge(userSession.ExternalLoginVerification, repo.ExternalLoginCheckLifeTime, request) {
selectedIDPConfigID := request.SelectedIDPConfigID
if selectedIDPConfigID == "" {
selectedIDPConfigID = userSession.SelectedIDPConfigID
@@ -638,7 +638,7 @@ func (repo *AuthRequestRepo) firstFactorChecked(request *domain.AuthRequest, use
var step domain.NextStep
if request.LoginPolicy.PasswordlessType != domain.PasswordlessTypeNotAllowed && user.IsPasswordlessReady() {
if checkVerificationTime(userSession.PasswordlessVerification, repo.MultiFactorCheckLifeTime) {
if checkVerificationTimeMaxAge(userSession.PasswordlessVerification, repo.MultiFactorCheckLifeTime, request) {
request.AuthTime = userSession.PasswordlessVerification
return nil
}
@@ -649,7 +649,7 @@ func (repo *AuthRequestRepo) firstFactorChecked(request *domain.AuthRequest, use
return &domain.InitPasswordStep{}
}
if checkVerificationTime(userSession.PasswordVerification, repo.PasswordCheckLifeTime) {
if checkVerificationTimeMaxAge(userSession.PasswordVerification, repo.PasswordCheckLifeTime, request) {
request.PasswordVerified = true
request.AuthTime = userSession.PasswordVerification
return nil
@@ -686,14 +686,14 @@ func (repo *AuthRequestRepo) mfaChecked(userSession *user_model.UserSessionView,
}
fallthrough
case domain.MFALevelSecondFactor:
if checkVerificationTime(userSession.SecondFactorVerification, repo.SecondFactorCheckLifeTime) {
if checkVerificationTimeMaxAge(userSession.SecondFactorVerification, repo.SecondFactorCheckLifeTime, request) {
request.MFAsVerified = append(request.MFAsVerified, auth_req_model.MFATypeToDomain(userSession.SecondFactorVerificationType))
request.AuthTime = userSession.SecondFactorVerification
return nil, true, nil
}
fallthrough
case domain.MFALevelMultiFactor:
if checkVerificationTime(userSession.MultiFactorVerification, repo.MultiFactorCheckLifeTime) {
if checkVerificationTimeMaxAge(userSession.MultiFactorVerification, repo.MultiFactorCheckLifeTime, request) {
request.MFAsVerified = append(request.MFAsVerified, auth_req_model.MFATypeToDomain(userSession.MultiFactorVerificationType))
request.AuthTime = userSession.MultiFactorVerification
return nil, true, nil
@@ -765,6 +765,16 @@ func getLoginPolicyIDPProviders(provider idpProviderViewProvider, iamID, orgID s
return iam_es_model.IDPProviderViewsToModel(idpProviders), nil
}
func checkVerificationTimeMaxAge(verificationTime time.Time, lifetime time.Duration, request *domain.AuthRequest) bool {
if !checkVerificationTime(verificationTime, lifetime) {
return false
}
if request.MaxAuthAge == nil {
return true
}
return verificationTime.After(request.CreationDate.Add(-*request.MaxAuthAge))
}
func checkVerificationTime(verificationTime time.Time, lifetime time.Duration) bool {
return verificationTime.Add(lifetime).After(time.Now().UTC())
}

View File

@@ -251,7 +251,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
{
"prompt none and checkLoggedIn false, callback step",
fields{},
args{&domain.AuthRequest{Prompt: domain.PromptNone}, false},
args{&domain.AuthRequest{Prompt: []domain.Prompt{domain.PromptNone}}, false},
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
nil,
},
@@ -278,7 +278,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
fields{
userSessionViewProvider: &mockViewErrUserSession{},
},
args{&domain.AuthRequest{Prompt: domain.PromptSelectAccount}, false},
args{&domain.AuthRequest{Prompt: []domain.Prompt{domain.PromptSelectAccount}}, false},
nil,
errors.IsInternal,
},
@@ -301,7 +301,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userEventProvider: &mockEventUser{},
},
args{&domain.AuthRequest{Prompt: domain.PromptSelectAccount}, false},
args{&domain.AuthRequest{Prompt: []domain.Prompt{domain.PromptSelectAccount}}, false},
[]domain.NextStep{
&domain.LoginStep{},
&domain.SelectUserStep{
@@ -341,7 +341,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userEventProvider: &mockEventUser{},
},
args{&domain.AuthRequest{Prompt: domain.PromptSelectAccount, RequestedOrgID: "orgID1"}, false},
args{&domain.AuthRequest{Prompt: []domain.Prompt{domain.PromptSelectAccount}, RequestedOrgID: "orgID1"}, false},
[]domain.NextStep{
&domain.LoginStep{},
&domain.SelectUserStep{
@@ -370,7 +370,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userEventProvider: &mockEventUser{},
},
args{&domain.AuthRequest{Prompt: domain.PromptSelectAccount}, false},
args{&domain.AuthRequest{Prompt: []domain.Prompt{domain.PromptSelectAccount}}, false},
[]domain.NextStep{
&domain.LoginStep{},
&domain.SelectUserStep{
@@ -848,7 +848,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
args{&domain.AuthRequest{
UserID: "UserID",
Prompt: domain.PromptNone,
Prompt: []domain.Prompt{domain.PromptNone},
Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
@@ -880,7 +880,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
args{&domain.AuthRequest{
UserID: "UserID",
Prompt: domain.PromptNone,
Prompt: []domain.Prompt{domain.PromptNone},
Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
@@ -912,7 +912,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
args{&domain.AuthRequest{
UserID: "UserID",
Prompt: domain.PromptNone,
Prompt: []domain.Prompt{domain.PromptNone},
Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},