fix: keep user idp links (#7079)

* login

* auth methods

* NewIDPUserLinksActiveQuery

* use has_login_policy projection

* fix unit tests

* docs

* keep old user links projection

* fix tests

* cleanup

* cleanup comments

* test idp links are not removed

* idempotent auth method test

* idempotent auth method test
This commit is contained in:
Elio Bischof 2023-12-19 11:25:50 +01:00 committed by GitHub
parent 2c4e7070ea
commit c3e6257d68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 57 additions and 235 deletions

View File

@ -1,2 +1,5 @@
Once you created the provider, it is listed in the providers overview. Once you created the provider, it is listed in the providers overview.
Activate it by selecting the tick with the tooltip *set as available*. Activate it by selecting the tick with the tooltip *set as available*.
If you deactivate a provider, your users with links to it will not be able to authenticate anymore.
You can reactivate it and the logins will work again.

View File

@ -7,9 +7,7 @@ import (
"github.com/zitadel/zitadel/internal/api/grpc/idp" "github.com/zitadel/zitadel/internal/api/grpc/idp"
"github.com/zitadel/zitadel/internal/api/grpc/object" "github.com/zitadel/zitadel/internal/api/grpc/object"
policy_grpc "github.com/zitadel/zitadel/internal/api/grpc/policy" policy_grpc "github.com/zitadel/zitadel/internal/api/grpc/policy"
"github.com/zitadel/zitadel/internal/api/grpc/user"
"github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/query"
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin" admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
) )
@ -61,19 +59,7 @@ func (s *Server) AddIDPToLoginPolicy(ctx context.Context, req *admin_pb.AddIDPTo
} }
func (s *Server) RemoveIDPFromLoginPolicy(ctx context.Context, req *admin_pb.RemoveIDPFromLoginPolicyRequest) (*admin_pb.RemoveIDPFromLoginPolicyResponse, error) { func (s *Server) RemoveIDPFromLoginPolicy(ctx context.Context, req *admin_pb.RemoveIDPFromLoginPolicyRequest) (*admin_pb.RemoveIDPFromLoginPolicyResponse, error) {
idpQuery, err := query.NewIDPUserLinkIDPIDSearchQuery(req.IdpId) objectDetails, err := s.command.RemoveIDPProviderFromDefaultLoginPolicy(ctx, &domain.IDPProvider{IDPConfigID: req.IdpId})
if err != nil {
return nil, err
}
idps, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{
Queries: []query.SearchQuery{idpQuery},
}, true)
if err != nil {
return nil, err
}
objectDetails, err := s.command.RemoveIDPProviderFromDefaultLoginPolicy(ctx, &domain.IDPProvider{IDPConfigID: req.IdpId}, user.ExternalIDPViewsToExternalIDPs(idps.Links)...)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -7,9 +7,7 @@ import (
"github.com/zitadel/zitadel/internal/api/grpc/idp" "github.com/zitadel/zitadel/internal/api/grpc/idp"
"github.com/zitadel/zitadel/internal/api/grpc/object" "github.com/zitadel/zitadel/internal/api/grpc/object"
policy_grpc "github.com/zitadel/zitadel/internal/api/grpc/policy" policy_grpc "github.com/zitadel/zitadel/internal/api/grpc/policy"
"github.com/zitadel/zitadel/internal/api/grpc/user"
"github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/query"
mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management" mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management"
) )
@ -94,21 +92,7 @@ func (s *Server) AddIDPToLoginPolicy(ctx context.Context, req *mgmt_pb.AddIDPToL
func (s *Server) RemoveIDPFromLoginPolicy(ctx context.Context, req *mgmt_pb.RemoveIDPFromLoginPolicyRequest) (*mgmt_pb.RemoveIDPFromLoginPolicyResponse, error) { func (s *Server) RemoveIDPFromLoginPolicy(ctx context.Context, req *mgmt_pb.RemoveIDPFromLoginPolicyRequest) (*mgmt_pb.RemoveIDPFromLoginPolicyResponse, error) {
orgID := authz.GetCtxData(ctx).OrgID orgID := authz.GetCtxData(ctx).OrgID
idpQuery, err := query.NewIDPUserLinkIDPIDSearchQuery(req.IdpId) objectDetails, err := s.command.RemoveIDPFromLoginPolicy(ctx, orgID, &domain.IDPProvider{IDPConfigID: req.IdpId})
if err != nil {
return nil, err
}
resourceOwnerQuery, err := query.NewIDPUserLinksResourceOwnerSearchQuery(orgID)
if err != nil {
return nil, err
}
userLinks, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{
Queries: []query.SearchQuery{idpQuery, resourceOwnerQuery},
}, false)
if err != nil {
return nil, err
}
objectDetails, err := s.command.RemoveIDPFromLoginPolicy(ctx, orgID, &domain.IDPProvider{IDPConfigID: req.IdpId}, user.ExternalIDPViewsToExternalIDPs(userLinks.Links)...)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -13,11 +13,14 @@ import (
"github.com/muhlemmer/gu" "github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/timestamppb"
"github.com/zitadel/zitadel/internal/api/grpc" "github.com/zitadel/zitadel/internal/api/grpc"
"github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/internal/integration"
"github.com/zitadel/zitadel/pkg/grpc/idp"
mgmt "github.com/zitadel/zitadel/pkg/grpc/management" mgmt "github.com/zitadel/zitadel/pkg/grpc/management"
object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta" object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
user "github.com/zitadel/zitadel/pkg/grpc/user/v2beta" user "github.com/zitadel/zitadel/pkg/grpc/user/v2beta"
@ -1063,12 +1066,27 @@ func TestServer_ListAuthenticationMethodTypes(t *testing.T) {
ClientSecret: "client_secret", ClientSecret: "client_secret",
}) })
require.NoError(t, err) require.NoError(t, err)
_, err = Tester.Client.Mgmt.AddCustomLoginPolicy(CTX, &mgmt.AddCustomLoginPolicyRequest{})
require.Condition(t, func() bool {
code := status.Convert(err).Code()
return code == codes.AlreadyExists || code == codes.OK
})
_, err = Tester.Client.Mgmt.AddIDPToLoginPolicy(CTX, &mgmt.AddIDPToLoginPolicyRequest{
IdpId: provider.GetId(),
OwnerType: idp.IDPOwnerType_IDP_OWNER_TYPE_ORG,
})
require.NoError(t, err)
idpLink, err := Tester.Client.UserV2.AddIDPLink(CTX, &user.AddIDPLinkRequest{UserId: userMultipleAuth, IdpLink: &user.IDPLink{ idpLink, err := Tester.Client.UserV2.AddIDPLink(CTX, &user.AddIDPLinkRequest{UserId: userMultipleAuth, IdpLink: &user.IDPLink{
IdpId: provider.GetId(), IdpId: provider.GetId(),
UserId: "external-id", UserId: "external-id",
UserName: "displayName", UserName: "displayName",
}}) }})
require.NoError(t, err) require.NoError(t, err)
// This should not remove the user IDP links
_, err = Tester.Client.Mgmt.RemoveIDPFromLoginPolicy(CTX, &mgmt.RemoveIDPFromLoginPolicyRequest{
IdpId: provider.GetId(),
})
require.NoError(t, err)
type args struct { type args struct {
ctx context.Context ctx context.Context

View File

@ -382,7 +382,7 @@ func (l *Login) migrateExternalUserID(r *http.Request, authReq *domain.AuthReque
return previousIDMatched, l.command.MigrateUserIDP(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, authReq.UserOrgID, externalUser.IDPConfigID, previousID, externalUserID) return previousIDMatched, l.command.MigrateUserIDP(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, authReq.UserOrgID, externalUser.IDPConfigID, previousID, externalUserID)
} }
// handleExternalUserAuthenticated maps the IDP user, checks for a corresponding externalID // handleExternalUserAuthenticated maps the IDP user, checks for a corresponding externalID and that the IDP is allowed
func (l *Login) handleExternalUserAuthenticated( func (l *Login) handleExternalUserAuthenticated(
w http.ResponseWriter, w http.ResponseWriter,
r *http.Request, r *http.Request,
@ -393,6 +393,11 @@ func (l *Login) handleExternalUserAuthenticated(
callback func(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest), callback func(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest),
) { ) {
externalUser := mapIDPUserToExternalUser(user, provider.ID) externalUser := mapIDPUserToExternalUser(user, provider.ID)
// ensure the linked IDP is added to the login policy
if err := l.authRepo.SelectExternalIDP(r.Context(), authReq.ID, provider.ID, authReq.AgentID); err != nil {
l.renderError(w, r, authReq, err)
return
}
// check and fill in local linked user // check and fill in local linked user
externalErr := l.authRepo.CheckExternalUserLogin(setContext(r.Context(), ""), authReq.ID, authReq.AgentID, externalUser, domain.BrowserInfoFromRequest(r), false) externalErr := l.authRepo.CheckExternalUserLogin(setContext(r.Context(), ""), authReq.ID, authReq.AgentID, externalUser, domain.BrowserInfoFromRequest(r), false)
if externalErr != nil && !zerrors.IsNotFound(externalErr) { if externalErr != nil && !zerrors.IsNotFound(externalErr) {

View File

@ -163,7 +163,7 @@ func (c *Commands) RemoveDefaultIDPConfig(ctx context.Context, idpID string, idp
events = append(events, userEvents...) events = append(events, userEvents...)
} }
orgAgg := OrgAggregateFromWriteModel(&NewOrgIdentityProviderWriteModel(idpProvider.AggregateID, idpID).WriteModel) orgAgg := OrgAggregateFromWriteModel(&NewOrgIdentityProviderWriteModel(idpProvider.AggregateID, idpID).WriteModel)
orgEvents := c.removeIDPFromLoginPolicy(ctx, orgAgg, idpID, true) orgEvents := c.removeIDPFromLoginPolicy(ctx, orgAgg, idpID, true, externalIDPs...)
events = append(events, orgEvents...) events = append(events, orgEvents...)
} }

View File

@ -66,7 +66,7 @@ func (c *Commands) AddIDPProviderToDefaultLoginPolicy(ctx context.Context, idpPr
return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil
} }
func (c *Commands) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider, cascadeExternalIDPs ...*domain.UserIDPLink) (*domain.ObjectDetails, error) { func (c *Commands) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider) (*domain.ObjectDetails, error) {
if !idpProvider.IsValid() { if !idpProvider.IsValid() {
return nil, zerrors.ThrowInvalidArgument(nil, "INSTANCE-66m9s", "Errors.IAM.LoginPolicy.IDP.Invalid") return nil, zerrors.ThrowInvalidArgument(nil, "INSTANCE-66m9s", "Errors.IAM.LoginPolicy.IDP.Invalid")
} }
@ -89,7 +89,7 @@ func (c *Commands) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context,
} }
instanceAgg := InstanceAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel) instanceAgg := InstanceAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
events := c.removeIDPProviderFromDefaultLoginPolicy(ctx, instanceAgg, idpProvider, false, cascadeExternalIDPs...) events := c.removeIDPProviderFromDefaultLoginPolicy(ctx, instanceAgg, idpProvider, false)
pushedEvents, err := c.eventstore.Push(ctx, events...) pushedEvents, err := c.eventstore.Push(ctx, events...)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -13,7 +13,6 @@ import (
"github.com/zitadel/zitadel/internal/eventstore/v1/models" "github.com/zitadel/zitadel/internal/eventstore/v1/models"
"github.com/zitadel/zitadel/internal/repository/instance" "github.com/zitadel/zitadel/internal/repository/instance"
"github.com/zitadel/zitadel/internal/repository/policy" "github.com/zitadel/zitadel/internal/repository/policy"
"github.com/zitadel/zitadel/internal/repository/user"
"github.com/zitadel/zitadel/internal/zerrors" "github.com/zitadel/zitadel/internal/zerrors"
) )
@ -458,9 +457,8 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
eventstore *eventstore.Eventstore eventstore *eventstore.Eventstore
} }
type args struct { type args struct {
ctx context.Context ctx context.Context
provider *domain.IDPProvider provider *domain.IDPProvider
cascadeExternalIDPs []*domain.UserIDPLink
} }
type res struct { type res struct {
want *domain.ObjectDetails want *domain.ObjectDetails
@ -707,89 +705,6 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
provider: &domain.IDPProvider{ provider: &domain.IDPProvider{
IDPConfigID: "config1", IDPConfigID: "config1",
}, },
cascadeExternalIDPs: []*domain.UserIDPLink{
{
ObjectRoot: models.ObjectRoot{
AggregateID: "user1",
},
IDPConfigID: "config1",
},
},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "INSTANCE",
},
},
},
{
name: "remove provider with external idps, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewLoginPolicyAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
domain.PasswordlessTypeAllowed,
"",
time.Hour*1,
time.Hour*2,
time.Hour*3,
time.Hour*4,
time.Hour*5,
),
),
),
expectFilter(
eventFromEventPusher(
instance.NewIdentityProviderAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
"config1",
),
),
),
expectFilter(
eventFromEventPusher(
user.NewUserIDPLinkAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"config1", "", "externaluser1"),
),
),
expectPush(
instance.NewIdentityProviderRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
"config1"),
user.NewUserIDPLinkCascadeRemovedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"config1", "externaluser1"),
),
),
},
args: args{
ctx: context.Background(),
provider: &domain.IDPProvider{
IDPConfigID: "config1",
},
cascadeExternalIDPs: []*domain.UserIDPLink{
{
ObjectRoot: models.ObjectRoot{
AggregateID: "user1",
},
IDPConfigID: "config1",
ExternalUserID: "externaluser1",
},
},
}, },
res: res{ res: res{
want: &domain.ObjectDetails{ want: &domain.ObjectDetails{
@ -803,7 +718,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
r := &Commands{ r := &Commands{
eventstore: tt.fields.eventstore, eventstore: tt.fields.eventstore,
} }
got, err := r.RemoveIDPProviderFromDefaultLoginPolicy(tt.args.ctx, tt.args.provider, tt.args.cascadeExternalIDPs...) got, err := r.RemoveIDPProviderFromDefaultLoginPolicy(tt.args.ctx, tt.args.provider)
if tt.res.err == nil { if tt.res.err == nil {
assert.NoError(t, err) assert.NoError(t, err)
} }

View File

@ -178,7 +178,7 @@ func (c *Commands) AddIDPToLoginPolicy(ctx context.Context, resourceOwner string
return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil
} }
func (c *Commands) RemoveIDPFromLoginPolicy(ctx context.Context, resourceOwner string, idpProvider *domain.IDPProvider, cascadeExternalIDPs ...*domain.UserIDPLink) (*domain.ObjectDetails, error) { func (c *Commands) RemoveIDPFromLoginPolicy(ctx context.Context, resourceOwner string, idpProvider *domain.IDPProvider) (*domain.ObjectDetails, error) {
if resourceOwner == "" { if resourceOwner == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "Org-M0fs9", "Errors.ResourceOwnerMissing") return nil, zerrors.ThrowInvalidArgument(nil, "Org-M0fs9", "Errors.ResourceOwnerMissing")
} }
@ -203,7 +203,7 @@ func (c *Commands) RemoveIDPFromLoginPolicy(ctx context.Context, resourceOwner s
} }
orgAgg := OrgAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel) orgAgg := OrgAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
events := c.removeIDPFromLoginPolicy(ctx, orgAgg, idpProvider.IDPConfigID, false, cascadeExternalIDPs...) events := c.removeIDPFromLoginPolicy(ctx, orgAgg, idpProvider.IDPConfigID, false)
pushedEvents, err := c.eventstore.Push(ctx, events...) pushedEvents, err := c.eventstore.Push(ctx, events...)
if err != nil { if err != nil {

View File

@ -13,7 +13,6 @@ import (
"github.com/zitadel/zitadel/internal/repository/instance" "github.com/zitadel/zitadel/internal/repository/instance"
"github.com/zitadel/zitadel/internal/repository/org" "github.com/zitadel/zitadel/internal/repository/org"
"github.com/zitadel/zitadel/internal/repository/policy" "github.com/zitadel/zitadel/internal/repository/policy"
"github.com/zitadel/zitadel/internal/repository/user"
"github.com/zitadel/zitadel/internal/zerrors" "github.com/zitadel/zitadel/internal/zerrors"
) )
@ -1006,10 +1005,9 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
eventstore *eventstore.Eventstore eventstore *eventstore.Eventstore
} }
type args struct { type args struct {
ctx context.Context ctx context.Context
resourceOwner string resourceOwner string
provider *domain.IDPProvider provider *domain.IDPProvider
cascadeExternalIDPs []*domain.UserIDPLink
} }
type res struct { type res struct {
want *domain.ObjectDetails want *domain.ObjectDetails
@ -1238,7 +1236,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
}, },
}, },
{ {
name: "remove provider external idp not found, ok", name: "remove provider from login policy, ok",
fields: fields{ fields: fields{
eventstore: eventstoreExpect( eventstore: eventstoreExpect(
t, t,
@ -1290,93 +1288,6 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
Name: "name", Name: "name",
Type: domain.IdentityProviderTypeOrg, Type: domain.IdentityProviderTypeOrg,
}, },
cascadeExternalIDPs: []*domain.UserIDPLink{
{
ObjectRoot: models.ObjectRoot{
AggregateID: "user1",
},
IDPConfigID: "config1",
},
},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "remove provider with external idps, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
org.NewLoginPolicyAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
domain.PasswordlessTypeAllowed,
"",
time.Hour*1,
time.Hour*2,
time.Hour*3,
time.Hour*4,
time.Hour*5,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewIdentityProviderAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"config1",
domain.IdentityProviderTypeOrg,
),
),
),
expectFilter(
eventFromEventPusher(
user.NewUserIDPLinkAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"config1", "", "externaluser1"),
),
),
expectPush(
org.NewIdentityProviderRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"config1",
),
user.NewUserIDPLinkCascadeRemovedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"config1", "externaluser1",
),
),
),
},
args: args{
ctx: context.Background(),
resourceOwner: "org1",
provider: &domain.IDPProvider{
IDPConfigID: "config1",
},
cascadeExternalIDPs: []*domain.UserIDPLink{
{
ObjectRoot: models.ObjectRoot{
AggregateID: "user1",
},
IDPConfigID: "config1",
ExternalUserID: "externaluser1",
},
},
}, },
res: res{ res: res{
want: &domain.ObjectDetails{ want: &domain.ObjectDetails{
@ -1390,7 +1301,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
r := &Commands{ r := &Commands{
eventstore: tt.fields.eventstore, eventstore: tt.fields.eventstore,
} }
got, err := r.RemoveIDPFromLoginPolicy(tt.args.ctx, tt.args.resourceOwner, tt.args.provider, tt.args.cascadeExternalIDPs...) got, err := r.RemoveIDPFromLoginPolicy(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
if tt.res.err == nil { if tt.res.err == nil {
assert.NoError(t, err) assert.NoError(t, err)
} }

View File

@ -146,7 +146,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: Невалиден външен IDP Invalid: Невалиден външен IDP
IDPConfigNotExisting: Невалиден доставчик на IDP за тази организация IDPConfigNotExisting: Невалиден доставчик на IDP за тази организация
NotAllowed: Външен IDP не е разрешен в тази организация NotAllowed: Външен IDP не е разрешен
MinimumExternalIDPNeeded: Трябва да се добави поне един IDP MinimumExternalIDPNeeded: Трябва да се добави поне един IDP
AlreadyExists: Външен IDP вече е зает AlreadyExists: Външен IDP вече е зает
NotFound: Външен IDP не е намерен NotFound: Външен IDP не е намерен

View File

@ -143,7 +143,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: Externí IDP je neplatné Invalid: Externí IDP je neplatné
IDPConfigNotExisting: Konfigurace poskytovatele IDP je pro tuto organizaci neplatná IDPConfigNotExisting: Konfigurace poskytovatele IDP je pro tuto organizaci neplatná
NotAllowed: Externí IDP není v této organizaci povoleno NotAllowed: Externí IDP není povolen
MinimumExternalIDPNeeded: Musí být přidán alespoň jeden IDP MinimumExternalIDPNeeded: Musí být přidán alespoň jeden IDP
AlreadyExists: Externí IDP již obsazeno AlreadyExists: Externí IDP již obsazeno
NotFound: Externí IDP nenalezeno NotFound: Externí IDP nenalezeno

View File

@ -144,7 +144,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: Externer IDP ungültig Invalid: Externer IDP ungültig
IDPConfigNotExisting: IDP Provider ungültig für diese Organisation IDPConfigNotExisting: IDP Provider ungültig für diese Organisation
NotAllowed: Externer IDP ist auf dieser Organisation nicht erlaubt. NotAllowed: Externer IDP nicht erlaubt
MinimumExternalIDPNeeded: Mindestens ein IDP muss hinzugefügt werden. MinimumExternalIDPNeeded: Mindestens ein IDP muss hinzugefügt werden.
AlreadyExists: External IDP ist bereits vergeben AlreadyExists: External IDP ist bereits vergeben
NotFound: Externer IDP nicht gefunden NotFound: Externer IDP nicht gefunden

View File

@ -144,7 +144,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: External IDP invalid Invalid: External IDP invalid
IDPConfigNotExisting: IDP provider invalid for this organization IDPConfigNotExisting: IDP provider invalid for this organization
NotAllowed: External IDP not allowed on this organization NotAllowed: External IDP not allowed
MinimumExternalIDPNeeded: At least one IDP must be added MinimumExternalIDPNeeded: At least one IDP must be added
AlreadyExists: External IDP already taken AlreadyExists: External IDP already taken
NotFound: External IDP not found NotFound: External IDP not found

View File

@ -144,7 +144,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: IDP externo no válido Invalid: IDP externo no válido
IDPConfigNotExisting: Proveedor IDP no válido para esta organización IDPConfigNotExisting: Proveedor IDP no válido para esta organización
NotAllowed: IDP externo no permitido para esta organización NotAllowed: IDP externo no permitido
MinimumExternalIDPNeeded: Al menos de añadirse un IDP MinimumExternalIDPNeeded: Al menos de añadirse un IDP
AlreadyExists: IDP externo ya cogido AlreadyExists: IDP externo ya cogido
NotFound: IDP no encontrado NotFound: IDP no encontrado

View File

@ -144,7 +144,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: IDP Externer invalide Invalid: IDP Externer invalide
IDPConfigNotExisting: Le fournisseur IDP n'est pas valide pour cette organisation IDPConfigNotExisting: Le fournisseur IDP n'est pas valide pour cette organisation
NotAllowed: IDP externe non autorisé pour cette organisation NotAllowed: IDP externe non autorisé
MinimumExternalIDPNeeded: Au moins un IDP doit être ajouté MinimumExternalIDPNeeded: Au moins un IDP doit être ajouté
AlreadyExists: External IDP déjà pris AlreadyExists: External IDP déjà pris
NotFound: IDP externe non trouvé NotFound: IDP externe non trouvé

View File

@ -144,7 +144,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: IDP esterno non valido Invalid: IDP esterno non valido
IDPConfigNotExisting: IDP non valido per questa organizzazione IDPConfigNotExisting: IDP non valido per questa organizzazione
NotAllowed: IDP esterno non consentito su questa organizzazione NotAllowed: IDP esterno non consentito
MinimumExternalIDPNeeded: Almeno un IDP deve essere aggiunto MinimumExternalIDPNeeded: Almeno un IDP deve essere aggiunto
AlreadyExists: IDP esterno già preso AlreadyExists: IDP esterno già preso
NotFound: IDP esterno non trovato NotFound: IDP esterno non trovato

View File

@ -136,7 +136,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: 無効な外部IDPです Invalid: 無効な外部IDPです
IDPConfigNotExisting: この組織はIDPプロバイダーが無効です IDPConfigNotExisting: この組織はIDPプロバイダーが無効です
NotAllowed: この組織では外部IDPが許可されていません NotAllowed: 外部IDPは許可されていません
MinimumExternalIDPNeeded: 少なくとも1つのIDPを追加する必要があります MinimumExternalIDPNeeded: 少なくとも1つのIDPを追加する必要があります
AlreadyExists: 外部IDPはすでに使用されています AlreadyExists: 外部IDPはすでに使用されています
NotFound: 外部IDPが見つかりません NotFound: 外部IDPが見つかりません

View File

@ -144,7 +144,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: Невалиден надворешен IDP Invalid: Невалиден надворешен IDP
IDPConfigNotExisting: IDP не е валиден за оваа организација IDPConfigNotExisting: IDP не е валиден за оваа организација
NotAllowed: Надворешниоте IDP не е дозволен на оваа организација NotAllowed: Надворешниот IDP не е дозволен
MinimumExternalIDPNeeded: Мора да се додаде најмалку еден надворешен IDP MinimumExternalIDPNeeded: Мора да се додаде најмалку еден надворешен IDP
AlreadyExists: Надворешниот IDP е веќе зафатен AlreadyExists: Надворешниот IDP е веќе зафатен
NotFound: Надворешниот IDP не е пронајден NotFound: Надворешниот IDP не е пронајден

View File

@ -144,7 +144,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: Externe IDP ongeldig Invalid: Externe IDP ongeldig
IDPConfigNotExisting: IDP provider ongeldig voor deze organisatie IDPConfigNotExisting: IDP provider ongeldig voor deze organisatie
NotAllowed: Externe IDP niet toegestaan op deze organisatie NotAllowed: Externe IDP niet toegestaan
MinimumExternalIDPNeeded: Er moet minstens één IDP worden toegevoegd MinimumExternalIDPNeeded: Er moet minstens één IDP worden toegevoegd
AlreadyExists: Externe IDP al ingenomen AlreadyExists: Externe IDP al ingenomen
NotFound: Externe IDP niet gevonden NotFound: Externe IDP niet gevonden

View File

@ -144,7 +144,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: Nieprawidłowy IDP zewnętrzny Invalid: Nieprawidłowy IDP zewnętrzny
IDPConfigNotExisting: Dostawca IDP jest nieprawidłowy dla tej organizacji IDPConfigNotExisting: Dostawca IDP jest nieprawidłowy dla tej organizacji
NotAllowed: IDP zewnętrzne nie jest dozwolone w tej organizacji NotAllowed: IDP zewnętrzne nie jest dozwolone
MinimumExternalIDPNeeded: Przynajmniej jeden IDP musi być dodany MinimumExternalIDPNeeded: Przynajmniej jeden IDP musi być dodany
AlreadyExists: IDP zewnętrzne już istnieje AlreadyExists: IDP zewnętrzne już istnieje
NotFound: IDP zewnętrzne nie znaleziony NotFound: IDP zewnętrzne nie znaleziony

View File

@ -143,7 +143,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: IDP externo inválido Invalid: IDP externo inválido
IDPConfigNotExisting: Provedor de IDP inválido para esta organização IDPConfigNotExisting: Provedor de IDP inválido para esta organização
NotAllowed: IDP externo não permitido nesta organização NotAllowed: IDP externo não permitido
MinimumExternalIDPNeeded: Pelo menos um IDP deve ser adicionado MinimumExternalIDPNeeded: Pelo menos um IDP deve ser adicionado
AlreadyExists: IDP externo já está em uso AlreadyExists: IDP externo já está em uso
NotFound: IDP externo não encontrado NotFound: IDP externo não encontrado

View File

@ -143,7 +143,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: Внешний идентификационный номер недействителен. Invalid: Внешний идентификационный номер недействителен.
IDPConfigNotExisting: Поставщик МВУ недействителен для этой организации. IDPConfigNotExisting: Поставщик МВУ недействителен для этой организации.
NotAllowed: Внешний IDP не разрешен в этой организации. NotAllowed: Внешний IDP не разрешен
MinimumExternalIDPNeeded: Необходимо добавить хотя бы одного ВПЛ. MinimumExternalIDPNeeded: Необходимо добавить хотя бы одного ВПЛ.
AlreadyExists: Внешнее ВПЛ уже занято AlreadyExists: Внешнее ВПЛ уже занято
NotFound: Внешний IDP не найден NotFound: Внешний IDP не найден

View File

@ -144,7 +144,7 @@ Errors:
ExternalIDP: ExternalIDP:
Invalid: 外部 IDP 无效 Invalid: 外部 IDP 无效
IDPConfigNotExisting: IDP 提供者对此组织无效 IDPConfigNotExisting: IDP 提供者对此组织无效
NotAllowed: 此组织不允许外部 IDP NotAllowed: 外部 IDP 不允许
MinimumExternalIDPNeeded: 必须添加至少一个 IDP MinimumExternalIDPNeeded: 必须添加至少一个 IDP
AlreadyExists: 外部 IDP 已存在 AlreadyExists: 外部 IDP 已存在
NotFound: 未找到外部 IDP NotFound: 未找到外部 IDP