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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 86 additions and 48 deletions

8
go.mod
View File

@ -16,7 +16,7 @@ require (
github.com/allegro/bigcache v1.2.1
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc
github.com/caos/logging v0.0.2
github.com/caos/oidc v0.15.2
github.com/caos/oidc v0.15.3
github.com/caos/orbos v1.5.14-0.20210428081839-983ffc569980
github.com/cockroachdb/cockroach-go/v2 v2.1.0
github.com/duo-labs/webauthn v0.0.0-20200714211715-1daaee874e43
@ -24,7 +24,7 @@ require (
github.com/ghodss/yaml v1.0.0
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/mock v1.5.0
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.2
github.com/golang/snappy v0.0.2 // indirect
github.com/gorilla/csrf v1.7.0
@ -71,13 +71,13 @@ require (
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/text v0.3.6
golang.org/x/tools v0.1.0
golang.org/x/tools v0.1.1
google.golang.org/api v0.34.0
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20210406143921-e86de6bf7a46
google.golang.org/grpc v1.36.1
google.golang.org/protobuf v1.26.0
gopkg.in/square/go-jose.v2 v2.5.1
gopkg.in/square/go-jose.v2 v2.6.0
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
gotest.tools v2.2.0+incompatible
k8s.io/api v0.19.2

24
go.sum
View File

@ -138,8 +138,8 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW
github.com/caos/logging v0.0.2 h1:ebg5C/HN0ludYR+WkvnFjwSExF4wvyiWPyWGcKMYsoo=
github.com/caos/logging v0.0.2/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0=
github.com/caos/oidc v0.14.4/go.mod h1:H5Y2zw3YIrWqQOoy0wcmZva2a66bumDyU2iOhXiM9uA=
github.com/caos/oidc v0.15.2 h1:fvR8Mtnv+d0Lw+tmXHS5u8XYpuE2xCNpobPA66rx/9Q=
github.com/caos/oidc v0.15.2/go.mod h1:JiK5RXSOgag66wiSOMEkS+yS4R46Baz6dGwfr60VfvI=
github.com/caos/oidc v0.15.3 h1:DNzzvSgUbhUewrZKOVF9nDop0AfMy0wjnMy/rD9f8xA=
github.com/caos/oidc v0.15.3/go.mod h1:doQ1B/mGnQWbgS+UOANIQCPJe1+KACyxQ8wjV2d11h0=
github.com/caos/orbos v1.5.14-0.20210428081839-983ffc569980 h1:Fz0aYUwGMA2tsu5w7SryqFGjqGClJVHbyhBMT5SXtPU=
github.com/caos/orbos v1.5.14-0.20210428081839-983ffc569980/go.mod h1:2I8oiZb5SMRm/qTLvwpSmdV0M6ex8J/UKyxUGfKaqJo=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
@ -360,8 +360,9 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -930,6 +931,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@ -1046,8 +1048,9 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1097,8 +1100,9 @@ golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201026091529-146b70c837a4/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 h1:b0LrWgu8+q7z4J+0Y3Umo5q1dL7NXBkKBWkaVkAq17E=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190517181255-950ef44c6e07/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1184,8 +1188,10 @@ golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1270,8 +1276,9 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201030143252-cf7a54d06671/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1406,8 +1413,9 @@ gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=

View File

@ -113,6 +113,7 @@ func AuthRequestFromBusiness(authReq *domain.AuthRequest) (_ op.AuthRequest, err
func CreateAuthRequestToBusiness(ctx context.Context, authReq *oidc.AuthRequest, userAgentID, userID string) *domain.AuthRequest {
return &domain.AuthRequest{
CreationDate: time.Now(),
AgentID: userAgentID,
BrowserInfo: ParseBrowserInfoFromContext(ctx),
ApplicationID: authReq.ClientID,
@ -122,7 +123,7 @@ func CreateAuthRequestToBusiness(ctx context.Context, authReq *oidc.AuthRequest,
PossibleLOAs: ACRValuesToBusiness(authReq.ACRValues),
UiLocales: UILocalesToBusiness(authReq.UILocales),
LoginHint: authReq.LoginHint,
MaxAuthAge: authReq.MaxAge,
MaxAuthAge: MaxAgeToBusiness(authReq.MaxAge),
UserID: userID,
Request: &domain.AuthRequestOIDC{
Scopes: authReq.Scopes,
@ -161,21 +162,23 @@ func IpFromContext(ctx context.Context) net.IP {
return net.ParseIP(ipString)
}
func PromptToBusiness(prompt oidc.Prompt) domain.Prompt {
switch prompt {
case oidc.PromptNone:
return domain.PromptNone
case oidc.PromptLogin:
return domain.PromptLogin
case oidc.PromptConsent:
return domain.PromptConsent
case oidc.PromptSelectAccount:
return domain.PromptSelectAccount
case "create": //this prompt is not final yet, so not implemented in oidc lib
return domain.PromptCreate
default:
return domain.PromptUnspecified
func PromptToBusiness(oidcPrompt []string) []domain.Prompt {
prompts := make([]domain.Prompt, len(oidcPrompt))
for _, oidcPrompt := range oidcPrompt {
switch oidcPrompt {
case oidc.PromptNone:
prompts = append(prompts, domain.PromptNone)
case oidc.PromptLogin:
prompts = append(prompts, domain.PromptLogin)
case oidc.PromptConsent:
prompts = append(prompts, domain.PromptConsent)
case oidc.PromptSelectAccount:
prompts = append(prompts, domain.PromptSelectAccount)
case "create": //this prompt is not final yet, so not implemented in oidc lib
prompts = append(prompts, domain.PromptCreate)
}
}
return prompts
}
func ACRValuesToBusiness(values []string) []domain.LevelOfAssurance {
@ -193,6 +196,14 @@ func UILocalesToBusiness(tags []language.Tag) []string {
return locales
}
func MaxAgeToBusiness(maxAge *uint) *time.Duration {
if maxAge == nil {
return nil
}
dur := time.Duration(*maxAge) * time.Second
return &dur
}
func ResponseTypeToBusiness(responseType oidc.ResponseType) domain.OIDCResponseType {
switch responseType {
case oidc.ResponseTypeCode:
@ -291,6 +302,6 @@ func (r *RefreshTokenRequest) GetSubject() string {
return r.UserID
}
func (r *RefreshTokenRequest) SetCurrentScopes(scopes oidc.Scopes) {
func (r *RefreshTokenRequest) SetCurrentScopes(scopes []string) {
r.Scopes = scopes
}

View File

@ -80,7 +80,7 @@ func (o *OPStorage) GetKeyByIDAndIssuer(ctx context.Context, keyID, issuer strin
}, nil
}
func (o *OPStorage) ValidateJWTProfileScopes(ctx context.Context, subject string, scopes oidc.Scopes) (oidc.Scopes, error) {
func (o *OPStorage) ValidateJWTProfileScopes(ctx context.Context, subject string, scopes []string) ([]string, error) {
user, err := o.repo.UserByID(ctx, subject)
if err != nil {
return nil, err

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},

View File

@ -18,11 +18,11 @@ type AuthRequest struct {
ApplicationID string
CallbackURI string
TransferState string
Prompt Prompt
Prompt []Prompt
PossibleLOAs []LevelOfAssurance
UiLocales []string
LoginHint string
MaxAuthAge uint32
MaxAuthAge *time.Duration
Request Request
levelOfAssurance LevelOfAssurance
@ -75,6 +75,15 @@ const (
PromptCreate
)
func IsPrompt(prompt []Prompt, requestedPrompt Prompt) bool {
for _, p := range prompt {
if p == requestedPrompt {
return true
}
}
return false
}
type LevelOfAssurance int
const (