fix: show clientid on api clients (#1379)

* fix: show clientid

* Update system-defaults.yaml

* fix: field name for clientId app key json

* fix: mfa verify otp

* fix: mfa verify otp (show error correctly)

* fix: nil pointer in login.html

* fix: check clientID clientSecret for apis correctly (and add missing i18n)

* update oidc pkg

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Max Peintner 2021-03-05 09:01:47 +01:00 committed by GitHub
parent 20c191c289
commit e163ea75cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 98 additions and 45 deletions

View File

@ -15,7 +15,7 @@ SystemDefaults:
IncludeLowerLetters: true
IncludeUpperLetters: true
IncludeDigits: true
IncludeSymbols: true
IncludeSymbols: false
InitializeUserCode:
Length: 6
Expiry: '72h'

View File

@ -70,6 +70,21 @@
</button>
</div>
</div>
<div class="environment" *ngIf="app?.apiConfig?.clientId">
<span class="key">{{'APP.API.INFO.CLIENTID' | translate}}</span>
<div class="environment-row">
<span>{{this.app.apiConfig?.clientId}}</span>
<button color="primary" [disabled]="copiedKey == this.app.apiConfig?.clientId"
[matTooltip]="(copiedKey != this.app.apiConfig?.clientId ? 'USER.PAGES.COPY' : 'USER.PAGES.COPIED' ) | translate"
appCopyToClipboard [valueToCopy]="this.app.apiConfig?.clientId"
(copiedValue)="copiedKey = 'clientId'" mat-icon-button>
<i *ngIf="copiedKey != 'clientId'" class="las la-clipboard"></i>
<i *ngIf="copiedKey == 'clientId'" class="las la-clipboard-check"></i>
</button>
</div>
</div>
<ng-container *ngFor="let environmentV of (environmentMap | keyvalue)">
<div *ngIf="environmentV.value" class="environment">
<span class="key">{{environmentV.key}}</span>

View File

@ -1080,6 +1080,9 @@
}
},
"API": {
"INFO": {
"CLIENTID":"Client Id"
},
"REGENERATESECRET": "Client Secret neu generieren",
"SELECTION":{
"TITLE":"API",

View File

@ -1081,6 +1081,9 @@
}
},
"API": {
"INFO": {
"CLIENTID":"Client Id"
},
"REGENERATESECRET": "Regenerate Client Secret",
"SELECTION":{
"TITLE":"API",

7
go.mod
View File

@ -16,12 +16,12 @@ 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.14.1
github.com/caos/oidc v0.14.3
github.com/caos/orbos v1.5.14-0.20210302165604-744ecfd88280
github.com/cockroachdb/cockroach-go/v2 v2.1.0
github.com/duo-labs/webauthn v0.0.0-20200714211715-1daaee874e43
github.com/envoyproxy/protoc-gen-validate v0.1.0
github.com/ghodss/yaml v1.0.0
github.com/go-git/go-git/v5 v5.2.0 // indirect
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/mock v1.5.0
github.com/golang/protobuf v1.4.3
@ -72,11 +72,10 @@ require (
golang.org/x/tools v0.0.0-20201103235415-b653051172e4
google.golang.org/api v0.34.0
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20201103154000-415bd0cd5df6 // indirect
google.golang.org/genproto v0.0.0-20201103154000-415bd0cd5df6
google.golang.org/grpc v1.34.0
google.golang.org/protobuf v1.25.0
gopkg.in/square/go-jose.v2 v2.5.1
gopkg.in/src-d/go-git.v4 v4.13.1 // indirect
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c
gotest.tools v2.2.0+incompatible
k8s.io/api v0.18.5

20
go.sum
View File

@ -140,17 +140,8 @@ github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a/go.mod h1:9LKiDE2ChuG
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.6.2/go.mod h1:ozoi3b+aY33gzdvjz4w90VZShIHGsmDa0goruuV0arQ=
github.com/caos/oidc v0.14.1 h1:MZ1wKomUnGeOjNWClf3dtcxqSKd2o37WXf0fpshSb0k=
github.com/caos/oidc v0.14.1/go.mod h1:fSLPGlxZhjSMP2LYKZ5QMaM/YYmLHfj/Fce+ji48kYY=
github.com/caos/orbos v1.5.14-0.20210211121904-d3fab469047a h1:UekNGhZhvUWElUCln84NWoq8oS9q3sBXPrCcBd1V3es=
github.com/caos/orbos v1.5.14-0.20210211121904-d3fab469047a/go.mod h1:ZLxNgPuYIlSvr80trezGGUIXng9gY2hHEdky/m0B/P0=
github.com/caos/orbos v1.5.14-0.20210224164007-e69ebe04569f/go.mod h1:hyjRSGFdmfGHjeiFzL/wyuNKiUPVdkP3eY7+H/JXqAU=
github.com/caos/orbos v1.5.14-0.20210224173224-b81c8b95f9f2 h1:9+2PovkAegaGuA/jrKGei83Xv8KMV5zxgwXii8tGGU0=
github.com/caos/orbos v1.5.14-0.20210224173224-b81c8b95f9f2/go.mod h1:hyjRSGFdmfGHjeiFzL/wyuNKiUPVdkP3eY7+H/JXqAU=
github.com/caos/orbos v1.5.14-0.20210225092819-3aca50a91e63 h1:J2DEoA/b8vSys/HmmZsM7DzR7HFbJiqp1GpRRZMkDkE=
github.com/caos/orbos v1.5.14-0.20210225092819-3aca50a91e63/go.mod h1:hyjRSGFdmfGHjeiFzL/wyuNKiUPVdkP3eY7+H/JXqAU=
github.com/caos/orbos v1.5.14-0.20210225130434-5875071139dd h1:7J9K6IQ32qLRhMPqhVcU4OPeexWktgcB+QCW9EXoWxQ=
github.com/caos/orbos v1.5.14-0.20210225130434-5875071139dd/go.mod h1:hyjRSGFdmfGHjeiFzL/wyuNKiUPVdkP3eY7+H/JXqAU=
github.com/caos/oidc v0.14.3 h1:ItpN396oY/lcIG2dm3rAm8Wm5ZM7kJRJ/BUIXn/tHtI=
github.com/caos/oidc v0.14.3/go.mod h1:fSLPGlxZhjSMP2LYKZ5QMaM/YYmLHfj/Fce+ji48kYY=
github.com/caos/orbos v1.5.14-0.20210302165604-744ecfd88280 h1:0c87LbDKLYZdDKhxcODZ+V4rwcz8Fnt7S4DVJG8bL1U=
github.com/caos/orbos v1.5.14-0.20210302165604-744ecfd88280/go.mod h1:hyjRSGFdmfGHjeiFzL/wyuNKiUPVdkP3eY7+H/JXqAU=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
@ -489,7 +480,6 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
@ -722,7 +712,6 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@ -831,7 +820,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
@ -1139,7 +1127,6 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -1307,9 +1294,6 @@ 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/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
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

@ -560,7 +560,7 @@ func addClientKeyFromModel(key *proj_model.ClientKey) *management.AddClientKeyRe
KeyID string `json:"keyId"`
Key string `json:"key"`
AppID string `json:"appId"`
ClientID string `json:"clientID"`
ClientID string `json:"clientId"`
}{
Type: "application",
KeyID: key.KeyID,

View File

@ -110,7 +110,7 @@ func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secr
UserID: oidcCtx,
OrgID: oidcCtx,
})
return o.repo.AuthorizeOIDCApplication(ctx, id, secret)
return o.repo.AuthorizeClientIDSecret(ctx, id, secret)
}
func (o *OPStorage) SetUserinfoFromToken(ctx context.Context, userInfo oidc.UserInfoSetter, tokenID, subject, origin string) (err error) {

View File

@ -8,5 +8,5 @@ import (
type ApplicationRepository interface {
ApplicationByClientID(ctx context.Context, clientID string) (*model.ApplicationView, error)
AuthorizeOIDCApplication(ctx context.Context, clientID, secret string) error
AuthorizeClientIDSecret(ctx context.Context, clientID, secret string) error
}

View File

@ -23,7 +23,7 @@ func (a *ApplicationRepo) ApplicationByClientID(ctx context.Context, clientID st
return proj_view_model.ApplicationViewToModel(app), nil
}
func (a *ApplicationRepo) AuthorizeOIDCApplication(ctx context.Context, clientID, secret string) (err error) {
func (a *ApplicationRepo) AuthorizeClientIDSecret(ctx context.Context, clientID, secret string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
@ -31,5 +31,5 @@ func (a *ApplicationRepo) AuthorizeOIDCApplication(ctx context.Context, clientID
if err != nil {
return err
}
return a.ProjectEvents.VerifyOIDCClientSecret(ctx, app.ProjectID, app.ID, secret)
return a.ProjectEvents.VerifyClientSecret(ctx, app.ProjectID, app.ID, secret)
}

View File

@ -879,7 +879,7 @@ func (es *ProjectEventstore) ChangeAPIConfigSecret(ctx context.Context, projectI
return nil, caos_errs.ThrowInternal(nil, "EVENT-HBfju", "Errors.Internal")
}
func (es *ProjectEventstore) VerifyOIDCClientSecret(ctx context.Context, projectID, appID string, secret string) (err error) {
func (es *ProjectEventstore) VerifyClientSecret(ctx context.Context, projectID, appID string, secret string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
if appID == "" {
@ -893,12 +893,18 @@ func (es *ProjectEventstore) VerifyOIDCClientSecret(ctx context.Context, project
if _, app = existingProject.GetApp(appID); app == nil {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-D6hba", "Errors.Project.AppNoExisting")
}
if app.Type != proj_model.AppTypeOIDC {
if app.Type == proj_model.AppTypeAPI {
return es.verifyAPIClientSecret(ctx, app, secret)
}
if app.Type == proj_model.AppTypeOIDC {
return es.verifyOIDCClientSecret(ctx, app, existingProject, secret)
}
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-huywq", "Errors.Project.AppIsNotOIDC")
}
func (es *ProjectEventstore) verifyOIDCClientSecret(ctx context.Context, app *proj_model.Application, existingProject *proj_model.Project, secret string) error {
ctx, spanHash := tracing.NewSpan(ctx)
err = crypto.CompareHash(app.OIDCConfig.ClientSecret, []byte(secret), es.passwordAlg)
err := crypto.CompareHash(app.OIDCConfig.ClientSecret, []byte(secret), es.passwordAlg)
spanHash.EndWithError(err)
if err == nil {
err = es.setOIDCClientSecretCheckResult(ctx, existingProject, app.AppID, OIDCClientSecretCheckSucceededAggregate)
@ -907,7 +913,18 @@ func (es *ProjectEventstore) VerifyOIDCClientSecret(ctx context.Context, project
}
err = es.setOIDCClientSecretCheckResult(ctx, existingProject, app.AppID, OIDCClientSecretCheckFailedAggregate)
logging.Log("EVENT-GD1gh").OnError(err).Warn("could not push event OIDCClientSecretCheckFailed")
return caos_errs.ThrowInvalidArgument(nil, "EVENT-wg24q", "Errors.Project.OIDCSecretInvalid")
return caos_errs.ThrowInvalidArgument(nil, "EVENT-wg24q", "Errors.Project.ClientSecretInvalid")
}
func (es *ProjectEventstore) verifyAPIClientSecret(ctx context.Context, app *proj_model.Application, secret string) error {
ctx, spanHash := tracing.NewSpan(ctx)
err := crypto.CompareHash(app.APIConfig.ClientSecret, []byte(secret), es.passwordAlg)
spanHash.EndWithError(err)
if err == nil {
return nil
}
logging.LogWithFields("EVENT-sfsb4", "app id", app.AppID, "clientID", app.APIConfig.ClientID).Warn("API client secret invalid")
return caos_errs.ThrowInvalidArgument(nil, "EVENT-AEdt6", "Errors.Project.ClientSecretInvalid")
}
func (es *ProjectEventstore) setOIDCClientSecretCheckResult(ctx context.Context, project *proj_model.Project, appID string, check func(*es_models.AggregateCreator, *model.Project, string) es_sdk.AggregateFunc) error {

View File

@ -169,7 +169,7 @@ Errors:
GrantNotExists: Projekt Grant existiert nicht
GrantHasNotExistingRole: Eine der Rollen existiert nicht auf dem Projekt
UserIDMisisng: User ID fehlt
OIDCSecretInvalid: Client Secret ist ungültig
ClientSecretInvalid: Client Secret ist ungültig
IAM:
MemberInvalid: Member ist ungültig
MemberAlreadyExisting: Member existiert bereits
@ -511,12 +511,20 @@ EventTypes:
check:
succeeded: OIDC Client Secret Validierung erfolgreich
failed: OIDC Client Secret Validierung fehlgeschlagen
key:
added: Applikations Schlüssel hinzugefügt
removed: Applikations Schlüssel entfernt
config:
oidc:
added: OIDC Konfiguration hinzugefügt
changed: OIDC Konfiguration geändert
secret:
changed: OIDC Client Secret geändert
api:
added: API Konfiguration hinzugefügt
changed: API Konfiguration geändert
secret:
changed: API Client Secret geändert
policy:
password:
complexity:

View File

@ -169,7 +169,7 @@ Errors:
GrantNotExists: Project grant doesn't exist
GrantHasNotExistingRole: One role doesn't exist on project
UserIDMisisng: User ID missing
OIDCSecretInvalid: Client Secret is invalid
ClientSecretInvalid: Client Secret is invalid
IAM:
MemberInvalid: Member is invalid
MemberAlreadyExisting: Member already exists
@ -511,12 +511,20 @@ EventTypes:
check:
succeeded: OIDC Client Secret check succeeded
failed: OIDC Client Secret check failed
key:
added: Application key added
removed: Application key removed
config:
oidc:
added: OIDC Configuration added
changed: OIDC Configuration changed
secret:
changed: OIDC secret changed
api:
added: API Configuration added
changed: API Configuration changed
secret:
changed: API secret changed
policy:
password:
complexity:

View File

@ -69,6 +69,9 @@ func (l *Login) renderLogin(w http.ResponseWriter, r *http.Request, authReq *mod
}
data := l.getUserData(r, authReq, "Login", errType, errMessage)
funcs := map[string]interface{}{
"hasUsernamePasswordLogin": func() bool {
return authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowUsernamePassword
},
"hasExternalLogin": func() bool {
return authReq.LoginPolicy.AllowExternalIDP && authReq.AllowedExternalIDPs != nil && len(authReq.AllowedExternalIDPs) > 0
},

View File

@ -14,6 +14,7 @@ const (
type mfaVerifyFormData struct {
MFAType model.MFAType `schema:"mfaType"`
Code string `schema:"code"`
SelectedProvider model.MFAType `schema:"provider"`
}
func (l *Login) handleMFAVerify(w http.ResponseWriter, r *http.Request) {
@ -23,14 +24,23 @@ func (l *Login) handleMFAVerify(w http.ResponseWriter, r *http.Request) {
l.renderError(w, r, authReq, err)
return
}
step, ok := authReq.PossibleSteps[0].(*model.MFAVerificationStep)
if !ok {
l.renderError(w, r, authReq, err)
return
}
if data.Code == "" {
l.renderMFAVerifySelected(w, r, authReq, step, data.SelectedProvider, nil)
return
}
if data.MFAType == model.MFATypeOTP {
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
err = l.authRepo.VerifyMFAOTP(setContext(r.Context(), authReq.UserOrgID), authReq.ID, authReq.UserID, data.Code, userAgentID, model.BrowserInfoFromRequest(r))
}
if err != nil {
l.renderError(w, r, authReq, err)
l.renderMFAVerifySelected(w, r, authReq, step, model.MFATypeOTP, err)
return
}
}
l.renderNextStep(w, r, authReq)
}

View File

@ -150,6 +150,9 @@ func CreateRenderer(pathPrefix string, staticDir http.FileSystem, cookieName str
"selectedGender": func(g int32) bool {
return false
},
"hasUsernamePasswordLogin": func() bool {
return false
},
"hasExternalLogin": func() bool {
return false
},

View File

@ -17,7 +17,7 @@
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
{{if .LoginPolicy.AllowUsernamePassword }}
{{if hasUsernamePasswordLogin }}
<div class="fields">
<label class="lgn-label" for="loginName">{{t "Login.Loginname"}}</label>
<input class="lgn-input lgn-suffix-input" type="text" id="loginName" name="loginName" placeholder="{{t "Login.LoginnamePlaceHolder"}}"