diff --git a/controller/db/external_jwt_signer_store.go b/controller/db/external_jwt_signer_store.go index 71a968708..264ec2615 100644 --- a/controller/db/external_jwt_signer_store.go +++ b/controller/db/external_jwt_signer_store.go @@ -74,6 +74,7 @@ func (entity *ExternalJwtSigner) GetEntityType() string { var _ ExternalJwtSignerStore = (*externalJwtSignerStoreImpl)(nil) type ExternalJwtSignerStore interface { + NameIndexed Store[*ExternalJwtSigner] } @@ -96,6 +97,10 @@ type externalJwtSignerStoreImpl struct { issuerIndex boltz.ReadIndex } +func (store *externalJwtSignerStoreImpl) GetNameIndex() boltz.ReadIndex { + return store.indexName +} + func (store *externalJwtSignerStoreImpl) initializeLocal() { store.AddExtEntitySymbols() store.indexName = store.addUniqueNameField() diff --git a/controller/env/appenv.go b/controller/env/appenv.go index f040aa4c2..a820b9c8e 100644 --- a/controller/env/appenv.go +++ b/controller/env/appenv.go @@ -573,6 +573,11 @@ func (ae *AppEnv) ProcessJwt(rc *response.RequestContext, token *jwt.Token) erro } func (ae *AppEnv) FillRequestContext(rc *response.RequestContext) error { + // do no process auth headers on authenticate request + if strings.HasSuffix(rc.Request.URL.Path, "/v1/authenticate") && !strings.HasSuffix(rc.Request.URL.Path, "/authenticate/mfa") { + return nil + } + ztSession := ae.getZtSessionFromRequest(rc.Request) if ztSession != "" { diff --git a/controller/model/authenticator.go b/controller/model/authenticator.go index e66cc9226..c92b678cf 100644 --- a/controller/model/authenticator.go +++ b/controller/model/authenticator.go @@ -24,14 +24,11 @@ import ( ) type AuthResult interface { - IdentityId() string - ExternalId() string AuthenticatorId() string SessionCerts() []*x509.Certificate Identity() *Identity Authenticator() *Authenticator AuthPolicy() *AuthPolicy - AuthPolicyId() string IsSuccessful() bool } @@ -121,25 +118,14 @@ func (context *AuthContextHttp) GetChangeContext() *change.Context { var _ AuthResult = &AuthResultBase{} type AuthResultBase struct { - identityId string - externalId string identity *Identity authenticatorId string authenticator *Authenticator sessionCerts []*x509.Certificate - authPolicyId string authPolicy *AuthPolicy env Env } -func (a *AuthResultBase) IdentityId() string { - return a.identityId -} - -func (a *AuthResultBase) ExternalId() string { - return a.externalId -} - func (a *AuthResultBase) AuthenticatorId() string { return a.authenticatorId } @@ -149,14 +135,6 @@ func (a *AuthResultBase) SessionCerts() []*x509.Certificate { } func (a *AuthResultBase) Identity() *Identity { - if a.identity == nil { - if a.identityId != "" { - a.identity, _ = a.env.GetManagers().Identity.Read(a.identityId) - } else if a.externalId != "" { - a.identity, _ = a.env.GetManagers().Identity.ReadByExternalId(a.externalId) - } - - } return a.identity } @@ -168,17 +146,9 @@ func (a *AuthResultBase) Authenticator() *Authenticator { } func (a *AuthResultBase) AuthPolicy() *AuthPolicy { - if a.authPolicy == nil { - a.authPolicy, _ = a.env.GetManagers().AuthPolicy.Read(a.authPolicyId) - } - return a.authPolicy } -func (a *AuthResultBase) AuthPolicyId() string { - return a.authPolicyId -} - func (a *AuthResultBase) IsSuccessful() bool { - return a.identityId != "" + return a.identity != nil } diff --git a/controller/model/authenticator_mod_cert.go b/controller/model/authenticator_mod_cert.go index 329428899..02c2a3c33 100644 --- a/controller/model/authenticator_mod_cert.go +++ b/controller/model/authenticator_mod_cert.go @@ -23,7 +23,6 @@ import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/foundation/v2/errorz" nfpem "github.com/openziti/foundation/v2/pem" - "github.com/openziti/foundation/v2/stringz" "github.com/openziti/ziti/common/cert" "github.com/openziti/ziti/controller/apierror" "github.com/openziti/ziti/controller/change" @@ -225,13 +224,10 @@ func (module *AuthModuleCert) Process(context AuthContext) (AuthResult, error) { } return &AuthResultBase{ - identityId: identity.Id, - externalId: stringz.OrEmpty(identity.ExternalId), identity: identity, authenticatorId: authenticator.Id, authenticator: authenticator, sessionCerts: []*x509.Certificate{clientCert}, - authPolicyId: authPolicy.Id, authPolicy: authPolicy, env: module.env, }, nil diff --git a/controller/model/authenticator_mod_ext_jwt.go b/controller/model/authenticator_mod_ext_jwt.go index 5b980d269..92111975b 100644 --- a/controller/model/authenticator_mod_ext_jwt.go +++ b/controller/model/authenticator_mod_ext_jwt.go @@ -28,8 +28,10 @@ import ( "github.com/openziti/storage/boltz" "github.com/openziti/ziti/controller/apierror" "github.com/openziti/ziti/controller/db" + "github.com/openziti/ziti/controller/models" cmap "github.com/orcaman/concurrent-map/v2" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "go.etcd.io/bbolt" "strings" "sync" @@ -39,11 +41,53 @@ import ( var _ AuthProcessor = &AuthModuleExtJwt{} const ( - AuthMethodExtJwt = "ext-jwt" - ExtJwtInternalClaim = "-internal-ext-jwt" - JwksQueryTimeout = 1 * time.Second + AuthMethodExtJwt = "ext-jwt" + ExtJwtInternalClaim = "-internal-ext-jwt" + JwksQueryTimeout = 1 * time.Second + MaxCandidateJwtProcessing = 2 ) +type candidateResult struct { + Error error + + ExpectedIssuer string + EncounteredIssuer string + ExpectedAudience string + EncounteredAudiences []string + EncounteredExtJwtSigner *db.ExternalJwtSigner + ExpectedExtJwtSignerIds []string + + AuthPolicy *AuthPolicy + Identity *Identity + + IdClaimProperty string + IdClaimsValue string +} + +func (r *candidateResult) LogResult(logger *logrus.Entry, index int) { + if r.AuthPolicy != nil { + logger = logger.WithField("authPolicyId", r.AuthPolicy.Id) + } + + if r.Identity != nil { + logger = logger.WithField("identityId", r.Identity.Id) + } + + if r.EncounteredExtJwtSigner != nil { + logger = logger.WithField("extJwtSignerId", r.EncounteredExtJwtSigner.Id) + } + + logger = logger.WithField("issuer", r.ExpectedIssuer) + logger = logger.WithField("audience", r.ExpectedAudience) + + if r.Error == nil { + logger.Debugf("validated candidate JWT at index %d", index) + } else { + logger.WithError(r.Error).Errorf("failed to validate candidate JWT at index %d", index) + } + +} + type AuthModuleExtJwt struct { env Env method string @@ -268,224 +312,77 @@ func (a *AuthModuleExtJwt) ProcessSecondary(context AuthContext) (AuthResult, er type AuthResultJwt struct { AuthResultBase - externalJwtSignerId string - externalJwtSigner *db.ExternalJwtSigner + externalJwtSigner *db.ExternalJwtSigner } func (a *AuthResultJwt) IsSuccessful() bool { - return a.externalJwtSignerId != "" && a.AuthResultBase.identityId != "" + return a.externalJwtSigner != nil && a.Identity() != nil } func (a *AuthResultJwt) AuthenticatorId() string { - return "extJwtId:" + a.externalJwtSignerId -} - -func (a *AuthModuleExtJwt) process(context AuthContext, isPrimary bool) (AuthResult, error) { - logger := pfxlog.Logger().WithField("authMethod", AuthMethodExtJwt) - - headers := map[string]interface{}{} - - for key, value := range context.GetHeaders() { - headers[strings.ToLower(key)] = value + if a.externalJwtSigner == nil { + return "" } - var authHeaders []string - - if authHeaderVal, ok := headers["authorization"]; ok { - authHeaders = authHeaderVal.([]string) - } + return "extJwtId:" + a.externalJwtSigner.Id +} - if len(authHeaders) != 1 { - logger.Error("no authorization header found") - return nil, apierror.NewInvalidAuth() +func (a *AuthResultJwt) Authenticator() *Authenticator { + authenticator := &Authenticator{ + BaseEntity: models.BaseEntity{ + Id: AuthMethodExtJwt, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + IsSystem: true, + }, + Method: AuthMethodExtJwt, } - authHeader := authHeaders[0] - if !strings.HasPrefix(authHeader, "Bearer ") { - logger.Error("authorization header missing Bearer prefix") - return nil, apierror.NewInvalidAuth() + if a.identity != nil { + authenticator.IdentityId = a.identity.Id } - jwtStr := strings.Replace(authHeader, "Bearer ", "", 1) - - //pubKeyLookup also handles extJwtSigner.enabled checking - jwtToken, err := jwt.Parse(jwtStr, a.pubKeyLookup) - - if err == nil && jwtToken.Valid { - mapClaims := jwtToken.Claims.(jwt.MapClaims) - extJwt := mapClaims[ExtJwtInternalClaim].(*db.ExternalJwtSigner) - - if extJwt == nil { - logger.Error("no external jwt signer found for internal claims") - return nil, apierror.NewInvalidAuth() - } - - logger = logger.WithField("externalJwtSignerId", extJwt.Id) - - issuer := "" - if issuerVal, ok := mapClaims["iss"]; ok { - issuer, ok = issuerVal.(string) - if !ok { - logger.Error("issuer in claims was not a string") - return nil, apierror.NewInvalidAuth() - } - } - - logger = logger.WithField("claimsIssuer", issuer) - - if extJwt.Issuer != nil && *extJwt.Issuer != issuer { - logger.WithField("expectedIssuer", *extJwt.Issuer).Error("invalid issuer") - return nil, apierror.NewInvalidAuth() - } - - if extJwt.Audience != nil { - audValues := mapClaims["aud"] + return authenticator +} - if audValues == nil { - logger.WithField("audience", audValues).Error("audience is missing") - return nil, apierror.NewInvalidAuth() - } +func (a *AuthModuleExtJwt) process(context AuthContext, isPrimary bool) (AuthResult, error) { + logger := pfxlog.Logger().WithField("authMethod", AuthMethodExtJwt) - audSlice, ok := audValues.([]string) + candidates := a.getJwtsFromAuthHeader(context) - if !ok { - audISlice, ok := audValues.([]interface{}) - - if ok { - audSlice = []string{} - for _, aud := range audISlice { - audSlice = append(audSlice, aud.(string)) - } - } else { - audString, ok := audValues.(string) - - if !ok { - logger.WithField("audience", audValues).Error("audience is not a string or array of strings") - return nil, apierror.NewInvalidAuth() - } - - audSlice = []string{audString} - } - } + var verifyResults []*candidateResult - found := false - for _, validAud := range audSlice { - if validAud == *extJwt.Audience { - found = true - break - } - } + for i, candidate := range candidates { + verifyResult := a.verifyCandidate(context, isPrimary, candidate) - if !found { - logger.WithField("expectedAudience", *extJwt.Audience).WithField("claimsAudiences", audSlice).Error("invalid audience") - return nil, apierror.NewInvalidAuth() + if verifyResult.Error == nil { + //success + result := &AuthResultJwt{ + AuthResultBase: AuthResultBase{ + authPolicy: verifyResult.AuthPolicy, + identity: verifyResult.Identity, + env: a.env, + }, + externalJwtSigner: verifyResult.EncounteredExtJwtSigner, } - } - - idClaimProperty := "sub" - if extJwt.ClaimsProperty != nil { - idClaimProperty = *extJwt.ClaimsProperty - } - - logger = logger.WithField("idClaimProperty", idClaimProperty) - - identityIdInterface, ok := mapClaims[idClaimProperty] - if !ok { - logger.Error("claims property on external jwt signer not found in claims") - return nil, apierror.NewInvalidAuth() - } + verifyResult.LogResult(logger, i) - claimsId, ok := identityIdInterface.(string) - - if !ok || claimsId == "" { - logger.Error("expected claims id was not a string or was empty") - return nil, apierror.NewInvalidAuth() - } - - var authPolicy *AuthPolicy - - var identity *Identity - if extJwt.UseExternalId { - authPolicy, identity, err = getAuthPolicyByExternalId(a.env, AuthMethodExtJwt, "", claimsId) + return result, nil } else { - authPolicy, identity, err = getAuthPolicyByIdentityId(a.env, AuthMethodExtJwt, "", claimsId) - } - - if err != nil { - logger.WithError(err).Error("encountered unhandled error during authentication") - return nil, apierror.NewInvalidAuth() - } - - if authPolicy == nil { - logger.WithError(err).Error("encountered unhandled nil auth policy during authentication") - return nil, apierror.NewInvalidAuth() - } - - if identity == nil { - logger.WithError(err).Error("encountered unhandled nil identity during authentication") - return nil, apierror.NewInvalidAuth() - } - - externalJwtSignerId := "" - if identity.Disabled { - logger. - WithField("disabledAt", identity.DisabledAt). - WithField("disabledUntil", identity.DisabledUntil). - Error("authentication failed, identity is disabled") - return nil, apierror.NewInvalidAuth() - } - - if !authPolicy.Primary.ExtJwt.Allowed { - logger.Error("external jwt authentication on auth policy is disabled") - return nil, apierror.NewInvalidAuth() - } - - if isPrimary { - if len(authPolicy.Primary.ExtJwt.AllowedExtJwtSigners) > 0 { - found := false - for _, allowedId := range authPolicy.Primary.ExtJwt.AllowedExtJwtSigners { - if allowedId == extJwt.Id { - externalJwtSignerId = allowedId - found = true - break - } - } - - if !found { - logger. - WithField("allowedSigners", authPolicy.Primary.ExtJwt.AllowedExtJwtSigners). - Error("auth policy does not allow specified signer") - return nil, apierror.NewInvalidAuth() - } - } else { - externalJwtSignerId = extJwt.Id - } - } else if authPolicy.Secondary.RequiredExtJwtSigner != nil { - if extJwt.Id != *authPolicy.Secondary.RequiredExtJwtSigner { - return nil, apierror.NewInvalidAuth() - } - - externalJwtSignerId = extJwt.Id - } - - result := &AuthResultJwt{ - AuthResultBase: AuthResultBase{ - authPolicyId: authPolicy.Id, - authPolicy: authPolicy, - identity: identity, - identityId: identity.Id, - externalId: stringz.OrEmpty(identity.ExternalId), - env: a.env, - }, - externalJwtSignerId: externalJwtSignerId, - externalJwtSigner: extJwt, + verifyResults = append(verifyResults, verifyResult) } + } - return result, nil + authType := "secondary" + if isPrimary { + authType = "primary" + } + logger.Errorf("encountered %d candidate JWTs and all failed to validate for %s authentication, see the following log messages", len(verifyResults), authType) + for i, result := range verifyResults { + result.LogResult(logger, i) } - logger.Error("authorization failed, jwt did not verify") return nil, apierror.NewInvalidAuth() } @@ -582,3 +479,251 @@ func (a *AuthModuleExtJwt) loadExistingSigners() { pfxlog.Logger().Errorf("error loading external jwt signerByIssuer: %v", err) } } + +func (a *AuthModuleExtJwt) verifyAudience(expectedAudience *string, mapClaims jwt.MapClaims) error { + + if expectedAudience == nil { + return errors.New("audience on ext-jwt signer is nil, audience is required") + } + + audValues := mapClaims["aud"] + + if audValues == nil { + return errors.New("audience field is missing or is empty in JWT") + } + + audSlice, ok := audValues.([]string) + + if !ok { + audISlice, ok := audValues.([]interface{}) + + if ok { + audSlice = []string{} + for _, aud := range audISlice { + audSlice = append(audSlice, aud.(string)) + } + } else { + audString, ok := audValues.(string) + + if !ok { + return errors.New("jwt audience field is not a string or an array of strings") + } + + audSlice = []string{audString} + } + } + + for _, validAud := range audSlice { + if validAud == *expectedAudience { + return nil + } + } + + return errors.New("audience value is invalid, no audiences matched the expected audience") +} + +func (a *AuthModuleExtJwt) verifyIssuer(expectedIssuer *string, mapClaims jwt.MapClaims) error { + + if expectedIssuer == nil { + return errors.New("no issuer found for external jwt signer, issuer is required") + } + + issuer := "" + if issuerVal, ok := mapClaims["iss"]; ok { + issuer, ok = issuerVal.(string) + if !ok { + return fmt.Errorf("issuer in claims was not a string, got %T", issuerVal) + } + } + + if *expectedIssuer == issuer { + return nil + } + + return fmt.Errorf("invalid issuer, got: %s", issuer) +} + +func (a *AuthModuleExtJwt) getJwtsFromAuthHeader(context AuthContext) []string { + headers := map[string]interface{}{} + + for key, value := range context.GetHeaders() { + headers[strings.ToLower(key)] = value + } + + var authHeaders []string + + if authHeaderVal, ok := headers["authorization"]; ok { + authHeaders = authHeaderVal.([]string) + } + + var candidates []string + for _, authHeader := range authHeaders { + if strings.HasPrefix(authHeader, "Bearer ") { + jwtStr := strings.Replace(authHeader, "Bearer ", "", 1) + jwtStr = strings.TrimSpace(jwtStr) + + if jwtStr != "" { + candidates = append(candidates, jwtStr) + } + } + } + + if len(candidates) > MaxCandidateJwtProcessing { + candidates = candidates[:MaxCandidateJwtProcessing] + } + + return candidates +} + +func (a *AuthModuleExtJwt) verifyAsPrimary(authPolicy *AuthPolicy, extJwt *db.ExternalJwtSigner) error { + if !authPolicy.Primary.ExtJwt.Allowed { + return errors.New("primary external jwt authentication on auth policy is disabled") + } + + if len(authPolicy.Primary.ExtJwt.AllowedExtJwtSigners) == 0 { + //allow any valid JWT + return nil + } + + for _, allowedId := range authPolicy.Primary.ExtJwt.AllowedExtJwtSigners { + if allowedId == extJwt.Id { + return nil + } + } + + return fmt.Errorf("allowed signers does not contain the external jwt id: %s, expected one of: %v", extJwt.Id, authPolicy.Primary.ExtJwt.AllowedExtJwtSigners) +} + +func (a *AuthModuleExtJwt) verifyCandidate(context AuthContext, isPrimary bool, jwtStr string) *candidateResult { + result := &candidateResult{} + + //pubKeyLookup also handles extJwtSigner.enabled checking + jwtToken, err := jwt.Parse(jwtStr, a.pubKeyLookup) + + if err != nil { + result.Error = fmt.Errorf("jwt failed to parse: %w", err) + return result + } + + if !jwtToken.Valid { + result.Error = errors.New("authorization failed, jwt did not pass signature verification") + return result + } + + mapClaims := jwtToken.Claims.(jwt.MapClaims) + extJwt := mapClaims[ExtJwtInternalClaim].(*db.ExternalJwtSigner) + + if extJwt == nil { + result.Error = errors.New("no external jwt signer found for internal claims") + return result + } + + result.EncounteredExtJwtSigner = extJwt + result.ExpectedIssuer = stringz.OrEmpty(extJwt.Issuer) + result.ExpectedAudience = stringz.OrEmpty(extJwt.Audience) + result.EncounteredIssuer, _ = mapClaims.GetIssuer() + result.EncounteredAudiences, _ = mapClaims.GetAudience() + + err = a.verifyIssuer(extJwt.Issuer, mapClaims) + + if err != nil { + result.Error = fmt.Errorf("issuer validation failed: %w", err) + return result + } + + err = a.verifyAudience(extJwt.Audience, mapClaims) + + if err != nil { + result.Error = fmt.Errorf("audience validation failed: %w", err) + return result + } + + idClaimProperty := "sub" + if extJwt.ClaimsProperty != nil { + idClaimProperty = *extJwt.ClaimsProperty + } + + result.IdClaimProperty = idClaimProperty + + identityIdInterface, ok := mapClaims[idClaimProperty] + + if !ok { + result.Error = fmt.Errorf("claims property [%s] was not found in the claims", idClaimProperty) + return result + } + + claimId, ok := identityIdInterface.(string) + + if !ok || claimId == "" { + result.Error = fmt.Errorf("claims property [%s] was not a string or was empty: %v", idClaimProperty, identityIdInterface) + return result + } + + result.IdClaimsValue = claimId + + var authPolicy *AuthPolicy + + var identity *Identity + claimIdLookupMethod := "" + if extJwt.UseExternalId { + claimIdLookupMethod = "external id" + authPolicy, identity, err = getAuthPolicyByExternalId(a.env, AuthMethodExtJwt, "", claimId) + } else { + claimIdLookupMethod = "identity id" + authPolicy, identity, err = getAuthPolicyByIdentityId(a.env, AuthMethodExtJwt, "", claimId) + } + + if err != nil { + result.Error = fmt.Errorf("error during authentication policy and identity lookup by claims type [%s] and claimd id [%s]: %w", claimIdLookupMethod, claimId, err) + return result + } + + if authPolicy == nil { + result.Error = fmt.Errorf("no authentication policy found for claims type [%s] and claimd id [%s]: %w", claimIdLookupMethod, claimId, err) + return result + } + + result.AuthPolicy = authPolicy + + if identity == nil { + result.Error = fmt.Errorf("no identity found for claims type [%s] and claimd id [%s]: %w", claimIdLookupMethod, claimId, err) + return result + } + + result.Identity = identity + + if identity.Disabled { + result.Error = fmt.Errorf("the identity [%s] is disabled, disabledAt %v, disabledUntil: %v", identity.Id, identity.DisabledAt, identity.DisabledUntil) + return result + } + + if isPrimary { + err = a.verifyAsPrimary(authPolicy, extJwt) + + if len(authPolicy.Primary.ExtJwt.AllowedExtJwtSigners) == 0 { + result.ExpectedExtJwtSignerIds = []string{""} + } else { + result.ExpectedExtJwtSignerIds = authPolicy.Primary.ExtJwt.AllowedExtJwtSigners + } + + if err != nil { + result.Error = fmt.Errorf("primary external jwt processing failed on authentication policy [%s]: %w", authPolicy.Id, err) + return result + } + + } else { + if authPolicy.Secondary.RequiredExtJwtSigner == nil { + result.Error = fmt.Errorf("secondary external jwt authentication on authentication policy [%s] is not configured", authPolicy.Id) + return result + } + + result.ExpectedExtJwtSignerIds = []string{*authPolicy.Secondary.RequiredExtJwtSigner} + + if extJwt.Id != *authPolicy.Secondary.RequiredExtJwtSigner { + result.Error = fmt.Errorf("secondary external jwt authentication failed on authentication policy [%s]: the required ext-jwt signer [%s] did not match the validating id [%s]", authPolicy.Id, *authPolicy.Secondary.RequiredExtJwtSigner, extJwt.Id) + return result + } + } + + return result +} diff --git a/controller/model/authenticator_mod_updb.go b/controller/model/authenticator_mod_updb.go index 3c4f03bd2..0dc06cecd 100644 --- a/controller/model/authenticator_mod_updb.go +++ b/controller/model/authenticator_mod_updb.go @@ -150,7 +150,6 @@ func (module *AuthModuleUpdb) Process(context AuthContext) (AuthResult, error) { return &AuthResultBase{ identity: identity, - identityId: updb.IdentityId, authenticator: authenticator, authenticatorId: authenticator.Id, env: module.env, diff --git a/controller/models/base_model.go b/controller/models/base_model.go index cc965dbfb..0cc9c6eea 100644 --- a/controller/models/base_model.go +++ b/controller/models/base_model.go @@ -275,7 +275,7 @@ func (ctrl *BaseEntityManager[E]) ValidateNameOnUpdate(ctx boltz.MutateContext, return errorz.NewFieldError("name is must be unique", "name", namedEntity.GetName()) } } else { - pfxlog.Logger().Errorf("entity of type %v is named, but store doesn't have name index", reflect.TypeOf(updatedEntity)) + pfxlog.Logger().Errorf("entity of type %v is named, but store doesn't implement the NamedIndexStore interface", reflect.TypeOf(updatedEntity)) } } } @@ -299,7 +299,7 @@ func (handler *BaseEntityManager[E]) ValidateNameOnCreate(tx *bbolt.Tx, entity i return errorz.NewFieldError("name is must be unique", "name", namedEntity.GetName()) } } else { - pfxlog.Logger().Errorf("entity of type %v is named, but store doesn't have name index", reflect.TypeOf(entity)) + pfxlog.Logger().Errorf("entity of type %v is named, but store doesn't implement the NamedIndexStore interface", reflect.TypeOf(entity)) } } return nil diff --git a/controller/oidc_auth/storage.go b/controller/oidc_auth/storage.go index abf2df4d1..d8870f8b8 100644 --- a/controller/oidc_auth/storage.go +++ b/controller/oidc_auth/storage.go @@ -208,7 +208,7 @@ func (s *HybridStorage) Authenticate(authCtx model.AuthContext, id string, confi return nil, apierror.NewInvalidAuth() } - authRequest.IdentityId = result.IdentityId() + authRequest.IdentityId = result.Identity().Id authRequest.AddAmr(authCtx.GetMethod()) configTypeIds := s.env.GetManagers().ConfigType.MapConfigTypeNamesToIds(configTypes, authRequest.IdentityId)