Merge branch 'main' into next
# Conflicts: # cmd/setup/config.go # cmd/setup/setup.go
1
.github/workflows/build.yml
vendored
@ -48,6 +48,7 @@ jobs:
|
||||
go_version: "1.21"
|
||||
core_cache_key: ${{ needs.core.outputs.cache_key }}
|
||||
core_cache_path: ${{ needs.core.outputs.cache_path }}
|
||||
crdb_version: "23.1.13"
|
||||
|
||||
core-integration-test:
|
||||
needs: core
|
||||
|
5
.github/workflows/core-unit-test.yml
vendored
@ -12,6 +12,9 @@ on:
|
||||
core_cache_path:
|
||||
required: true
|
||||
type: string
|
||||
crdb_version:
|
||||
required: false
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@ -51,7 +54,7 @@ jobs:
|
||||
-
|
||||
name: test
|
||||
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
|
||||
run: make core_unit_test
|
||||
run: export ZITADEL_CRDB_VERSION="${{ inputs.crdb_version }}" && make core_unit_test
|
||||
-
|
||||
name: publish coverage
|
||||
uses: codecov/codecov-action@v3.1.4
|
||||
|
20
Makefile
@ -28,10 +28,10 @@ core_static:
|
||||
|
||||
.PHONY: core_generate_all
|
||||
core_generate_all:
|
||||
go install github.com/dmarkham/enumer@v1.5.9
|
||||
go install github.com/rakyll/statik@v0.1.7
|
||||
go install go.uber.org/mock/mockgen@v0.3.0
|
||||
go install golang.org/x/tools/cmd/stringer@v0.15.0
|
||||
go install github.com/dmarkham/enumer@v1.5.9 # https://pkg.go.dev/github.com/dmarkham/enumer?tab=versions
|
||||
go install github.com/rakyll/statik@v0.1.7 # https://pkg.go.dev/github.com/rakyll/statik?tab=versions
|
||||
go install go.uber.org/mock/mockgen@v0.4.0 # https://pkg.go.dev/go.uber.org/mock/mockgen?tab=versions
|
||||
go install golang.org/x/tools/cmd/stringer@v0.17.0 # https://pkg.go.dev/golang.org/x/tools/cmd/stringer?tab=versions
|
||||
go generate ./...
|
||||
|
||||
.PHONY: core_assets
|
||||
@ -52,12 +52,12 @@ endif
|
||||
|
||||
.PHONY: core_grpc_dependencies
|
||||
core_grpc_dependencies:
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.31
|
||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3
|
||||
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.18.1
|
||||
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@v2.18.1
|
||||
go install github.com/envoyproxy/protoc-gen-validate@v1.0.2
|
||||
go install github.com/bufbuild/buf/cmd/buf@v1.27.2
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.32 # https://pkg.go.dev/google.golang.org/protobuf/cmd/protoc-gen-go?tab=versions
|
||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3 # https://pkg.go.dev/google.golang.org/grpc/cmd/protoc-gen-go-grpc?tab=versions
|
||||
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.19.0 # https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway?tab=versions
|
||||
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@v2.19.0 # https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2?tab=versions
|
||||
go install github.com/envoyproxy/protoc-gen-validate@v1.0.3 # https://pkg.go.dev/github.com/envoyproxy/protoc-gen-validate?tab=versions
|
||||
go install github.com/bufbuild/buf/cmd/buf@v1.28.1 # https://pkg.go.dev/github.com/bufbuild/buf/cmd/buf?tab=versions
|
||||
|
||||
.PHONY: core_api
|
||||
core_api: core_api_generator core_grpc_dependencies
|
||||
|
@ -830,6 +830,9 @@ DefaultInstance:
|
||||
# A value of "0s" means that all events are available.
|
||||
# If this value is set, it overwrites the system default unless it is not reset via the admin API.
|
||||
AuditLogRetention: # ZITADEL_DEFAULTINSTANCE_LIMITS_AUDITLOGRETENTION
|
||||
# If Block is true, all requests except to /ui/console or the system API are blocked and /ui/login is redirected to /ui/console.
|
||||
# /ui/console shows a message that the instance is blocked with a link to Console.InstanceManagementURL
|
||||
Block: # ZITADEL_DEFAULTINSTANCE_LIMITS_BLOCK
|
||||
Restrictions:
|
||||
# DisallowPublicOrgRegistration defines if ZITADEL should expose the endpoint /ui/login/register/org
|
||||
# If it is true, the endpoint returns the HTTP status 404 on GET requests, and 409 on POST requests.
|
||||
@ -862,7 +865,8 @@ DefaultInstance:
|
||||
# ResetInterval: 720h # 30 days
|
||||
# # Amount defines the number of units for this quota
|
||||
# Amount: 25000
|
||||
# # Limit defines whether ZITADEL should block further usage when the configured amount is used
|
||||
# # Limit defines whether ZITADEL should block further authenticated requests when the configured amount is used.
|
||||
# # If you not only want to block authenticated requests but also authentication itself, consider using the system APIs SetLimits method.
|
||||
# Limit: false
|
||||
# # Notifications are emitted by ZITADEL when certain quota percentages are reached
|
||||
# Notifications:
|
||||
|
@ -39,7 +39,7 @@ func New() *cobra.Command {
|
||||
Long: `Sets up the minimum requirements to start ZITADEL.
|
||||
|
||||
Prerequisites:
|
||||
- cockroachdb
|
||||
- cockroachDB
|
||||
|
||||
The user provided by flags needs privileges to
|
||||
- create the database if it does not exist
|
||||
|
@ -17,10 +17,10 @@ func newDatabase() *cobra.Command {
|
||||
Short: "initialize only the database",
|
||||
Long: `Sets up the ZITADEL database.
|
||||
|
||||
Prereqesits:
|
||||
Prerequisites:
|
||||
- cockroachDB or postgreSQL
|
||||
|
||||
The user provided by flags needs priviledge to
|
||||
The user provided by flags needs privileges to
|
||||
- create the database if it does not exist
|
||||
- see other users and create a new one if the user does not exist
|
||||
- grant all rights of the ZITADEL database to the user created if not yet set
|
||||
|
@ -17,7 +17,7 @@ func newGrant() *cobra.Command {
|
||||
Short: "set ALL grant to user",
|
||||
Long: `Sets ALL grant to the database user.
|
||||
|
||||
Prereqesits:
|
||||
Prerequisites:
|
||||
- cockroachDB or postgreSQL
|
||||
`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
@ -17,10 +17,10 @@ func newUser() *cobra.Command {
|
||||
Short: "initialize only the database user",
|
||||
Long: `Sets up the ZITADEL database user.
|
||||
|
||||
Prereqesits:
|
||||
- cockroachDB or postreSQL
|
||||
Prerequisites:
|
||||
- cockroachDB or postgreSQL
|
||||
|
||||
The user provided by flags needs priviledge to
|
||||
The user provided by flags needs privileges to
|
||||
- create the database if it does not exist
|
||||
- see other users and create a new one if the user does not exist
|
||||
- grant all rights of the ZITADEL database to the user created if not yet set
|
||||
|
@ -19,7 +19,7 @@ func newZitadel() *cobra.Command {
|
||||
Short: "initialize ZITADEL internals",
|
||||
Long: `initialize ZITADEL internals.
|
||||
|
||||
Prereqesits:
|
||||
Prerequisites:
|
||||
- cockroachDB or postgreSQL with user and database
|
||||
`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
26
cmd/setup/21.go
Normal file
@ -0,0 +1,26 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/database"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed 21.sql
|
||||
addBlockFieldToLimits string
|
||||
)
|
||||
|
||||
type AddBlockFieldToLimits struct {
|
||||
dbClient *database.DB
|
||||
}
|
||||
|
||||
func (mig *AddBlockFieldToLimits) Execute(ctx context.Context) error {
|
||||
_, err := mig.dbClient.ExecContext(ctx, addBlockFieldToLimits)
|
||||
return err
|
||||
}
|
||||
|
||||
func (mig *AddBlockFieldToLimits) String() string {
|
||||
return "21_add_block_field_to_limits"
|
||||
}
|
1
cmd/setup/21.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE IF EXISTS projections.limits ADD COLUMN IF NOT EXISTS block BOOLEAN;
|
@ -42,10 +42,10 @@ func Cleanup(config *Config) {
|
||||
es := eventstore.NewEventstore(config.Eventstore)
|
||||
migration.RegisterMappers(es)
|
||||
|
||||
step, err := migration.LatestStep(ctx, es)
|
||||
step, err := migration.LastStuckStep(ctx, es)
|
||||
logging.OnError(err).Fatal("unable to query latest migration")
|
||||
|
||||
if step.BaseEvent.EventType != migration.StartedType {
|
||||
if step == nil {
|
||||
logging.Info("there is no stuck migration please run `zitadel setup`")
|
||||
return
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ type Steps struct {
|
||||
s18AddLowerFieldsToLoginNames *AddLowerFieldsToLoginNames
|
||||
s19AddCurrentStatesIndex *AddCurrentSequencesIndex
|
||||
s20AddByUserSessionIndex *AddByUserIndexToSession
|
||||
s21AddBlockFieldToLimits *AddBlockFieldToLimits
|
||||
}
|
||||
|
||||
type encryptionKeyConfig struct {
|
||||
|
@ -20,14 +20,11 @@ type externalConfigChange struct {
|
||||
defaults systemdefaults.SystemDefaults
|
||||
}
|
||||
|
||||
func (mig *externalConfigChange) SetLastExecution(lastRun map[string]interface{}) {
|
||||
func (mig *externalConfigChange) Check(lastRun map[string]interface{}) bool {
|
||||
mig.currentExternalDomain, _ = lastRun["externalDomain"].(string)
|
||||
externalPort, _ := lastRun["externalPort"].(float64)
|
||||
mig.currentExternalPort = uint16(externalPort)
|
||||
mig.currentExternalSecure, _ = lastRun["externalSecure"].(bool)
|
||||
}
|
||||
|
||||
func (mig *externalConfigChange) Check() bool {
|
||||
return mig.currentExternalSecure != mig.ExternalSecure ||
|
||||
mig.currentExternalPort != mig.ExternalPort ||
|
||||
mig.currentExternalDomain != mig.ExternalDomain
|
||||
|
@ -8,18 +8,14 @@ import (
|
||||
)
|
||||
|
||||
type projectionTables struct {
|
||||
es *eventstore.Eventstore
|
||||
currentVersion string
|
||||
es *eventstore.Eventstore
|
||||
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
func (mig *projectionTables) SetLastExecution(lastRun map[string]interface{}) {
|
||||
mig.currentVersion, _ = lastRun["version"].(string)
|
||||
}
|
||||
|
||||
func (mig *projectionTables) Check() bool {
|
||||
return mig.currentVersion != mig.Version
|
||||
func (mig *projectionTables) Check(lastRun map[string]interface{}) bool {
|
||||
currentVersion, _ := lastRun["version"].(string)
|
||||
return currentVersion != mig.Version
|
||||
}
|
||||
|
||||
func (mig *projectionTables) Execute(ctx context.Context) error {
|
||||
|
@ -111,6 +111,7 @@ func Setup(config *Config, steps *Steps, masterKey string) {
|
||||
steps.s18AddLowerFieldsToLoginNames = &AddLowerFieldsToLoginNames{dbClient: queryDBClient}
|
||||
steps.s19AddCurrentStatesIndex = &AddCurrentSequencesIndex{dbClient: queryDBClient}
|
||||
steps.s20AddByUserSessionIndex = &AddByUserIndexToSession{dbClient: queryDBClient}
|
||||
steps.s21AddBlockFieldToLimits = &AddBlockFieldToLimits{dbClient: queryDBClient}
|
||||
|
||||
err = projection.Create(ctx, projectionDBClient, eventstoreClient, config.Projections, nil, nil, nil)
|
||||
logging.OnError(err).Fatal("unable to start projections")
|
||||
@ -165,9 +166,11 @@ func Setup(config *Config, steps *Steps, masterKey string) {
|
||||
logging.OnError(err).Fatalf("unable to migrate repeatable step: %s", repeatableStep.String())
|
||||
}
|
||||
|
||||
// This step is executed after the repeatable steps because it adds fields to the login_names3 projection
|
||||
// These steps are executed after the repeatable steps because they add fields projections
|
||||
err = migration.Migrate(ctx, eventstoreClient, steps.s18AddLowerFieldsToLoginNames)
|
||||
logging.WithFields("name", steps.s18AddLowerFieldsToLoginNames.String()).OnError(err).Fatal("migration failed")
|
||||
err = migration.Migrate(ctx, eventstoreClient, steps.s21AddBlockFieldToLimits)
|
||||
logging.WithFields("name", steps.s21AddBlockFieldToLimits.String()).OnError(err).Fatal("migration failed")
|
||||
}
|
||||
|
||||
func readStmt(fs embed.FS, folder, typ, filename string) (string, error) {
|
||||
|
@ -384,10 +384,10 @@ func startAPIs(
|
||||
if err := apis.RegisterServer(ctx, auth.CreateServer(commands, queries, authRepo, config.SystemDefaults, keys.User, config.ExternalSecure), tlsConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := apis.RegisterService(ctx, user_v2.CreateServer(commands, queries, keys.User, keys.IDPConfig, idp.CallbackURL(config.ExternalSecure), idp.SAMLRootURL(config.ExternalSecure))); err != nil {
|
||||
if err := apis.RegisterService(ctx, user_v2.CreateServer(commands, queries, keys.User, keys.IDPConfig, idp.CallbackURL(config.ExternalSecure), idp.SAMLRootURL(config.ExternalSecure), assets.AssetAPI(config.ExternalSecure), permissionCheck)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := apis.RegisterService(ctx, session.CreateServer(commands, queries, permissionCheck)); err != nil {
|
||||
if err := apis.RegisterService(ctx, session.CreateServer(commands, queries)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -439,14 +439,14 @@ func startAPIs(
|
||||
return fmt.Errorf("unable to start console: %w", err)
|
||||
}
|
||||
apis.RegisterHandlerOnPrefix(console.HandlerPrefix, c)
|
||||
|
||||
consolePath := console.HandlerPrefix + "/"
|
||||
l, err := login.CreateLogin(
|
||||
config.Login,
|
||||
commands,
|
||||
queries,
|
||||
authRepo,
|
||||
store,
|
||||
console.HandlerPrefix+"/",
|
||||
consolePath,
|
||||
oidcServer.AuthCallbackURL(),
|
||||
provider.AuthCallbackURL(samlProvider),
|
||||
config.ExternalSecure,
|
||||
@ -455,7 +455,7 @@ func startAPIs(
|
||||
provider.NewIssuerInterceptor(samlProvider.IssuerFromRequest).Handler,
|
||||
instanceInterceptor.Handler,
|
||||
assetsCache.Handler,
|
||||
limitingAccessInterceptor.WithoutLimiting().Handle,
|
||||
limitingAccessInterceptor.WithRedirect(consolePath).Handle,
|
||||
keys.User,
|
||||
keys.IDPConfig,
|
||||
keys.CSRFCookieKey,
|
||||
|
@ -36,11 +36,11 @@
|
||||
"codemirror": "^5.65.8",
|
||||
"cors": "^2.8.5",
|
||||
"file-saver": "^2.0.5",
|
||||
"flag-icons": "^6.7.0",
|
||||
"flag-icons": "^7.1.0",
|
||||
"google-proto-files": "^4.0.0",
|
||||
"google-protobuf": "^3.21.2",
|
||||
"grpc-web": "^1.4.1",
|
||||
"i18n-iso-countries": "^7.6.0",
|
||||
"i18n-iso-countries": "^7.7.0",
|
||||
"libphonenumber-js": "^1.10.49",
|
||||
"material-design-icons-iconfont": "^6.1.1",
|
||||
"moment": "^2.29.4",
|
||||
@ -49,8 +49,8 @@
|
||||
"rxjs": "~7.8.0",
|
||||
"tinycolor2": "^1.6.0",
|
||||
"tslib": "^2.6.2",
|
||||
"uuid": "^9.0.0",
|
||||
"zone.js": "~0.13.1"
|
||||
"uuid": "^9.0.1",
|
||||
"zone.js": "~0.13.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^16.2.2",
|
||||
@ -65,13 +65,13 @@
|
||||
"@bufbuild/buf": "^1.23.1",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/google-protobuf": "^3.15.3",
|
||||
"@types/jasmine": "~4.3.6",
|
||||
"@types/jasminewd2": "~2.0.10",
|
||||
"@types/jasmine": "~5.1.4",
|
||||
"@types/jasminewd2": "~2.0.13",
|
||||
"@types/jsonwebtoken": "^9.0.5",
|
||||
"@types/node": "^20.7.0",
|
||||
"@types/opentype.js": "^1.3.4",
|
||||
"@types/opentype.js": "^1.3.8",
|
||||
"@types/qrcode": "^1.5.2",
|
||||
"@types/uuid": "^9.0.2",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.11",
|
||||
"@typescript-eslint/parser": "^5.60.1",
|
||||
"codelyzer": "^6.0.2",
|
||||
@ -83,8 +83,8 @@
|
||||
"karma-coverage-istanbul-reporter": "^3.0.3",
|
||||
"karma-jasmine": "^5.1.0",
|
||||
"karma-jasmine-html-reporter": "^2.1.0",
|
||||
"prettier": "^3.0.3",
|
||||
"prettier-plugin-organize-imports": "^3.2.2",
|
||||
"prettier": "^3.1.1",
|
||||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"protractor": "~7.0.0",
|
||||
"typescript": "^5.1.6"
|
||||
}
|
||||
|
@ -265,7 +265,12 @@ export class AppComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
public changedOrg(org: Org.AsObject): void {
|
||||
this.router.navigate(['/org']);
|
||||
// Reference: https://stackoverflow.com/a/58114797
|
||||
const currentUrl = this.router.url;
|
||||
this.router.navigateByUrl('/', { skipLocationChange: true }).then(() => {
|
||||
// We use navigateByUrl as our urls may have queryParams
|
||||
this.router.navigateByUrl(currentUrl);
|
||||
});
|
||||
}
|
||||
|
||||
private setLanguage(): void {
|
||||
|
@ -24,8 +24,8 @@
|
||||
creationType === CreationType.PROJECT_OWNED
|
||||
? ProjectAutocompleteType.PROJECT_OWNED
|
||||
: creationType === CreationType.PROJECT_GRANTED
|
||||
? ProjectAutocompleteType.PROJECT_GRANTED
|
||||
: undefined
|
||||
? ProjectAutocompleteType.PROJECT_GRANTED
|
||||
: undefined
|
||||
"
|
||||
>
|
||||
</cnsl-search-project-autocomplete>
|
||||
|
@ -180,13 +180,13 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
||||
validationErrors: combined[0],
|
||||
}
|
||||
: combined[1]
|
||||
? <Help>{
|
||||
type: 'errors',
|
||||
}
|
||||
: <Help>{
|
||||
type: 'hints',
|
||||
validationErrors: undefined,
|
||||
};
|
||||
? <Help>{
|
||||
type: 'errors',
|
||||
}
|
||||
: <Help>{
|
||||
type: 'hints',
|
||||
validationErrors: undefined,
|
||||
};
|
||||
}),
|
||||
);
|
||||
this._changeDetectorRef.markForCheck();
|
||||
|
@ -83,3 +83,23 @@ function i18nErr(err: ValidationErrors | null | undefined, i18nKey: string, para
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const isFieldEmpty = (fieldName: string, g: AbstractControl) => {
|
||||
const field = g.get(fieldName)?.value;
|
||||
if (typeof field === 'number') {
|
||||
return field && field >= 0 ? true : false;
|
||||
}
|
||||
if (typeof field === 'string') {
|
||||
return field && field.length > 0 ? true : false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Reference: https://stackoverflow.com/a/56057955
|
||||
export function atLeastOneIsFilled(...fields: string[]): ValidationErrors | null {
|
||||
return (g: AbstractControl): ValidationErrors | null => {
|
||||
return fields.some((fieldName) => isFieldEmpty(fieldName, g))
|
||||
? null
|
||||
: ({ atLeastOne: 'At least one field has to be provided.' } as ValidationErrors);
|
||||
};
|
||||
}
|
||||
|
@ -141,8 +141,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: ''
|
||||
? 'org.idp.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -161,8 +161,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: ''
|
||||
? 'org.idp.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -185,8 +185,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: ''
|
||||
? 'org.idp.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
|
@ -16,8 +16,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -38,8 +38,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -57,21 +57,21 @@
|
||||
<div class="left-right">
|
||||
<div *ngIf="domainData.userLoginMustBeDomain"><small>domain</small><span>acme.com</span></div>
|
||||
<div *ngIf="domainData.userLoginMustBeDomain"><small>username</small><span>john</span></div>
|
||||
<div *ngIf="domainData.userLoginMustBeDomain"><small>loginname</small><span>john@acme.com</span></div>
|
||||
<div *ngIf="domainData.userLoginMustBeDomain"><small>loginname</small><span>john@acme.com</span></div>
|
||||
|
||||
<div *ngIf="!domainData.userLoginMustBeDomain"><small>domain</small><span>acme.com</span></div>
|
||||
<div *ngIf="!domainData.userLoginMustBeDomain"><small>username</small><span>john@acme.com</span></div>
|
||||
<div *ngIf="!domainData.userLoginMustBeDomain"><small>loginname</small><span>john@acme.com</span></div>
|
||||
<div *ngIf="!domainData.userLoginMustBeDomain"><small>username</small><span>john@acme.com</span></div>
|
||||
<div *ngIf="!domainData.userLoginMustBeDomain"><small>loginname</small><span>john@acme.com</span></div>
|
||||
</div>
|
||||
<i class="las la-arrow-right"></i>
|
||||
<div class="left-right">
|
||||
<div *ngIf="domainData.userLoginMustBeDomain"><small>domain</small><span>acme.com</span></div>
|
||||
<div *ngIf="domainData.userLoginMustBeDomain"><small>username</small><span>john@acme.com</span></div>
|
||||
<div *ngIf="domainData.userLoginMustBeDomain"><small>loginname</small><span>john@acme.com</span></div>
|
||||
<div *ngIf="domainData.userLoginMustBeDomain"><small>username</small><span>john@acme.com</span></div>
|
||||
<div *ngIf="domainData.userLoginMustBeDomain"><small>loginname</small><span>john@acme.com</span></div>
|
||||
|
||||
<div *ngIf="!domainData.userLoginMustBeDomain"><small>domain</small><span>acme.com</span></div>
|
||||
<div *ngIf="!domainData.userLoginMustBeDomain"><small>username</small><span>john</span></div>
|
||||
<div *ngIf="!domainData.userLoginMustBeDomain"><small>loginname</small><span>john@acme.com</span></div>
|
||||
<div *ngIf="!domainData.userLoginMustBeDomain"><small>loginname</small><span>john@acme.com</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -88,8 +88,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -110,8 +110,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -133,8 +133,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
|
@ -14,8 +14,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'google', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'google', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'google', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo" src="./assets/images/idp/google.png" alt="google" />
|
||||
@ -30,8 +30,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'azure-ad', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'azure-ad', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'azure-ad', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo" src="./assets/images/idp/ms.svg" alt="microsoft" />
|
||||
@ -47,8 +47,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'github', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'github', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'github', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="GitHub" />
|
||||
@ -65,8 +65,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'github-es', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'github-es', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'github-es', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="GitHub" />
|
||||
@ -83,8 +83,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'gitlab', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'gitlab', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'gitlab', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="GitLab" />
|
||||
@ -99,8 +99,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'gitlab-self-hosted', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'gitlab-self-hosted', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'gitlab-self-hosted', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="GitLab" />
|
||||
@ -115,8 +115,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'apple', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'apple', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'apple', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo apple dark" src="./assets/images/idp/apple-dark.svg" alt="Apple" />
|
||||
@ -132,8 +132,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'oidc', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'oidc', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'oidc', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<div class="idp-icon">
|
||||
@ -150,8 +150,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'oauth', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'oauth', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'oauth', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo" src="./assets/images/idp/oauth.svg" alt="oauth" />
|
||||
@ -167,8 +167,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'jwt', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'jwt', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'jwt', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<div class="idp-icon">
|
||||
@ -185,8 +185,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'ldap', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'ldap', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'ldap', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<div class="idp-icon">
|
||||
@ -203,8 +203,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['/instance', 'provider', 'saml', 'create']
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['/org', 'provider', 'saml', 'create']
|
||||
: []
|
||||
? ['/org', 'provider', 'saml', 'create']
|
||||
: []
|
||||
"
|
||||
>
|
||||
<img class="idp-logo" src="./assets/images/idp/saml-icon.svg" alt="oauth" />
|
||||
|
@ -12,8 +12,8 @@
|
||||
(data.componentType === LoginMethodComponentType.SecondFactor
|
||||
? 'MFA.SECONDFACTORTYPES.'
|
||||
: LoginMethodComponentType.MultiFactor
|
||||
? 'MFA.MULTIFACTORTYPES.'
|
||||
: '') + mfa | translate
|
||||
? 'MFA.MULTIFACTORTYPES.'
|
||||
: '') + mfa | translate
|
||||
}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
|
@ -9,8 +9,8 @@
|
||||
(componentType === LoginMethodComponentType.SecondFactor
|
||||
? 'MFA.SECONDFACTORTYPES.'
|
||||
: LoginMethodComponentType.MultiFactor
|
||||
? 'MFA.MULTIFACTORTYPES.'
|
||||
: '') + mfa | translate
|
||||
? 'MFA.MULTIFACTORTYPES.'
|
||||
: '') + mfa | translate
|
||||
}}
|
||||
</span>
|
||||
|
||||
|
@ -150,13 +150,13 @@ export class FactorTableComponent {
|
||||
this.componentType === LoginMethodComponentType.MultiFactor
|
||||
? [MultiFactorType.MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION]
|
||||
: this.componentType === LoginMethodComponentType.SecondFactor
|
||||
? [
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_U2F,
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_OTP,
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_OTP_SMS,
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_OTP_EMAIL,
|
||||
]
|
||||
: [];
|
||||
? [
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_U2F,
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_OTP,
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_OTP_SMS,
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_OTP_EMAIL,
|
||||
]
|
||||
: [];
|
||||
|
||||
const filtered = (allTypes as Array<MultiFactorType | SecondFactorType>).filter((type) => !this.list.includes(type));
|
||||
|
||||
|
@ -34,8 +34,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -62,8 +62,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -89,8 +89,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -111,8 +111,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -134,8 +134,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -210,8 +210,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -235,8 +235,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -268,8 +268,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -296,8 +296,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -324,8 +324,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -346,8 +346,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -368,8 +368,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -390,8 +390,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -413,8 +413,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -439,8 +439,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
|
@ -25,6 +25,15 @@ import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
import { LoginMethodComponentType } from './factor-table/factor-table.component';
|
||||
import { catchError, map, takeUntil } from 'rxjs/operators';
|
||||
import { error } from 'console';
|
||||
|
||||
const minValueValidator = (minValue: number) => (control: AbstractControl) => {
|
||||
const value = control.value;
|
||||
if (value !== null && value < minValue) {
|
||||
return { minValue: true, message: `Minimum value allowed is ${minValue}.` };
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-login-policy',
|
||||
@ -48,11 +57,11 @@ export class LoginPolicyComponent implements OnInit, OnDestroy {
|
||||
public InfoSectionType: any = InfoSectionType;
|
||||
public PasswordlessType: any = PasswordlessType;
|
||||
public lifetimeForm: UntypedFormGroup = this.fb.group({
|
||||
passwordCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
externalLoginCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
mfaInitSkipLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
secondFactorCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
multiFactorCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
passwordCheckLifetime: [{ disabled: true }, [requiredValidator, minValueValidator(1)]],
|
||||
externalLoginCheckLifetime: [{ disabled: true }, [requiredValidator, minValueValidator(1)]],
|
||||
mfaInitSkipLifetime: [{ disabled: true }, [requiredValidator, minValueValidator(0)]],
|
||||
secondFactorCheckLifetime: [{ disabled: true }, [requiredValidator, minValueValidator(1)]],
|
||||
multiFactorCheckLifetime: [{ disabled: true }, [requiredValidator, minValueValidator(1)]],
|
||||
});
|
||||
private destroy$: Subject<void> = new Subject();
|
||||
|
||||
@ -142,8 +151,8 @@ export class LoginPolicyComponent implements OnInit, OnDestroy {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.policy.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['policy.write']
|
||||
: [],
|
||||
? ['policy.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
@ -285,6 +294,12 @@ export class LoginPolicyComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public savePolicy(): void {
|
||||
if (this.lifetimeForm.invalid) {
|
||||
// Display error message
|
||||
this.toast.showError('POLICY.LOGIN_POLICY.LIFETIME_INVALID', false, true);
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateData()
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.LOGIN_POLICY.SAVED', true);
|
||||
|
@ -134,8 +134,8 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: '',
|
||||
? 'policy.write'
|
||||
: '',
|
||||
]);
|
||||
constructor(
|
||||
private authService: GrpcAuthService,
|
||||
|
@ -552,8 +552,8 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: '',
|
||||
? 'policy.write'
|
||||
: '',
|
||||
]);
|
||||
|
||||
constructor(
|
||||
|
@ -42,8 +42,8 @@ export class PrivacyPolicyComponent implements OnInit, OnDestroy {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: '',
|
||||
? 'policy.write'
|
||||
: '',
|
||||
]);
|
||||
|
||||
public LANGPLACEHOLDER: string = '{{.Lang}}';
|
||||
|
@ -46,8 +46,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -150,8 +150,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.delete'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.delete'
|
||||
: ''
|
||||
? 'policy.delete'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -174,8 +174,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -224,8 +224,8 @@
|
||||
? previewData.logoUrlDark
|
||||
: previewData.logoUrl
|
||||
: theme === Theme.DARK
|
||||
? data.logoUrlDark
|
||||
: data.logoUrl as logoSrc;
|
||||
? data.logoUrlDark
|
||||
: data.logoUrl as logoSrc;
|
||||
else addLogoButton
|
||||
"
|
||||
>
|
||||
@ -241,8 +241,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -271,8 +271,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -295,8 +295,8 @@
|
||||
? previewData.iconUrlDark
|
||||
: previewData.iconUrl
|
||||
: theme === Theme.DARK
|
||||
? data.iconUrlDark
|
||||
: data.iconUrl as iconSrc;
|
||||
? data.iconUrlDark
|
||||
: data.iconUrl as iconSrc;
|
||||
else addIconButton
|
||||
"
|
||||
>
|
||||
@ -312,8 +312,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -342,8 +342,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -385,8 +385,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -407,8 +407,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -430,8 +430,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -453,8 +453,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -480,8 +480,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -502,8 +502,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -525,8 +525,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -547,8 +547,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -592,8 +592,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -630,8 +630,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -669,8 +669,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
@ -697,8 +697,8 @@
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
|
@ -46,8 +46,8 @@ export class ProjectMembersDataSource extends DataSource<Member.AsObject> {
|
||||
projectType === ProjectType.PROJECTTYPE_OWNED
|
||||
? this.service.listProjectMembers(projectId, pageSize, offset)
|
||||
: projectType === ProjectType.PROJECTTYPE_GRANTED && grantId
|
||||
? this.service.listProjectGrantMembers(projectId, grantId, pageSize, offset)
|
||||
: undefined;
|
||||
? this.service.listProjectGrantMembers(projectId, grantId, pageSize, offset)
|
||||
: undefined;
|
||||
if (promise) {
|
||||
from(promise)
|
||||
.pipe(
|
||||
|
@ -23,8 +23,8 @@
|
||||
'project.member.write:' + (projectType === ProjectType.PROJECTTYPE_OWNED)
|
||||
? $any(project)?.id
|
||||
: projectType === ProjectType.PROJECTTYPE_GRANTED
|
||||
? $any(project)?.projectId
|
||||
: ''
|
||||
? $any(project)?.projectId
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async
|
||||
@ -35,8 +35,8 @@
|
||||
'project.member.delete:' + (projectType === ProjectType.PROJECTTYPE_OWNED)
|
||||
? $any(project)?.id
|
||||
: projectType === ProjectType.PROJECTTYPE_GRANTED
|
||||
? $any(project)?.projectId
|
||||
: ''
|
||||
? $any(project)?.projectId
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async
|
||||
@ -50,8 +50,8 @@
|
||||
'project.member.delete:' + (projectType === ProjectType.PROJECTTYPE_OWNED)
|
||||
? $any(project)?.id
|
||||
: projectType === ProjectType.PROJECTTYPE_GRANTED
|
||||
? $any(project)?.projectId
|
||||
: '',
|
||||
? $any(project)?.projectId
|
||||
: '',
|
||||
'project.member.delete'
|
||||
]"
|
||||
>
|
||||
@ -74,8 +74,8 @@
|
||||
'project.member.write:' + (projectType === ProjectType.PROJECTTYPE_OWNED)
|
||||
? $any(project)?.id
|
||||
: projectType === ProjectType.PROJECTTYPE_GRANTED
|
||||
? $any(project)?.projectId
|
||||
: '',
|
||||
? $any(project)?.projectId
|
||||
: '',
|
||||
'project.member.write'
|
||||
]"
|
||||
>
|
||||
|
@ -69,8 +69,8 @@ export class ProviderAppleComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
|
@ -76,8 +76,8 @@ export class ProviderAzureADComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
|
@ -67,8 +67,8 @@ export class ProviderGithubESComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
|
@ -65,8 +65,8 @@ export class ProviderGithubComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
|
@ -66,8 +66,8 @@ export class ProviderGitlabSelfHostedComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
|
@ -65,8 +65,8 @@ export class ProviderGitlabComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
|
@ -65,8 +65,8 @@ export class ProviderGoogleComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
|
@ -95,8 +95,8 @@ export class ProviderJWTComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
|
@ -69,8 +69,8 @@ export class ProviderLDAPComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
|
@ -68,8 +68,8 @@ export class ProviderOAuthComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
|
@ -21,7 +21,12 @@
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'IDP.SAML.METADATAXML' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="metadataXml" />
|
||||
<textarea
|
||||
cnslInput
|
||||
formControlName="metadataXml"
|
||||
placeholder="base64 encoded metadata xml"
|
||||
class="metadata-xml"
|
||||
></textarea>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'IDP.SAML.METADATAURL' | translate }}</cnsl-label>
|
||||
@ -29,7 +34,7 @@
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'IDP.SAML.BINDING' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="binding">
|
||||
<mat-select formControlName="binding" [compareWith]="compareBinding">
|
||||
<mat-option *ngFor="let binding of bindingValues" [value]="binding">{{ binding }}</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
@ -0,0 +1,3 @@
|
||||
.metadata-xml {
|
||||
min-height: 200px;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { Component, Injector, Type } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { Options, Provider } from '../../../proto/generated/zitadel/idp_pb';
|
||||
import { Options, Provider, SAMLBinding } from '../../../proto/generated/zitadel/idp_pb';
|
||||
import { AbstractControl, FormGroup, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||
import { ManagementService } from '../../../services/mgmt.service';
|
||||
@ -10,7 +10,7 @@ import { GrpcAuthService } from '../../../services/grpc-auth.service';
|
||||
import { take } from 'rxjs';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from '../../../services/breadcrumb.service';
|
||||
import { requiredValidator } from '../../form-field/validators/validators';
|
||||
import { atLeastOneIsFilled, requiredValidator } from '../../form-field/validators/validators';
|
||||
import {
|
||||
AddSAMLProviderRequest as AdminAddSAMLProviderRequest,
|
||||
GetProviderByIDRequest as AdminGetProviderByIDRequest,
|
||||
@ -21,7 +21,6 @@ import {
|
||||
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
|
||||
UpdateSAMLProviderRequest as MgmtUpdateSAMLProviderRequest,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import * as zitadel_idp_pb from '../../../proto/generated/zitadel/idp_pb';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-provider-saml-sp',
|
||||
@ -38,7 +37,7 @@ export class ProviderSamlSpComponent {
|
||||
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||
private service!: ManagementService | AdminService;
|
||||
|
||||
bindingValues: string[] = Object.keys(zitadel_idp_pb.SAMLBinding);
|
||||
bindingValues: string[] = Object.keys(SAMLBinding);
|
||||
|
||||
constructor(
|
||||
private _location: Location,
|
||||
@ -54,13 +53,16 @@ export class ProviderSamlSpComponent {
|
||||
}
|
||||
|
||||
private _initializeForm(): void {
|
||||
this.form = new UntypedFormGroup({
|
||||
name: new UntypedFormControl('', [requiredValidator]),
|
||||
metadataXml: new UntypedFormControl('', [requiredValidator]),
|
||||
metadataUrl: new UntypedFormControl('', [requiredValidator]),
|
||||
binding: new UntypedFormControl(this.bindingValues[0], [requiredValidator]),
|
||||
withSignedRequest: new UntypedFormControl(true, [requiredValidator]),
|
||||
});
|
||||
this.form = new UntypedFormGroup(
|
||||
{
|
||||
name: new UntypedFormControl('', [requiredValidator]),
|
||||
metadataXml: new UntypedFormControl('', []),
|
||||
metadataUrl: new UntypedFormControl('', []),
|
||||
binding: new UntypedFormControl(this.bindingValues[0], [requiredValidator]),
|
||||
withSignedRequest: new UntypedFormControl(true, [requiredValidator]),
|
||||
},
|
||||
atLeastOneIsFilled('metadataXml', 'metadataUrl'),
|
||||
);
|
||||
}
|
||||
|
||||
private _checkFormPermissions(): void {
|
||||
@ -69,8 +71,8 @@ export class ProviderSamlSpComponent {
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? ['iam.idp.write']
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
? ['org.idp.write']
|
||||
: [],
|
||||
)
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
@ -121,18 +123,23 @@ export class ProviderSamlSpComponent {
|
||||
this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? new MgmtUpdateSAMLProviderRequest()
|
||||
: new AdminUpdateSAMLProviderRequest();
|
||||
|
||||
req.setId(this.provider.id);
|
||||
req.setName(this.name?.value);
|
||||
req.setMetadataUrl(this.metadataUrl?.value);
|
||||
req.setMetadataXml(this.metadataXml?.value);
|
||||
if (this.metadataXml?.value) {
|
||||
req.setMetadataXml(this.metadataXml?.value);
|
||||
} else {
|
||||
req.setMetadataUrl(this.metadataUrl?.value);
|
||||
}
|
||||
req.setWithSignedRequest(this.withSignedRequest?.value);
|
||||
// @ts-ignore
|
||||
req.setBinding(zitadel_idp_pb.SAMLBinding[`${this.biding?.value}`]);
|
||||
req.setBinding(SAMLBinding[this.binding?.value]);
|
||||
req.setProviderOptions(this.options);
|
||||
|
||||
this.loading = true;
|
||||
this.service
|
||||
.updateSAMLProvider(req)
|
||||
.then((idp) => {
|
||||
.then(() => {
|
||||
setTimeout(() => {
|
||||
this.loading = false;
|
||||
this.close();
|
||||
@ -151,16 +158,19 @@ export class ProviderSamlSpComponent {
|
||||
? new MgmtAddSAMLProviderRequest()
|
||||
: new AdminAddSAMLProviderRequest();
|
||||
req.setName(this.name?.value);
|
||||
req.setMetadataUrl(this.metadataUrl?.value);
|
||||
req.setMetadataXml(this.metadataXml?.value);
|
||||
if (this.metadataXml?.value) {
|
||||
req.setMetadataXml(this.metadataXml?.value);
|
||||
} else {
|
||||
req.setMetadataUrl(this.metadataUrl?.value);
|
||||
}
|
||||
req.setProviderOptions(this.options);
|
||||
// @ts-ignore
|
||||
req.setBinding(zitadel_idp_pb.SAMLBinding[`${this.biding?.value}`]);
|
||||
req.setBinding(SAMLBinding[this.binding?.value]);
|
||||
req.setWithSignedRequest(this.withSignedRequest?.value);
|
||||
this.loading = true;
|
||||
this.service
|
||||
.addSAMLProvider(req)
|
||||
.then((idp) => {
|
||||
.then(() => {
|
||||
setTimeout(() => {
|
||||
this.loading = false;
|
||||
this.close();
|
||||
@ -187,9 +197,9 @@ export class ProviderSamlSpComponent {
|
||||
.then((resp) => {
|
||||
this.provider = resp.idp;
|
||||
this.loading = false;
|
||||
this.name?.setValue(this.provider?.name);
|
||||
if (this.provider?.config?.saml) {
|
||||
this.form.patchValue(this.provider.config.saml);
|
||||
this.name?.setValue(this.provider.name);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
@ -202,6 +212,13 @@ export class ProviderSamlSpComponent {
|
||||
this._location.back();
|
||||
}
|
||||
|
||||
compareBinding(value: string, index: number) {
|
||||
if (value) {
|
||||
return value === Object.keys(SAMLBinding)[index];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private get name(): AbstractControl | null {
|
||||
return this.form.get('name');
|
||||
}
|
||||
@ -214,7 +231,7 @@ export class ProviderSamlSpComponent {
|
||||
return this.form.get('metadataUrl');
|
||||
}
|
||||
|
||||
private get biding(): AbstractControl | null {
|
||||
private get binding(): AbstractControl | null {
|
||||
return this.form.get('binding');
|
||||
}
|
||||
|
||||
|
@ -167,8 +167,8 @@ export class SearchProjectAutocompleteComponent implements OnInit, OnDestroy {
|
||||
const type = (p as Project.AsObject).id
|
||||
? ProjectType.PROJECTTYPE_OWNED
|
||||
: (p as GrantedProject.AsObject).projectId
|
||||
? ProjectType.PROJECTTYPE_GRANTED
|
||||
: ProjectType.PROJECTTYPE_OWNED;
|
||||
? ProjectType.PROJECTTYPE_GRANTED
|
||||
: ProjectType.PROJECTTYPE_OWNED;
|
||||
|
||||
this.selectionChanged.emit({
|
||||
project: p,
|
||||
|
@ -10,8 +10,8 @@
|
||||
type === PolicyComponentServiceType.ADMIN
|
||||
? setting.iamWithRole
|
||||
: type === PolicyComponentServiceType.MGMT
|
||||
? setting.orgWithRole
|
||||
: []
|
||||
? setting.orgWithRole
|
||||
: []
|
||||
"
|
||||
>
|
||||
<div class="p-item card" @policy data-e2e="policy-card">
|
||||
@ -35,8 +35,8 @@
|
||||
type === PolicyComponentServiceType.ADMIN
|
||||
? setting.iamRouterLink
|
||||
: type === PolicyComponentServiceType.MGMT
|
||||
? setting.orgRouterLink
|
||||
: null
|
||||
? setting.orgRouterLink
|
||||
: null
|
||||
"
|
||||
[queryParams]="setting.queryParams"
|
||||
mat-stroked-button
|
||||
|
@ -69,8 +69,8 @@
|
||||
((context === UserGrantContext.OWNED_PROJECT
|
||||
? ['user.grant.write:' + row?.projectId]
|
||||
: context === UserGrantContext.GRANTED_PROJECT
|
||||
? ['user.grant.write:' + row?.id]
|
||||
: []
|
||||
? ['user.grant.write:' + row?.id]
|
||||
: []
|
||||
)
|
||||
| hasRole
|
||||
| async)
|
||||
|
@ -8,10 +8,10 @@
|
||||
? 4
|
||||
: 3
|
||||
: appType?.value?.createType === AppCreateType.API
|
||||
? 3
|
||||
: appType?.value?.createType === AppCreateType.SAML
|
||||
? 3
|
||||
: 0
|
||||
? 3
|
||||
: appType?.value?.createType === AppCreateType.SAML
|
||||
? 3
|
||||
: 0
|
||||
: 0
|
||||
"
|
||||
[currentCreateStep]="currentCreateStep"
|
||||
|
@ -261,8 +261,8 @@
|
||||
"DESCRIPTION": "Щракнете върху бутона по-долу, за да влезете отново."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Вашата квота за удостоверени заявки е изчерпана.",
|
||||
"DESCRIPTION": "Премахнете или увеличете ограничението на квотата за този екземпляр на ZITADEL."
|
||||
"TITLE": "Вашият екземпляр е блокиран.",
|
||||
"DESCRIPTION": "Попитайте администратора на вашия екземпляр ZITADEL да актуализира абонамента."
|
||||
},
|
||||
"INVALID_FORMAT": "Форматирането е невалидно.",
|
||||
"NOTANEMAIL": "Дадената стойност не е имейл адрес.",
|
||||
@ -1244,6 +1244,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Потребителите могат да избират от наличните доставчици на идентичност по-долу. ",
|
||||
"ADVANCED": "Разширено",
|
||||
"LIFETIMEDURATIONS": "Продължителност на влизане",
|
||||
"LIFETIME_INVALID": "Формулярът съдържа невалидни стойности.",
|
||||
"SAVED": "Запазено успешно!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -268,8 +268,8 @@
|
||||
"DESCRIPTION": "Klikněte na tlačítko níže pro opětovné přihlášení."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Vyčerpali jste kvótu pro autentizované požadavky.",
|
||||
"DESCRIPTION": "Odstraňte nebo zvyšte limit kvóty pro tuto instanci ZITADEL."
|
||||
"TITLE": "Vaše instance je blokována.",
|
||||
"DESCRIPTION": "Požádejte svého správce instance ZITADEL, aby aktualizoval předplatné."
|
||||
},
|
||||
"INVALID_FORMAT": "Formát je neplatný.",
|
||||
"NOTANEMAIL": "Zadaná hodnota není e-mailová adresa.",
|
||||
@ -1251,6 +1251,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Uživatelé si mohou vybrat z dostupných poskytovatelů identity níže. Poznámka: Můžete použít poskytovatele nastavené systémem, jakož i poskytovatele nastavené pouze pro vaši organizaci.",
|
||||
"ADVANCED": "Pokročilé",
|
||||
"LIFETIMEDURATIONS": "Doba trvání přihlášení",
|
||||
"LIFETIME_INVALID": "Formulář obsahuje neplatné hodnoty.",
|
||||
"SAVED": "Úspěšně uloženo!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -267,8 +267,8 @@
|
||||
"DESCRIPTION": "Klicke auf \"Einloggen\", um Dich erneut anzumelden."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Dein Kontingent an authentifizierten Anfragen is erschöpft.",
|
||||
"DESCRIPTION": "Lösche oder erhöhe die Grenze für diese ZITADEL Instanz."
|
||||
"TITLE": "Deine Instanz ist blockiert.",
|
||||
"DESCRIPTION": "Bitte kontaktiere den Administrator deiner ZITADEL Instanz."
|
||||
},
|
||||
"INVALID_FORMAT": "Das Format is ungültig.",
|
||||
"NOTANEMAIL": "Der eingegebene Wert ist keine E-Mail Adresse.",
|
||||
@ -1250,6 +1250,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Nutzer können sich mit den verfügbaren Idps authentifizieren. Achtung: Es kann zwischen System- und organisationsspezifischen Providern gewählt werden.",
|
||||
"ADVANCED": "Erweitert",
|
||||
"LIFETIMEDURATIONS": "Login Lifetimes",
|
||||
"LIFETIME_INVALID": "Login Lifetimes sind ungültig.",
|
||||
"SAVED": "Erfolgreich gespeichert."
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -268,8 +268,8 @@
|
||||
"DESCRIPTION": "Click the button below to log in again."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Your quota for authenticated requests is exhausted.",
|
||||
"DESCRIPTION": "Remove or increase the quota limit for this ZITADEL instance."
|
||||
"TITLE": "Your instance is blocked.",
|
||||
"DESCRIPTION": "Ask your ZITADEL instance administrator to update the subscription."
|
||||
},
|
||||
"INVALID_FORMAT": "The formatting is invalid.",
|
||||
"NOTANEMAIL": "The given value is not an e-mail address.",
|
||||
@ -1251,6 +1251,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Users can choose from the available identity providers below. Note: You can use System-set providers as well as providers set for your organization only.",
|
||||
"ADVANCED": "Advanced",
|
||||
"LIFETIMEDURATIONS": "Login Lifetimes",
|
||||
"LIFETIME_INVALID": "Form contains invalid value(s).",
|
||||
"SAVED": "Saved successfully!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -268,8 +268,8 @@
|
||||
"DESCRIPTION": "Haz clic en el botón más abajo para iniciar sesión otra vez."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Su cuota de solicitudes autenticadas se ha agotado.",
|
||||
"DESCRIPTION": "Borrar o aumentar el límite de esta instancia de ZITADEL."
|
||||
"TITLE": "Tu instancia está bloqueada.",
|
||||
"DESCRIPTION": "Pide a tu administrador de instancia de ZITADEL que actualice la suscripción."
|
||||
},
|
||||
"INVALID_FORMAT": "El formato no es valido.",
|
||||
"NOTANEMAIL": "El valor proporcionado no es una dirección de email.",
|
||||
@ -1252,6 +1252,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Los usuarios pueden elegir entre los siguientes proveedores de identidad. Nota: Puedes usar los proveedores integrados en el sistema así como sólo los proveedores configurados para tu organización.",
|
||||
"ADVANCED": "Avanzado",
|
||||
"LIFETIMEDURATIONS": "Tiempos de vida de los inicios de sesión",
|
||||
"LIFETIME_INVALID": "El formulario contiene valores no válidos.",
|
||||
"SAVED": "¡Guardado con éxito!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -267,8 +267,8 @@
|
||||
"DESCRIPTION": "Cliquez sur le bouton ci-dessous pour vous reconnecter."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Ton quota de demandes authentifiées est épuisé.",
|
||||
"DESCRIPTION": "Supprimez ou augmentez la limite de cette instance ZITADEL."
|
||||
"TITLE": "Votre instance est bloquée.",
|
||||
"DESCRIPTION": "Demandez à votre administrateur d'instance ZITADEL de mettre à jour l'abonnement."
|
||||
},
|
||||
"INVALID_FORMAT": "Le format n'est pas valide",
|
||||
"NOTANEMAIL": "La valeur donnée n'est pas une adresse e-mail",
|
||||
@ -1250,6 +1250,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Les utilisateurs peuvent choisir parmi les fournisseurs d'identité disponibles ci-dessous. Note",
|
||||
"ADVANCED": "Avancé",
|
||||
"LIFETIMEDURATIONS": "Durée de vie des connexions",
|
||||
"LIFETIME_INVALID": "Le formulaire contient des valeurs non valides.",
|
||||
"SAVED": "Enregistré avec succès !"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -266,8 +266,8 @@
|
||||
"DESCRIPTION": "Clicca il pulsante per richiedere una nuova sessione."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "La quota di richieste autenticate è esaurita.",
|
||||
"DESCRIPTION": "Cancellare o aumentare il limite per questa istanza ZITADEL."
|
||||
"TITLE": "La tua istanza è bloccata.",
|
||||
"DESCRIPTION": "Chiedi all'amministratore dell'istanza ZITADEL di aggiornare l'abbonamento."
|
||||
},
|
||||
"INVALID_FORMAT": "Il formato non è valido.",
|
||||
"NOTANEMAIL": "Il valore dato non \u00e8 un indirizzo e-mail.",
|
||||
@ -1250,6 +1250,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Gli utenti possono scegliere tra gli IDP disponibili qui sotto. Nota: puoi usare i provider impostati nel sistema e quelli impostati della tua organizzazione.",
|
||||
"ADVANCED": "Impostazioni avanzate",
|
||||
"LIFETIMEDURATIONS": "Login Lifetimes",
|
||||
"LIFETIME_INVALID": "Login Lifetimes non sono validi",
|
||||
"SAVED": "Salvato con successo!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -268,8 +268,8 @@
|
||||
"DESCRIPTION": "下のボタンをクリックして、もう一度ログインする。"
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "認証されたリクエストのクォータを使い果たしました",
|
||||
"DESCRIPTION": "このZITADELインスタンスの制限を削除または増加させる"
|
||||
"TITLE": "あなたのインスタンスはブロックされています。",
|
||||
"DESCRIPTION": "ZITADELインスタンス管理者にサブスクリプションの更新を依頼してください。"
|
||||
},
|
||||
"INVALID_FORMAT": "不正なフォーマットです",
|
||||
"NOTANEMAIL": "入力された値がメールアドレスではありません。",
|
||||
@ -1247,6 +1247,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "ユーザーは、以下の利用可能なIDプロバイダーから選択できます。注:システムセットプロバイダーと、組織用に設定されたプロバイダーのみを使用できます。",
|
||||
"ADVANCED": "高度",
|
||||
"LIFETIMEDURATIONS": "ログインライフタイム",
|
||||
"LIFETIME_INVALID": "フォームに無効な値が含まれています。",
|
||||
"SAVED": "正常に保存されました!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -268,8 +268,8 @@
|
||||
"DESCRIPTION": "Кликнете на копчето подолу за повторна најава."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Вашиот квота за автентицирани барања е надмината.",
|
||||
"DESCRIPTION": "Отстранете или зголемете ја квотата за оваа ZITADEL инстанца."
|
||||
"TITLE": "Вашиот авторизациски токен е истечен.",
|
||||
"DESCRIPTION": "Кликнете на копчето подолу за повторна најава."
|
||||
},
|
||||
"INVALID_FORMAT": "Невалиден формат.",
|
||||
"NOTANEMAIL": "Внесената вредност не е е-пошта.",
|
||||
@ -1252,6 +1252,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Корисниците можат да избираат од достапните IDPs подолу. Забелешка: Можете да користите системски поставени IDPs, како и IDPs поставени само за вашата организација.",
|
||||
"ADVANCED": "Напредно",
|
||||
"LIFETIMEDURATIONS": "Време на траење на најавата",
|
||||
"LIFETIME_INVALID": "Формуларот содржи неважечки вредности.",
|
||||
"SAVED": "Успешно зачувано!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -268,8 +268,8 @@
|
||||
"DESCRIPTION": "Klik op de knop hieronder om opnieuw in te loggen."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Uw quotum voor geauthenticeerde aanvragen is opgebruikt.",
|
||||
"DESCRIPTION": "Verwijder of verhoog het quotumlimiet voor deze ZITADEL-instantie."
|
||||
"TITLE": "Uw instantie is geblokkeerd.",
|
||||
"DESCRIPTION": "Vraag uw ZITADEL instantiebeheerder om het abonnement bij te werken."
|
||||
},
|
||||
"INVALID_FORMAT": "De opmaak is ongeldig.",
|
||||
"NOTANEMAIL": "De opgegeven waarde is geen e-mailadres.",
|
||||
@ -1251,6 +1251,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Gebruikers kunnen kiezen uit de beschikbare identiteitsproviders hieronder. Opmerking: U kunt systeem ingestelde providers gebruiken evenals providers die alleen voor uw organisatie zijn ingesteld.",
|
||||
"ADVANCED": "Geavanceerd",
|
||||
"LIFETIMEDURATIONS": "Login Levensduur",
|
||||
"LIFETIME_INVALID": "Formulier bevat ongeldige waarde(n).",
|
||||
"SAVED": "Succesvol opgeslagen!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -267,8 +267,8 @@
|
||||
"DESCRIPTION": "Kliknij przycisk poniżej, aby ponownie się zalogować."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Twój limit uwierzytelnionych wniosków został wyczerpany.",
|
||||
"DESCRIPTION": "Usuń lub zwiększ limit dla tej instancji ZITADEL."
|
||||
"TITLE": "Twoja instancja jest zablokowana.",
|
||||
"DESCRIPTION": "Poproś administratora swojej instancji ZITADEL o aktualizację subskrypcji."
|
||||
},
|
||||
"INVALID_FORMAT": "Format jest nieprawidłowy.",
|
||||
"NOTANEMAIL": "Podana wartość nie jest adresem e-mail.",
|
||||
@ -1250,6 +1250,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Użytkownicy mogą wybrać z dostępnych poniżej dostawców tożsamości. Uwaga: Możesz korzystać z dostawców ustawionych przez system lub tylko dla twojej organizacji.",
|
||||
"ADVANCED": "Zaawansowane",
|
||||
"LIFETIMEDURATIONS": "Czasy trwania logowania",
|
||||
"LIFETIME_INVALID": "Formularz zawiera nieprawidłowe wartości.",
|
||||
"SAVED": "Pomyślnie zapisano!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -268,8 +268,8 @@
|
||||
"DESCRIPTION": "Clique no botão abaixo para fazer login novamente."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Sua cota para solicitações autenticadas está esgotada.",
|
||||
"DESCRIPTION": "Remova ou aumente o limite de cota para esta instância ZITADEL."
|
||||
"TITLE": "Sua instância está bloqueada.",
|
||||
"DESCRIPTION": "Peça ao administrador da sua instância ZITADEL para atualizar a assinatura."
|
||||
},
|
||||
"INVALID_FORMAT": "O formato é inválido.",
|
||||
"NOTANEMAIL": "O valor fornecido não é um endereço de e-mail.",
|
||||
@ -1252,6 +1252,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Os usuários podem escolher entre os provedores de identidade disponíveis abaixo. Observação: você também pode usar provedores definidos pelo sistema e provedores definidos apenas para sua organização.",
|
||||
"ADVANCED": "Avançado",
|
||||
"LIFETIMEDURATIONS": "Duração do login",
|
||||
"LIFETIME_INVALID": "O formulário contém valores inválidos.",
|
||||
"SAVED": "Salvo com sucesso!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -264,8 +264,8 @@
|
||||
"DESCRIPTION": "Нажмите кнопку ниже, чтобы войти снова."
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "Ваша квота на аутентифицированные запросы исчерпана.",
|
||||
"DESCRIPTION": "Удалите или увеличьте лимит квоты для этого экземпляра ZITADEL."
|
||||
"TITLE": "Ваш экземпляр заблокирован.",
|
||||
"DESCRIPTION": "Попросите администратора вашего экземпляра ZITADEL обновить подписку."
|
||||
},
|
||||
"INVALID_FORMAT": "Форматирование неверно.",
|
||||
"NOTANEMAIL": "Данное значение не является адресом электронной почты.",
|
||||
@ -1237,6 +1237,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "Пользователи могут выбирать из доступных поставщиков удостоверений, указанных ниже. Примечание. Вы можете использовать поставщиков, установленных системой, а также поставщиков, установленных только для вашей организации.",
|
||||
"ADVANCED": "Продвинутые настройки",
|
||||
"LIFETIMEDURATIONS": "Время входа в систему",
|
||||
"LIFETIME_INVALID": "Formularul conține valori nevalide.",
|
||||
"SAVED": "Успешно сохранено!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -267,8 +267,8 @@
|
||||
"DESCRIPTION": "点击下方按钮再次登录。"
|
||||
},
|
||||
"EXHAUSTED": {
|
||||
"TITLE": "你的认证请求配额已用完.",
|
||||
"DESCRIPTION": "删除或增加这个ZITADEL实例的限制。"
|
||||
"TITLE": "您的实例已被阻止。",
|
||||
"DESCRIPTION": "请联系您的 ZITADEL 实例管理员以更新订阅。"
|
||||
},
|
||||
"INVALID_FORMAT": "格式是无效的。",
|
||||
"NOTANEMAIL": "给定的值不是合法电子邮件地址。",
|
||||
@ -1249,6 +1249,7 @@
|
||||
"DESCRIPTIONCREATEMGMT": "用户可以从以下可用的身份提供者中进行选择。注意:您可为系统设置提供者也可以仅为您的组织单独设置提供者。",
|
||||
"ADVANCED": "高级设置",
|
||||
"LIFETIMEDURATIONS": "登录状态有效期",
|
||||
"LIFETIME_INVALID": "表单包含无效值。",
|
||||
"SAVED": "保存成功!"
|
||||
},
|
||||
"PRIVACY_POLICY": {
|
||||
|
@ -3305,15 +3305,15 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/jasmine@*", "@types/jasmine@~4.3.6":
|
||||
version "4.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-4.3.6.tgz#d9855fa9f808138488784610f888046bb9a59aff"
|
||||
integrity sha512-3N0FpQTeiWjm+Oo1WUYWguUS7E6JLceiGTriFrG8k5PU7zRLJCzLcWURU3wjMbZGS//a2/LgjsnO3QxIlwxt9g==
|
||||
"@types/jasmine@*", "@types/jasmine@~5.1.4":
|
||||
version "5.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-5.1.4.tgz#0de3f6ca753e10d1600ce1864ae42cfd47cf9924"
|
||||
integrity sha512-px7OMFO/ncXxixDe1zR13V1iycqWae0MxTaw62RpFlksUi5QuNWgQJFkTQjIOvrmutJbI7Fp2Y2N1F6D2R4G6w==
|
||||
|
||||
"@types/jasminewd2@~2.0.10":
|
||||
version "2.0.10"
|
||||
resolved "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.10.tgz"
|
||||
integrity sha512-J7mDz7ovjwjc+Y9rR9rY53hFWKATcIkrr9DwQWmOas4/pnIPJTXawnzjwpHm3RSxz/e3ZVUvQ7cRbd5UQLo10g==
|
||||
"@types/jasminewd2@~2.0.13":
|
||||
version "2.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/jasminewd2/-/jasminewd2-2.0.13.tgz#0b60c1fcd06277ea97efbbad5a02e0c1a4a8996a"
|
||||
integrity sha512-aJ3wj8tXMpBrzQ5ghIaqMisD8C3FIrcO6sDKHqFbuqAsI7yOxj0fA7MrRCPLZHIVUjERIwsMmGn/vB0UQ9u0Hg==
|
||||
dependencies:
|
||||
"@types/jasmine" "*"
|
||||
|
||||
@ -3344,10 +3344,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.7.0.tgz#c03de4572f114a940bc2ca909a33ddb2b925e470"
|
||||
integrity sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg==
|
||||
|
||||
"@types/opentype.js@^1.3.4":
|
||||
version "1.3.4"
|
||||
resolved "https://registry.npmjs.org/@types/opentype.js/-/opentype.js-1.3.4.tgz"
|
||||
integrity sha512-6fbXi67I07ugNM+FExwJnfuui2hD7hraD6nqjr3UnqsbBpxSkrtmO6tBubPdNAjqRT9TVkquVkNS9IkgTtq6/w==
|
||||
"@types/opentype.js@^1.3.8":
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/opentype.js/-/opentype.js-1.3.8.tgz#741be92429d1c2d64b5fa79cf692f74b49d6007f"
|
||||
integrity sha512-H6qeTp03jrknklSn4bpT1/9+1xCAEIU2CnjcWPkicJy8A1SKuthanbvoHYMiv79/2W3Xn1XE4gfSJFzt2U3JSw==
|
||||
|
||||
"@types/q@^0.0.32":
|
||||
version "0.0.32"
|
||||
@ -3430,10 +3430,10 @@
|
||||
dependencies:
|
||||
"@types/estree" "*"
|
||||
|
||||
"@types/uuid@^9.0.2":
|
||||
version "9.0.2"
|
||||
resolved "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz"
|
||||
integrity sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==
|
||||
"@types/uuid@^9.0.7":
|
||||
version "9.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.7.tgz#b14cebc75455eeeb160d5fe23c2fcc0c64f724d8"
|
||||
integrity sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==
|
||||
|
||||
"@types/ws@^8.5.5":
|
||||
version "8.5.5"
|
||||
@ -5705,10 +5705,10 @@ find-up@^6.3.0:
|
||||
locate-path "^7.1.0"
|
||||
path-exists "^5.0.0"
|
||||
|
||||
flag-icons@^6.7.0:
|
||||
version "6.9.3"
|
||||
resolved "https://registry.npmjs.org/flag-icons/-/flag-icons-6.9.3.tgz"
|
||||
integrity sha512-HIU4V8342pmBjk+zlvq0jGyHEifyP9976ynzQw8sLeONNcyMxW5I+NWY9OWGMrd9lkFjgfcnvRdD3MGd1ihHzQ==
|
||||
flag-icons@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/flag-icons/-/flag-icons-7.1.0.tgz#6898ae3b3a57e5a363e12478c1ef384aa62d641f"
|
||||
integrity sha512-AH4v++19bpC5P3Wh767top4wylJYJCWkFnvNiDqGHDxqSqdMZ49jpLXp8PWBHTTXaNQ+/A+QPrOwyiIGaiIhmw==
|
||||
|
||||
flat-cache@^3.0.4:
|
||||
version "3.0.4"
|
||||
@ -6269,10 +6269,10 @@ humanize-ms@^1.2.1:
|
||||
dependencies:
|
||||
ms "^2.0.0"
|
||||
|
||||
i18n-iso-countries@^7.6.0:
|
||||
version "7.6.0"
|
||||
resolved "https://registry.npmjs.org/i18n-iso-countries/-/i18n-iso-countries-7.6.0.tgz"
|
||||
integrity sha512-HPKjOUKS0BkjiY4ayrsuFbu7Ock++pXLs+FAOYl4WfTL5L0ploEH68fiRAP6Zev5g/jvMFt54KcPGJcb942wbg==
|
||||
i18n-iso-countries@^7.7.0:
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/i18n-iso-countries/-/i18n-iso-countries-7.7.0.tgz#33a0974d6ffbe864fb853325de3afb4717c54b52"
|
||||
integrity sha512-07zMatrSsR1Z+cnxW//7s14Xf4v5g6U6ORHPaH8+Ox4uPqV+y46Uq78veYV8H1DKTr76EfdjSeaTxHpnaYq+bw==
|
||||
dependencies:
|
||||
diacritics "1.3.0"
|
||||
|
||||
@ -8105,15 +8105,15 @@ prelude-ls@^1.2.1:
|
||||
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
|
||||
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
||||
|
||||
prettier-plugin-organize-imports@^3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.2.tgz"
|
||||
integrity sha512-e97lE6odGSiHonHJMTYC0q0iLXQyw0u5z/PJpvP/3vRy6/Zi9kLBwFAbEGjDzIowpjQv8b+J04PDamoUSQbzGA==
|
||||
prettier-plugin-organize-imports@^3.2.4:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz#77967f69d335e9c8e6e5d224074609309c62845e"
|
||||
integrity sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog==
|
||||
|
||||
prettier@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643"
|
||||
integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==
|
||||
prettier@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848"
|
||||
integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==
|
||||
|
||||
pretty-bytes@^5.3.0:
|
||||
version "5.6.0"
|
||||
@ -9506,10 +9506,10 @@ uuid@^8.3.2:
|
||||
resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz"
|
||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||
|
||||
uuid@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz"
|
||||
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
|
||||
uuid@^9.0.1:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
|
||||
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
|
||||
|
||||
v8-compile-cache@2.3.0:
|
||||
version "2.3.0"
|
||||
@ -9984,9 +9984,9 @@ zone.js@~0.10.3:
|
||||
resolved "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz"
|
||||
integrity sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==
|
||||
|
||||
zone.js@~0.13.1:
|
||||
version "0.13.1"
|
||||
resolved "https://registry.npmjs.org/zone.js/-/zone.js-0.13.1.tgz"
|
||||
integrity sha512-+bIeDAFEBYuXRuU3qGQvzdPap+N1zjM4KkBAiiQuVVCrHrhjDuY6VkUhNa5+U27+9w0q3fbKiMCbpJ0XzMmSWA==
|
||||
zone.js@~0.13.3:
|
||||
version "0.13.3"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.13.3.tgz#344c24098fa047eda6427a4c7ed486e391fd67b5"
|
||||
integrity sha512-MKPbmZie6fASC/ps4dkmIhaT5eonHkEt6eAy80K42tAm0G2W+AahLJjbfi6X9NPdciOE9GRFTTM8u2IiF6O3ww==
|
||||
dependencies:
|
||||
tslib "^2.3.0"
|
||||
|
@ -8,11 +8,13 @@ To add a new site to the already existing structure simply save the `md` file in
|
||||
|
||||
## Installation
|
||||
|
||||
Install dependencies with
|
||||
|
||||
```
|
||||
yarn install
|
||||
```
|
||||
|
||||
## Generate
|
||||
then run
|
||||
|
||||
```
|
||||
yarn generate
|
||||
@ -21,10 +23,18 @@ yarn generate
|
||||
|
||||
## Local Development
|
||||
|
||||
Start a local development server with
|
||||
|
||||
```
|
||||
yarn start
|
||||
```
|
||||
|
||||
When working on the API docs, run a local development server with
|
||||
|
||||
```
|
||||
yarn start:api
|
||||
```
|
||||
|
||||
## Container Image
|
||||
|
||||
If you just want to start docusaurus locally without installing node you can fallback to our container image.
|
||||
|
@ -4,9 +4,9 @@ title: Complement Token Flow
|
||||
|
||||
This flow is executed during the creation of tokens and token introspection.
|
||||
|
||||
## Pre Userinfo creation
|
||||
## Pre Userinfo creation (id_token / userinfo / introspection endpoint)
|
||||
|
||||
This trigger is called before userinfo are set in the token or response.
|
||||
This trigger is called before userinfo are set in the id_token or userinfo and introspection endpoint response.
|
||||
|
||||
### Parameters of Pre Userinfo creation
|
||||
|
||||
|
@ -68,8 +68,31 @@ Please check below the matrix for an overview where which scope is asserted.
|
||||
|
||||
## Custom Claims
|
||||
|
||||
Custom claims are being inserted into user tokens in addition to the standard claims.
|
||||
Your app can use custom claims to handle more complex scenarios, such as restricting access based on these claims.
|
||||
|
||||
You can add custom claims using the [complement token flow](/docs/apis/actions/complement-token) of the [actions feature](/docs/apis/actions/introduction).
|
||||
|
||||
Multiple examples of Actions that result in custom claims can be found in our [Marketplace for ZITADEL Actions](https://github.com/zitadel/actions).
|
||||
|
||||
### Static values as custom claim
|
||||
|
||||
```javascript reference
|
||||
https://github.com/zitadel/actions/blob/de69b56f6d0463817953b59a52ffd6afc6a366fb/examples/add_claim.js#L9-L11
|
||||
```
|
||||
|
||||
### Metadata as custom claim
|
||||
|
||||
```javascript reference
|
||||
https://github.com/zitadel/actions/blob/main/examples/add_metadata.js#L9-L15
|
||||
```
|
||||
|
||||
### Format roles claims
|
||||
|
||||
```javascript reference
|
||||
https://github.com/zitadel/actions/blob/main/examples/custom_roles.js#L20-L33
|
||||
```
|
||||
|
||||
## Reserved Claims
|
||||
|
||||
ZITADEL reserves some claims to assert certain data. Please check out the [reserved scopes](scopes#reserved-scopes).
|
||||
|
@ -57,4 +57,13 @@ Regardless of the error, the used http error code will be '200', which represent
|
||||
response will contain a StatusCode include a message which provides more information if an error occurred.
|
||||
|
||||
**Link to
|
||||
spec** [Assertions and Protocols for the OASIS Security Assertion Markup Language (SAML) V2.0 – Errata Composite](https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf)
|
||||
spec** [Assertions and Protocols for the OASIS Security Assertion Markup Language (SAML) V2.0 – Errata Composite](https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf)
|
||||
|
||||
## Custom attributes
|
||||
|
||||
Custom attributes are being inserted into SAML response if not already present.
|
||||
Your app can use custom claims to handle more complex scenarios, such as restricting access based on these claims.
|
||||
|
||||
You can add custom attributes using the [complement SAMLresponse](/docs/apis/actions/customize-samlresponse) of the [actions feature](/docs/apis/actions/introduction).
|
||||
|
||||
Examples of Actions that result in custom attributes can be found in our [Marketplace for ZITADEL Actions](https://github.com/zitadel/actions).
|
||||
|
@ -101,16 +101,16 @@ Our examples cover a range of programming languages and frameworks, so no matter
|
||||
</td>
|
||||
<td>Java Spring Boot Web</td>
|
||||
<td><a href="https://github.com/zitadel/zitadel-java" target="_blank"><i class="lab la-github"></i></a></td>
|
||||
<td></td>
|
||||
<td><a href="/examples/login/java-spring">Guide</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px">
|
||||
<img src="/docs/img/tech/php.svg" alt="php"/>
|
||||
</td>
|
||||
<td>PHP Web</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Symfony PHP Framework</td>
|
||||
<td><a href="https://github.com/zitadel/example-symfony-oidc" target="_blank"><i class="lab la-github"></i></a></td>
|
||||
<td><a href="/examples/login/symfony">Guide</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -174,9 +174,9 @@ Our examples cover a range of programming languages and frameworks, so no matter
|
||||
<td>
|
||||
<img src="/docs/img/tech/nodejs.svg" alt="node"/>
|
||||
</td>
|
||||
<td>NodeJS</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Node.js NestJS API</td>
|
||||
<td><a href="https://github.com/ehwplus/zitadel-nodejs-nestjs" target="_blank"><i class="lab la-github"></i></a></td>
|
||||
<td><a href="./secure-api/nodejs-nestjs">Guide</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -194,7 +194,7 @@ Our examples cover a range of programming languages and frameworks, so no matter
|
||||
</td>
|
||||
<td>Java Spring Boot API</td>
|
||||
<td><a href="https://github.com/zitadel/zitadel-java" target="_blank"><i class="lab la-github"></i></a></td>
|
||||
<td></td>
|
||||
<td><a href="/examples/login/java-spring">Guide</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -161,7 +161,7 @@ This line automatically refreshes a token before it expires.
|
||||
|
||||
Congratulations! You have successfully integrated your Angular application with ZITADEL!
|
||||
|
||||
If you get stuck, consider checking out our [example](https://github.com/zitadel/zitadel-angular) application. This application includes all the funcationalities mentioned in this quickstart. You can start by cloning the repository and replacing the _AuthConfig_ in the _AppModule_ with your own configuration. If you face issues, contact us or raise an issue on [GitHub](https://github.com/zitadel/zitadel).
|
||||
If you get stuck, consider checking out our [example](https://github.com/zitadel/zitadel-angular) application. This application includes all the functionalities mentioned in this quick-start. You can start by cloning the repository and replacing the _AuthConfig_ in the _AppModule_ with your own configuration. If you face issues, contact us or raise an issue on [GitHub](https://github.com/zitadel/zitadel).
|
||||
|
||||

|
||||
|
||||
|
177
docs/docs/examples/login/java-spring.md
Normal file
@ -0,0 +1,177 @@
|
||||
---
|
||||
title: ZITADEL with Java Spring Boot
|
||||
sidebar_label: Java Spring Boot
|
||||
---
|
||||
|
||||
This integration guide demonstrates the recommended way to incorporate ZITADEL into your Spring Boot web application.
|
||||
It explains how to enable user login in your application and how to fetch data from the user info endpoint.
|
||||
|
||||
By the end of this guide, your application will have login functionality and will be able to access the current user's profile.
|
||||
|
||||
:::info
|
||||
This documentation references our [example](https://github.com/zitadel/zitadel-java) on GitHub.
|
||||
You can either create your own application or directly run the example by providing the necessary arguments.
|
||||
:::
|
||||
|
||||
## Set up application
|
||||
|
||||
Before we begin developing our application, we need to perform a few configuration steps in the ZITADEL Console.
|
||||
You'll need to provide some information about your app. We recommend creating a new app to start from scratch. Navigate to your Project, then add a new application at the top of the page.
|
||||
Select the **Web** application type and continue.
|
||||
|
||||

|
||||
|
||||
We recommend that you use [Proof Key for Code Exchange (PKCE)](/apis/openidoauth/grant-types#proof-key-for-code-exchange) for all applications.
|
||||
|
||||

|
||||
|
||||
### Redirect URIs
|
||||
|
||||
The Redirect URIs field tells ZITADEL where it's allowed to redirect users after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
|
||||
The Post-logout redirect send the users back to a route on your application after they have logged out.
|
||||
|
||||
:::info
|
||||
If you are following along with the [example](https://github.com/zitadel/zitadel-java), set the dev mode to `true`, the Redirect URIs to `http://localhost:18080/webapp/login/oauth2/code/zitadel` and Post redirect URI to `http://localhost:18080/webapp`.
|
||||
:::
|
||||
|
||||

|
||||
|
||||
Continue and create the application.
|
||||
|
||||
### Client ID
|
||||
|
||||
After successful creation of the app, a pop-up will appear displaying the app's client ID. Copy the client ID, as you will need it to configure your Java client.
|
||||
|
||||

|
||||
|
||||
## Spring setup
|
||||
|
||||
Now that you have configured your web application on the ZITADEL side, you can proceed with the integration of your Spring client.
|
||||
This guide will reference the [example repository](https://github.com/zitadel/zitadel-java) and explain the necessary steps taken in there.
|
||||
If your starting from scratch, you can use the Spring Initializer with the [following setup](https://start.spring.io/#!type=maven-project&language=java&platformVersion=3.2.1&packaging=jar&jvmVersion=17&dependencies=web,thymeleaf,security,oauth2-client,lombok) as a base.
|
||||
|
||||
### Support classes
|
||||
|
||||
To be able to take the most out of ZITADELs RBAC, we first need to create a GrantedAuthoritiesMapper, that will map the role claims (`urn:zitadel:iam:org:project:roles`)
|
||||
into Spring Security `authiorities`, which can be used later on to determine the granted permissions.
|
||||
|
||||
So in your application, create a 'support/zitadel' package and in there the `ZitadelGrantedAuthoritiesMapper.java`:
|
||||
|
||||
```java reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/web/src/main/java/demo/support/zitadel/ZitadelGrantedAuthoritiesMapper.java
|
||||
```
|
||||
|
||||
The following two classes will provide you the possibility to access and use the user's token for requests to another API, e.g. the Spring Boot API example.
|
||||
|
||||
Directly create them in the `support` package.
|
||||
|
||||
```java reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/web/src/main/java/demo/support/TokenAccessor.java
|
||||
```
|
||||
|
||||
```java reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/web/src/main/java/demo/support/AccessTokenInterceptor.java
|
||||
```
|
||||
|
||||
### Application server configuration
|
||||
|
||||
As we have now our support classes, we can now create and configure the application server (and API client) itself.
|
||||
|
||||
In a new `config` package, create first the `WebClientConfig.java`, which will provide a RestTemplate using the previously created AccessTokenInterceptor:
|
||||
|
||||
```java reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/web/src/main/java/demo/config/WebClientConfig.java
|
||||
```
|
||||
|
||||
Additionally also create the `WebSecurityConfig.java` in the same package. This class will take care of the authentication, redirecting the user to the login,
|
||||
mapping the claims (using the ZitadelGrantedAuthoritiesMapper) and also provide the possibility for logout:
|
||||
|
||||
```java reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/web/src/main/java/demo/config/WebSecurityConfig.java
|
||||
```
|
||||
|
||||
For the authentication (and the server in general) to work, the application needs some configuration, so please provide the following to your `application.yml` (resources folder):
|
||||
|
||||
```yaml reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/web/src/main/resources/application.yml
|
||||
```
|
||||
|
||||
Note that both the `issuer-uri` as well as the `client-id` are only placeholders. You can either change them in here using the values provided by ZITADEL
|
||||
or pass them later on as arguments when starting the application.
|
||||
|
||||
### Add pages to your application
|
||||
|
||||
To be able to serve these pages create a `templates` directory in the `resources` folder.
|
||||
Now create three HTML files in the new `templates` folder and copy the content of the examples:
|
||||
|
||||
**index.html**
|
||||
|
||||
The home page will display the Userinfo from the authentication context and the granted roles / Spring security authorities.
|
||||
|
||||
```html reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/web/src/main/resources/templates/index.html
|
||||
```
|
||||
|
||||
**fragments.html**
|
||||
|
||||
The navigation to switch between the home and tasks page and allows the user to logout.
|
||||
|
||||
```html reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/web/src/main/resources/templates/fragments.html
|
||||
```
|
||||
|
||||
**tasks.html**
|
||||
|
||||
The tasks page allows to interact with the Spring Boot API example and display / add new tasks.
|
||||
|
||||
```html reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/web/src/main/resources/templates/tasks.html
|
||||
```
|
||||
|
||||
**UiController**
|
||||
|
||||
To serve these pages and handler their actions, you finally need a `UiController.java`:
|
||||
|
||||
```java reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/web/src/main/java/demo/web/UiController.java
|
||||
```
|
||||
|
||||
### Start your application
|
||||
|
||||
In case you've created your own application and depending on your development setup you might need to build the application first:
|
||||
|
||||
```bash
|
||||
mvn clean package -DskipTests
|
||||
```
|
||||
|
||||
You will need to provide the `issuer-uri` (your ZITADEL domain) and the `client-id` previously created:
|
||||
|
||||
```bash
|
||||
java \
|
||||
-Dspring.security.oauth2.client.provider.zitadel.issuer-uri=<see configuration above> \
|
||||
-Dspring.security.oauth2.client.registration.zitadel.client-id=<see configuration above> \
|
||||
-jar web/target/web-0.0.2-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
This could look like:
|
||||
|
||||
```bash
|
||||
java \
|
||||
-Dspring.security.oauth2.client.provider.zitadel.issuer-uri=https://my-domain.zitadel.cloud \
|
||||
-Dspring.security.oauth2.client.registration.zitadel.client-id=243861220627644836@example \
|
||||
-jar web/target/web-0.0.2-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
If you then visit on <http://localhost:18080/webapp> you should directly be redirected to your ZITADEL instance.
|
||||
After login with your existing user you will be presented the profile page:
|
||||
|
||||

|
||||
|
||||
## Completion
|
||||
|
||||
Congratulations! You have successfully integrated your Spring Boot web application with ZITADEL!
|
||||
|
||||
If you get stuck, consider checking out our [example](https://github.com/zitadel/zitadel-java) application.
|
||||
This application includes all the functionalities mentioned in this quickstart.
|
||||
You can directly start it with your own configuration. If you face issues, contact us or raise an issue on [GitHub](https://github.com/zitadel/zitadel-java/issues).
|
||||
|
408
docs/docs/examples/login/symfony.md
Normal file
@ -0,0 +1,408 @@
|
||||
---
|
||||
title: ZITADEL with Symfony PHP
|
||||
sidebar_label: Symfony
|
||||
---
|
||||
|
||||
This integration guide demonstrates the recommended way to incorporate ZITADEL into your Symfony PHP application.
|
||||
It explains how to enable user login in your application and how to fetch data from the user info endpoint.
|
||||
|
||||
By the end of this guide, your application will have login functionality with basic role mapping, access the current user's profile and a user list accessible by admins.
|
||||
|
||||
:::info
|
||||
This documentation references our [example](https://github.com/zitadel/example-symfony-oidc) on GitHub.
|
||||
:::
|
||||
|
||||
## ZITADEL setup
|
||||
|
||||
Before we can start building our application, we have to do a few configuration steps in ZITADEL Console.
|
||||
|
||||
### Project roles
|
||||
|
||||
The Example expects [user roles](guides/integrate/retrieve-user-roles) to be returned after login.
|
||||
Symfony uses `ROLE_USER` format.
|
||||
The application will take care of upper-casing and prefixing for us.
|
||||
Inside ZITADEL, you can use regular lower-case role names without prefixes, if you prefer.
|
||||
|
||||
> Symfony automatically assigns `ROLE_USER` to any authenticated user.
|
||||
|
||||
In your project settings make sure the "Assert Roles On Authentication" is enabled.
|
||||
|
||||

|
||||
|
||||
In the project Role tab, add 2 special roles:
|
||||
|
||||
- `admin`: Assigned to users that need access to the user list.
|
||||
- `foo`: Random role for display purposes
|
||||
|
||||
A `user` role is not required. This role is assumed by default for any authenticated user in Symfony.
|
||||
|
||||

|
||||
|
||||
Finally, we can assign the roles to users in the project's authorizations tab.
|
||||
|
||||

|
||||
|
||||
### Set up application and obtain secrets
|
||||
|
||||
Next you will need to provide some information about your app.
|
||||
|
||||
In your Project, add a new application at the top of the page.
|
||||
Select Web application type and continue.
|
||||
We use [Authorization Code](/apis/openidoauth/grant-types#authorization-code)for our Symfony application.
|
||||
|
||||

|
||||
|
||||
Select `CODE` in the next step. This makes sure you still get a secret. Note that the secret never gets exposed on the browser and is therefore kept in a confidential environment. Safe the generated
|
||||
|
||||

|
||||
|
||||
With the Redirect URIs field, you tell ZITADEL where it is allowed to redirect users to after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
|
||||
|
||||
For the example application we are writing use:
|
||||
|
||||
- `http://localhost:8000/login_check` as Redirect URI
|
||||
- `http://localhost:8000/logout` as post-logout URI.
|
||||
|
||||

|
||||
|
||||
After the final step you are presented with a client ID and secret.
|
||||
Copy and paste them to a safe location for later use by the application.
|
||||
The secret will not be displayed again, but you can regenerate one if you loose it.
|
||||
|
||||
## Setup new Symfony application
|
||||
|
||||
Now that you have configured your web application on the ZITADEL side, you can proceed with the integration of your Symfony client.
|
||||
The example is build on a [generated Symfony web app](https://symfony.com/doc/current/setup.html#creating-symfony-applications), using the following command:
|
||||
|
||||
:::info
|
||||
Skip this step if you are connecting ZITADEL to an existing application.
|
||||
:::
|
||||
|
||||
```bash
|
||||
symfony new my_project_directory --version="7.0.*" --webapp
|
||||
cd my_project_directory
|
||||
```
|
||||
|
||||
:::info
|
||||
The remainder of this guide assumes a Symfony project which already includes all web app bundles, such as security, routing and ORM.
|
||||
If you are using this guide against an existing project you must make sure the required bundles are installed using the `composer require` command.
|
||||
:::
|
||||
|
||||
### Install Symfony dependencies
|
||||
|
||||
To connect with ZITADEL through OpenID connect, you need to install the [Symfony OIDC bundle](https://github.com/Drenso/symfony-oidc). Run the following command:
|
||||
|
||||
```bash
|
||||
composer require drenso/symfony-oidc-bundle
|
||||
```
|
||||
|
||||
## Define the Symfony app
|
||||
|
||||
### Create a User class
|
||||
|
||||
First, we need to create a User class for the database, so we can persist user info between requests. In this case you don't need password authentication.
|
||||
Email addresses are not unique for ZITADEL users. There can be multiple user accounts with the same email address.
|
||||
See [User Constraints](https://zitadel.com/docs/concepts/structure/users#constraints) for more details.
|
||||
We will use the User Info `sub` claim as unique "display" name for the user. `sub` equals the unique User ID from ZITADEL.
|
||||
This creates a User Repository and Entity that implements the `UserInterface`:
|
||||
|
||||
:::info
|
||||
You can skip this step, if you already have an existing User object in your project.
|
||||
:::
|
||||
|
||||
```bash
|
||||
php bin/console make:user
|
||||
|
||||
The name of the security user class (e.g. User) [User]:
|
||||
> User
|
||||
|
||||
Do you want to store user data in the database (via Doctrine)? (yes/no) [yes]:
|
||||
> yes
|
||||
|
||||
Enter a property name that will be the unique "display" name for the user (e.g. email, username, uuid) [email]:
|
||||
> sub
|
||||
|
||||
Will this app need to hash/check user passwords? Choose No if passwords are not needed or will be checked/hashed by some other system (e.g. a single sign-on server).
|
||||
|
||||
Does this app need to hash/check user passwords? (yes/no) [yes]:
|
||||
> no
|
||||
```
|
||||
|
||||
Next, extend the User Entity with properties that we will obtain from ZITADEL and use in the application later.
|
||||
|
||||
> None of the following properties are required for authentication, but show how we can map User Info to a Symfony User Entity later. You can adjust the properties how you wish for your application.
|
||||
|
||||
```bash
|
||||
php bin/console make:entity
|
||||
|
||||
Class name of the entity to create or update (e.g. GrumpyElephant):
|
||||
> User
|
||||
|
||||
Your entity already exists! So let's add some new fields!
|
||||
|
||||
New property name (press <return> to stop adding fields):
|
||||
> display_name
|
||||
|
||||
Field type (enter ? to see all types) [string]:
|
||||
> string
|
||||
|
||||
Field length [255]:
|
||||
> 255
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> yes
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
> full_name
|
||||
|
||||
Field type (enter ? to see all types) [string]:
|
||||
> string
|
||||
|
||||
Field length [255]:
|
||||
>
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> yes
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
> email
|
||||
|
||||
Field type (enter ? to see all types) [string]:
|
||||
> string
|
||||
|
||||
Field length [255]:
|
||||
> 255
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> yes
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
> email_verified
|
||||
|
||||
Field type (enter ? to see all types) [string]:
|
||||
> boolean
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> yes
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
> created_at
|
||||
|
||||
Field type (enter ? to see all types) [datetime_immutable]:
|
||||
> datetime_immutable
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> no
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
> updated_at
|
||||
|
||||
Field type (enter ? to see all types) [datetime_immutable]:
|
||||
> datetime_immutable
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> no
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
>
|
||||
|
||||
Success!
|
||||
```
|
||||
|
||||
Now edit `src/Entity/User.php` to add some methods to pretty-print user data later in this example. Add import near the top of the file:
|
||||
|
||||
```php
|
||||
use DateTimeInterface;
|
||||
```
|
||||
|
||||
And extend the User class with this methods:
|
||||
|
||||
```php
|
||||
class User implements UserInterface
|
||||
{
|
||||
...
|
||||
|
||||
public function implodeRoles(): string
|
||||
{
|
||||
return implode(', ', $this->getRoles());
|
||||
}
|
||||
|
||||
public function formatCreatedAt(): string
|
||||
{
|
||||
return $this->created_at->format(DateTimeInterface::W3C);
|
||||
}
|
||||
|
||||
public function formatUpdatedAt(): string
|
||||
{
|
||||
return $this->updated_at->format(DateTimeInterface::W3C);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When you are done, the User Entity should look something like:
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Entity/User.php
|
||||
```
|
||||
|
||||
Edit the User Repository to have a `findOneBySub` method, used later for OIDC User Info updates.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Repository/UserRepository.php
|
||||
```
|
||||
|
||||
### Create a Security Provider
|
||||
|
||||
Next you will need to create a Security Provider that integrates the OIDC flow between Symfony and ZITADEL.
|
||||
Create a `ZitadelUserProvider` which implements `UserProviderInterface`, `OidcUserProviderInterface` and `LoggerAwareInterface`.
|
||||
`LoggerAwareInterface` is optional if you want debug logging.
|
||||
|
||||
> We called this a `ZitadelUserProvider` because it carries a custom scope and claim mapping from ZITADEL roles to the Symfony role system.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Security/ZitadelUserProvider.php
|
||||
```
|
||||
|
||||
You can customize the User Info that is obtained and stored by adjusting the `SCOPES` constant, the `updateUserEntity` method and the User Entity.
|
||||
|
||||
### Controllers and templates
|
||||
|
||||
We need to create couple of Controllers and templates to define the app.
|
||||
|
||||
#### Index
|
||||
|
||||
The index controller serves a public page on the `/` route and provides some basic links to the authenticated sections of the app.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Controller/IndexController.php
|
||||
```
|
||||
|
||||
The index template:
|
||||
|
||||
```twig reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/templates/index.html.twig
|
||||
```
|
||||
|
||||
#### Login
|
||||
|
||||
The login controller initiates the OIDC login flow by creating a Auth request and redirecting the user to ZITADEL.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Controller/LoginController.php
|
||||
```
|
||||
|
||||
#### Profile
|
||||
|
||||
The profile controller displays User Info of the currently authenticated user.
|
||||
Any authenticated user will have access to this page.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Controller/ProfileController.php
|
||||
```
|
||||
|
||||
The profile template maps the User Entity to a HTML page.
|
||||
|
||||
```twig reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/templates/profile.html.twig
|
||||
```
|
||||
|
||||
#### User list
|
||||
|
||||
The user list controller displays all users from the database, that were created during OIDC login.
|
||||
Only users with an admin role will have access to this page.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Controller/UserListController.php
|
||||
```
|
||||
|
||||
```twig reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/templates/user_list.html.twig
|
||||
```
|
||||
|
||||
## Configure and run the application
|
||||
|
||||
:::warning
|
||||
Never store and commit secrets in a `.env` file. Use a `env.local` file instead and make sure the file is in `.gitignore`.
|
||||
:::
|
||||
|
||||
### Database
|
||||
|
||||
Make sure you have a database configured in `.env` or `.env.local`. This example uses a local sqlite file to simplify setup:
|
||||
|
||||
```sh
|
||||
DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
|
||||
```
|
||||
|
||||
Create and run migrations:
|
||||
|
||||
```bash
|
||||
php bin/console make:migration
|
||||
php bin/console doctrine:migrations:migrate
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
A firewall needs to be defined along with roles based access control rules.
|
||||
In the following example we define the `zitadel_user_provider` as the security class we wrote earlier. We configure the main firewall to use the `zitadel_user_provider` and listen for logout requests on the `/logout` path. We tell the oidc module to enable End Session support.
|
||||
|
||||
In the `access_control` section we protect the `/users` and `/profile` routes based on roles. Roles are mapped from ZITADEL to Symfony in the `ZitadelUserProvider` we wrote earlier.
|
||||
|
||||
```yaml reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/config/packages/security.yaml
|
||||
```
|
||||
|
||||
### OIDC
|
||||
|
||||
The generated [`dresno_oidc.yaml`](https://github.com/zitadel/example-symfony-oidc/blob/main/config/packages/drenso_oidc.yaml) file can be edited to customize behavior of the OIDC bundle. For this example we stick with the default and use environment variables to connect to ZITADEL.
|
||||
|
||||
Edit `.env.local` to contain the details from the [Application setup section](#set-up-application-and-obtain-keys).
|
||||
|
||||
```sh
|
||||
OIDC_WELL_KNOWN_URL="https://tims-zitadel-instance-oj7iry.zitadel.cloud/.well-known/openid-configuration"
|
||||
OIDC_CLIENT_ID="248680248240075805@dev"
|
||||
OIDC_CLIENT_SECRET="BJPhEJULSUXseC4geqg5Yg4wWMoy7RgZKar86mbIpt8ZekC5kixMzYGcXLDeeJv7"
|
||||
```
|
||||
|
||||
> The well-known URL needs to be adjusted to your own instance domain.
|
||||
|
||||
Activate the route that is used as callback by the OIDC bundle:
|
||||
|
||||
```yaml reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/config/routes.yaml#L6-L7
|
||||
```
|
||||
|
||||
### Run
|
||||
|
||||
You can use a local Symfony server to test the application.
|
||||
|
||||
```bash
|
||||
symfony server:start --no-tls
|
||||
```
|
||||
|
||||
Visit http://localhost:8000 and click around.
|
||||
When you go to profile you will be redirected to login your user on ZITADEL.
|
||||
After login you should see some profile data of the current user.
|
||||
Upon clicking logout you are redirected to the homepage.
|
||||
Now you can click "users" and login with an account that has the admin role.
|
||||
|
||||
## Completion
|
||||
|
||||
Congratulations! You have successfully integrated your Symfony application with ZITADEL!
|
||||
|
||||
If you get stuck, consider checking out our [example](https://github.com/zitadel/example-symfony-oidc) application. This application includes all the functionalities mentioned in this quick-start. You can start by cloning the repository and defining a `.env.local` with your settings. If you face issues, contact us or raise an issue on [GitHub](https://github.com/zitadel/example-symfony-oidc/issues).
|
||||
|
||||
### What's next?
|
||||
|
||||
Now that you have enabled authentication, it's time for you to add more authorizations to your application using ZITADEL APIs. To do this, you can refer to the [docs](/apis/introduction) or check out the ZITADEL Console code on [GitHub](https://github.com/zitadel/zitadel) which uses gRPC and OpenAPI to access data.
|
129
docs/docs/examples/login/vue.md
Normal file
@ -0,0 +1,129 @@
|
||||
---
|
||||
title: ZITADEL with Vue
|
||||
sidebar_label: Vue
|
||||
---
|
||||
|
||||
This integration guide demonstrates the recommended way to incorporate ZITADEL into your Vue application.
|
||||
It explains how to enable user login in your application and how to fetch data from the user info endpoint.
|
||||
|
||||
By the end of this guide, your application will have login functionality and will be able to access the current user's profile.
|
||||
|
||||
:::tip
|
||||
This documentation references our [example](https://github.com/zitadel/zitadel-vue) on GitHub.
|
||||
It also uses the @zitadel/vue package with its default configuration.
|
||||
:::
|
||||
|
||||
## Set up application and obtain keys
|
||||
|
||||
Before we begin developing our application, we need to perform a few configuration steps in the ZITADEL Console.
|
||||
You'll need to provide some information about your app.
|
||||
We recommend creating a new app to start from scratch.
|
||||
Navigate to your project, then add a new application at the top of the page.
|
||||
Select the **User Agent** application type and continue.
|
||||
We recommend that you use [Proof Key for Code Exchange (PKCE)](/apis/openidoauth/grant-types#proof-key-for-code-exchange) for all single page applications.
|
||||
|
||||

|
||||
|
||||
### Redirect URIs
|
||||
|
||||
The redirect URIs field tells ZITADEL where it's allowed to redirect users after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
|
||||
The post logout redirect sends your users back to a public route on your application after they have logged out.
|
||||
|
||||
:::tip
|
||||
If you are following along with the [example](https://github.com/zitadel/zitadel-vue), set the dev mode switch to `true`.
|
||||
Configure a redirect URIs to *http:/<span></span>/localhost:5173/auth/signinwin/zitadel* and a post redirect URI to *http:/<span></span>/localhost:5173/*.
|
||||
:::
|
||||
|
||||
Continue and create the application.
|
||||
|
||||
### Refresh Token and Client ID
|
||||
|
||||
After successful creation of the app, make sure you tick the checkbox to enable refresh tokens.
|
||||
Also copy the client ID, as you will need it to configure your Vue client.
|
||||
|
||||

|
||||
|
||||
## Create a project role "admin" and assign it to your user
|
||||
|
||||
Also note the projects resource ID, as you will need it to configure your Vue client.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Vue setup
|
||||
|
||||
Now that you have configured your web application on the ZITADEL side, you can proceed with the integration of your Vue client.
|
||||
|
||||
### Install Vue dependencies
|
||||
|
||||
To conveniently connect with ZITADEL, you can install the [@zitadel/vue NPM package](https://www.npmjs.com/package/@zitadel/vue). Run the following command:
|
||||
|
||||
```bash
|
||||
npm install --save @zitadel/vue
|
||||
```
|
||||
|
||||
### Create and configure the auth service
|
||||
|
||||
The @zitadel/vue package provides a `createZITADELAuth()` function which sets some defaults and calls the underlying [vue-oidc-client packages](https://github.com/soukoku/vue-oidc-client) `createOidcAuth()` function.
|
||||
You can overwrite all the defaults with the aguments you pass to `createZITADELAuth()`.
|
||||
|
||||
Export the object returned from `createZITADELAuth()`
|
||||
|
||||
```ts reference
|
||||
https://github.com/zitadel/zitadel-vue/blob/main/src/services/zitadelAuth.ts
|
||||
```
|
||||
|
||||
### Register the auth service in your global variables when bootstrapping Vue
|
||||
|
||||
```ts reference
|
||||
https://github.com/zitadel/zitadel-vue/blob/main/src/main.ts
|
||||
```
|
||||
|
||||
### Add three new views to your application
|
||||
|
||||
The restricted admin view will only be shown if the user is authenticated and has the role "admin" in the apps project in ZITADEL.
|
||||
|
||||
```ts reference
|
||||
https://github.com/zitadel/zitadel-vue/blob/main/src/views/Admin.vue
|
||||
```
|
||||
|
||||
The restricted login view is shown to all authenticated users.
|
||||
It prints all the information it gets from the token and from the user info endpoint.
|
||||
|
||||
```ts reference
|
||||
https://github.com/zitadel/zitadel-vue/blob/main/src/views/Login.vue
|
||||
```
|
||||
|
||||
The public no access view is shown to authenticated users who navigate to a page they don't have access to based on their roles.
|
||||
|
||||
```ts reference
|
||||
https://github.com/zitadel/zitadel-vue/blob/main/src/views/NoAccess.vue
|
||||
```
|
||||
|
||||
### Add protected routes to your new pages as well as a Signout link
|
||||
|
||||
Note that we conditionally render the admin view or the no access view based on the user's roles.
|
||||
|
||||
```ts reference
|
||||
https://github.com/zitadel/zitadel-vue/blob/main/src/router/index.ts
|
||||
```
|
||||
|
||||
## Completion
|
||||
|
||||
Congratulations! You have successfully integrated your Vue application with ZITADEL!
|
||||
|
||||
If you get stuck, consider checking out the [ZITADEL Vue example application](https://github.com/zitadel/zitadel-vue).
|
||||
This application includes all the functionalities mentioned in this quickstart.
|
||||
You can start by cloning the repository and change the arguments to createZITADELAuth so they fit your requirements.
|
||||
If you face issues, contact us or [raise an issue on GitHub](https://github.com/zitadel/zitadel-vue/issues).
|
||||
|
||||

|
||||
|
||||
### What's next?
|
||||
|
||||
Now that you have enabled authentication, you are ready to call add authorization to your application using ZITADEL APIs.
|
||||
To do this, [refer to the API docs](/apis/introduction) or check out [the ZITADEL Console code on GitHub](https://github.com/zitadel/zitadel) which uses gRPC to access data.
|
||||
|
||||
For more information on how to create an Vue application, you can refer to [Vue](https://vuejs.org/guide/quick-start.html).
|
||||
If you want to learn more about the libraries wrapped by [@zitadel/vue](https://www.npmjs.com/package/@zitadel/vue), [read the docs for vue-oidc-client](https://github.com/soukoku/vue-oidc-client/wiki/V1-Docs).
|
@ -9,16 +9,17 @@ Management for resources.
|
||||
|
||||
## ZITADEL SDKs
|
||||
|
||||
| Language / Framework | Link Github | User Authentication | Manage resources | Notes |
|
||||
|----------------------|---------------------------------------------------------------|-----------------------------------------------------------|------------------|-------------|
|
||||
| .NET | [zitadel-net](https://github.com/smartive/zitadel-net) | ✔️ | ✔️ | `community` |
|
||||
| Elixir | [zitadel_api](https://github.com/jshmrtn/zitadel_api) | ✔️ | ✔️ | `community` |
|
||||
| Go | [zitadel-go](https://github.com/zitadel/zitadel-go) | 🚧 [WIP](https://github.com/zitadel/zitadel-go/tree/next) | ✔️ | `official` |
|
||||
| JVM | 🚧 [WIP](https://github.com/zitadel/zitadel/discussions/3650) | ❓ | ❓ | TBD |
|
||||
| Python | 🚧 [WIP](https://github.com/zitadel/zitadel/issues/3675) | ❓ | ❓ | TBD |
|
||||
| NodeJS | [@zitadel/node](https://www.npmjs.com/package/@zitadel/node) | ❌ | ✔️ | `community` |
|
||||
| Dart | [zitadel-dart](https://github.com/smartive/zitadel-dart) | ❌ | ✔️ | `community` |
|
||||
| Rust | [zitadel-rust](https://github.com/smartive/zitadel-rust) | ✔️ | ✔️ | `community` |
|
||||
| Language / Framework | Link Github | User Authentication | Manage resources | Notes |
|
||||
|----------------------|---------------------------------------------------------------|-----------------------------------------------------------|------------------|-------------------|
|
||||
| Go | [zitadel-go](https://github.com/zitadel/zitadel-go) | 🚧 [WIP](https://github.com/zitadel/zitadel-go/tree/next) | ✔️ | `official` |
|
||||
| Vue | [zitadel-vue](https://github.com/zitadel/zitadel-vue) | ✔️ | ❌ | `official` |
|
||||
| .NET | [zitadel-net](https://github.com/smartive/zitadel-net) | ✔️ | ✔️ | `community` |
|
||||
| Elixir | [zitadel_api](https://github.com/jshmrtn/zitadel_api) | ✔️ | ✔️ | `community` |
|
||||
| NodeJS | [@zitadel/node](https://www.npmjs.com/package/@zitadel/node) | ❌ | ✔️ | `community` |
|
||||
| Dart | [zitadel-dart](https://github.com/smartive/zitadel-dart) | ❌ | ✔️ | `community` |
|
||||
| Rust | [zitadel-rust](https://github.com/smartive/zitadel-rust) | ✔️ | ✔️ | `community` |
|
||||
| JVM | 🚧 [WIP](https://github.com/zitadel/zitadel/discussions/3650) | ❓ | ❓ | TBD |
|
||||
| Python | 🚧 [WIP](https://github.com/zitadel/zitadel/issues/3675) | ❓ | ❓ | TBD |
|
||||
|
||||
## Missing SDK
|
||||
|
||||
|
283
docs/docs/examples/secure-api/java-spring.md
Normal file
@ -0,0 +1,283 @@
|
||||
---
|
||||
title: ZITADEL with Java Spring Boot
|
||||
sidebar_label: Java Spring Boot
|
||||
---
|
||||
|
||||
This integration guide shows you how to integrate **ZITADEL** into your Java Spring Boot API. It demonstrates how to secure your API using
|
||||
OAuth 2 Token Introspection.
|
||||
|
||||
At the end of the guide you should have an API with a protected endpoint.
|
||||
|
||||
:::info
|
||||
This documentation references our [example](https://github.com/zitadel/zitadel-java) on GitHub.
|
||||
You can either create your own application or directly run the example by providing the necessary arguments.
|
||||
:::
|
||||
|
||||
## Set up application
|
||||
|
||||
Before we begin developing our API, we need to perform a few configuration steps in the ZITADEL Console.
|
||||
You'll need to provide some information about your app. We recommend creating a new app to start from scratch. Navigate to your Project, then add a new application at the top of the page.
|
||||
Select the **API** application type and continue.
|
||||
|
||||

|
||||
|
||||
Select Basic Auth for authenticating at the Introspection Endpoint.
|
||||
|
||||

|
||||
|
||||
After successful creation of the app, a pop-up will appear displaying the app's client ID. Copy the client ID and secret, as you will need it to configure your Java client.
|
||||
|
||||

|
||||
|
||||
## Spring Setup
|
||||
|
||||
Now that you have configured your web application on the ZITADEL side, you can proceed with the integration of your Spring client.
|
||||
This guide will reference the [example repository](https://github.com/zitadel/zitadel-java) and explain the necessary steps taken in there.
|
||||
If your starting from scratch, you can use the Spring Initializer with the [following setup](https://start.spring.io/#!type=maven-project&language=java&platformVersion=3.2.1&packaging=jar&jvmVersion=17&dependencies=web,lombok,oauth2-resource-server) as a base.
|
||||
|
||||
### Support class
|
||||
|
||||
To be able to take the most out of ZITADELs RBAC, we first need to create a CustomAuthorityOpaqueTokenIntrospector, that will
|
||||
customize the introspection behaviour and map the role claims (`urn:zitadel:iam:org:project:roles`)
|
||||
into Spring Security `authiorities`, which can be used later on to determine the granted permissions.
|
||||
|
||||
So in your application, create a `support/zitadel` package and in there the `CustomAuthorityOpaqueTokenIntrospector.java`:
|
||||
|
||||
```java reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/api/src/main/java/demo/app/support/zitadel/CustomAuthorityOpaqueTokenIntrospector.java
|
||||
```
|
||||
|
||||
### Application server configuration
|
||||
|
||||
As we have now our support class, we can now create and configure the application server itself.
|
||||
|
||||
In a new `config` package, create the `WebSecurityConfig.java`.
|
||||
This class will take care of the authorization by require the calls on `/api/tasks` to be authorized. Any other endpoint will be public by default.
|
||||
It will also use the just created CustomAuthorityOpaqueTokenIntrospector for the introspection call:
|
||||
|
||||
```java reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/api/src/main/java/demo/app/config/WebSecurityConfig.java
|
||||
```
|
||||
|
||||
For the authorization (and the server in general) to work, the application needs some configuration, so please provide the following to your `application.yml` (resources folder):
|
||||
|
||||
```yaml reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/api/src/main/resources/application.yml
|
||||
```
|
||||
|
||||
Note that the `introspection-uri`, `client-id` and `client-secret` are only placeholders. You can either change them in here using the values provided by ZITADEL
|
||||
or pass them later on as arguments when starting the application.
|
||||
|
||||
### Create example API
|
||||
|
||||
Create a `api` package with a `ExampleController.java` file with the content below. This will create an API with three endpoints / methods:
|
||||
- `/api/healthz`: can be called by anyone and always returns `OK`
|
||||
- `/api/tasks (GET)`: requires authorization and returns the available tasks
|
||||
- `/api/tasks (POST)`: requires authorization with granted `admin` role and adds the task to the list
|
||||
|
||||
If authorization is required, the token must not be expired and the API has to be part of the audience (either client_id or project_id).
|
||||
|
||||
For tests we will use a Personal Access Token or the [Java Spring web example](../login/java-spring).
|
||||
|
||||
```java reference
|
||||
https://github.com/zitadel/zitadel-java/blob/main/api/src/main/java/demo/app/api/ExampleController.java
|
||||
```
|
||||
|
||||
## Test API
|
||||
|
||||
In case you've created your own application and depending on your development setup you might need to build the application first:
|
||||
|
||||
```bash
|
||||
mvn clean package -DskipTests
|
||||
```
|
||||
|
||||
You will need to provide the `introspection-uri` (your ZITADEL domain> /oauth/v2/introspect), the `client-id` and `client-secret` previously created:
|
||||
|
||||
```bash
|
||||
java \
|
||||
-Dspring.security.oauth2.resourceserver.opaquetoken.introspection-uri=<see configuration above> \
|
||||
-Dspring.security.oauth2.resourceserver.opaquetoken.client-id=<see configuration above> \
|
||||
-Dspring.security.oauth2.resourceserver.opaquetoken.client-secret=<see configuration above> \
|
||||
-jar api/target/api-0.0.2-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
This could look like:
|
||||
|
||||
```bash
|
||||
java \
|
||||
-Dspring.security.oauth2.resourceserver.opaquetoken.introspection-uri=https://my-domain.zitadel.cloud/oauth/v2/introspect \
|
||||
-Dspring.security.oauth2.resourceserver.opaquetoken.client-id=243861220627644836@example \
|
||||
-Dspring.security.oauth2.resourceserver.opaquetoken.client-secret=WJKLF3kfPOi3optkg9vi3jmfjv8oj32nfiäohj!FSC09RWUSR \
|
||||
-jar web/target/web-0.0.2-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
### Public endpoint
|
||||
|
||||
Now you can call the API by browser or curl. Try the healthz endpoint first:
|
||||
|
||||
```bash
|
||||
curl -i http://localhost:18090/api/healthz
|
||||
```
|
||||
|
||||
it should return something like:
|
||||
|
||||
```
|
||||
HTTP/1.1 200
|
||||
Vary: Origin
|
||||
Vary: Access-Control-Request-Method
|
||||
Vary: Access-Control-Request-Headers
|
||||
X-Content-Type-Options: nosniff
|
||||
X-XSS-Protection: 0
|
||||
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
||||
Pragma: no-cache
|
||||
Expires: 0
|
||||
X-Frame-Options: DENY
|
||||
Content-Type: text/plain;charset=UTF-8
|
||||
Content-Length: 2
|
||||
Date: Mon, 15 Jan 2024 09:07:21 GMT
|
||||
|
||||
OK
|
||||
```
|
||||
|
||||
### Task list
|
||||
|
||||
and the task list endpoint:
|
||||
|
||||
```bash
|
||||
curl -i http://localhost:18090/api/tasks
|
||||
```
|
||||
|
||||
it will return:
|
||||
|
||||
```
|
||||
HTTP/1.1 401
|
||||
Vary: Origin
|
||||
Vary: Access-Control-Request-Method
|
||||
Vary: Access-Control-Request-Headers
|
||||
WWW-Authenticate: Bearer
|
||||
X-Content-Type-Options: nosniff
|
||||
X-XSS-Protection: 0
|
||||
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
||||
Pragma: no-cache
|
||||
Expires: 0
|
||||
X-Frame-Options: DENY
|
||||
Content-Length: 0
|
||||
Date: Mon, 15 Jan 2024 09:07:55 GMT
|
||||
```
|
||||
|
||||
Get a valid access_token for the API. You can either achieve this by getting an access token with the project_id in the audience
|
||||
(e.g. by using the [Spring Boot web example](../login/java-spring)) use a PAT of a service account.
|
||||
|
||||
If you provide a valid Bearer Token:
|
||||
|
||||
```bash
|
||||
curl -i -H "Authorization: Bearer ${token}" http://localhost:18090/api/tasks
|
||||
```
|
||||
|
||||
it will return an empty list:
|
||||
```
|
||||
HTTP/1.1 200
|
||||
Vary: Origin
|
||||
Vary: Access-Control-Request-Method
|
||||
Vary: Access-Control-Request-Headers
|
||||
X-Content-Type-Options: nosniff
|
||||
X-XSS-Protection: 0
|
||||
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
||||
Pragma: no-cache
|
||||
Expires: 0
|
||||
X-Frame-Options: DENY
|
||||
Content-Type: application/json
|
||||
Transfer-Encoding: chunked
|
||||
Date: Mon, 15 Jan 2024 09:15:10 GMT
|
||||
|
||||
[]
|
||||
```
|
||||
|
||||
### Try to add a new task
|
||||
|
||||
Let's see what happens if you call the tasks endpoint:
|
||||
|
||||
```bash
|
||||
curl -i -X POST -H "Authorization: Bearer ${token}" -H "Content-Type: application/json" --data 'my new task' http://localhost:18090/api/tasks
|
||||
```
|
||||
|
||||
it will complain with a permission denied (missing `admin` role):
|
||||
```
|
||||
HTTP/1.1 403
|
||||
Vary: Origin
|
||||
Vary: Access-Control-Request-Method
|
||||
Vary: Access-Control-Request-Headers
|
||||
WWW-Authenticate: Bearer error="insufficient_scope", error_description="The request requires higher privileges than provided by the access token.", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
|
||||
X-Content-Type-Options: nosniff
|
||||
X-XSS-Protection: 0
|
||||
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
||||
Pragma: no-cache
|
||||
Expires: 0
|
||||
X-Frame-Options: DENY
|
||||
Content-Length: 0
|
||||
Date: Mon, 15 Jan 2024 09:24:39 GMT
|
||||
```
|
||||
|
||||
### Add admin role
|
||||
|
||||
So let's create the role and grant it to the user. To do so, go to your project in ZITADEL Console
|
||||
and create the role by selecting `Roles` in the navigation and then clicking on the `New Role` button.
|
||||
Finally, create the role as shown below:
|
||||
|
||||

|
||||
|
||||
After you have created the role, let's grant it the user, who requested the tasks.
|
||||
Click on `Authorization` in the navigation and create a new one by selecting the user and the `admin` role.
|
||||
After successful creation, it should look like:
|
||||
|
||||

|
||||
|
||||
So you should now be able to add a new task:
|
||||
|
||||
```bash
|
||||
curl -i -X POST -H "Authorization: Bearer ${token}" -H "Content-Type: application/json" --data 'my new task' http://localhost:18090/api/tasks
|
||||
```
|
||||
|
||||
which will report back the successful addition:
|
||||
```
|
||||
HTTP/1.1 200
|
||||
Vary: Origin
|
||||
Vary: Access-Control-Request-Method
|
||||
Vary: Access-Control-Request-Headers
|
||||
X-Content-Type-Options: nosniff
|
||||
X-XSS-Protection: 0
|
||||
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
||||
Pragma: no-cache
|
||||
Expires: 0
|
||||
X-Frame-Options: DENY
|
||||
Content-Type: application/json
|
||||
Content-Length: 10
|
||||
Date: Mon, 15 Jan 2024 09:26:11 GMT
|
||||
|
||||
task added
|
||||
```
|
||||
|
||||
Let's now retrieve the task list again:
|
||||
|
||||
```bash
|
||||
curl -i -H "Authorization: Bearer ${token}" http://localhost:18090/api/tasks
|
||||
```
|
||||
|
||||
As you can see your new task is listed:
|
||||
```
|
||||
HTTP/1.1 200
|
||||
Vary: Origin
|
||||
Vary: Access-Control-Request-Method
|
||||
Vary: Access-Control-Request-Headers
|
||||
X-Content-Type-Options: nosniff
|
||||
X-XSS-Protection: 0
|
||||
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
||||
Pragma: no-cache
|
||||
Expires: 0
|
||||
X-Frame-Options: DENY
|
||||
Content-Type: application/json
|
||||
Transfer-Encoding: chunked
|
||||
Date: Mon, 15 Jan 2024 09:26:48 GMT
|
||||
|
||||
["my new task"]
|
||||
```
|
71
docs/docs/examples/secure-api/nodejs-nestjs.md
Normal file
@ -0,0 +1,71 @@
|
||||
---
|
||||
title: ZITADEL with Node.js
|
||||
sidebar_label: Node.js
|
||||
---
|
||||
|
||||
# ZITADEL with Node.js (NestJS)
|
||||
|
||||
This documentation section guides you through the process of integrating ZITADEL into your Node.js backend using the NestJS framework. The provided example demonstrates authentication using an OIDC (OAuth2) token introspection strategy with a ZITADEL service account for machine-to-machine communication.
|
||||
|
||||
## Overview
|
||||
|
||||
The NestJS API includes a single secured route that prints "Hello World!" when authenticated. The API expects an authorization header with a valid JWT, serving as a bearer token to authenticate the user when calling the API. The API will validate the access token on the [introspect endpoint](https://zitadel.com/docs/apis/openidoauth/endpoints#introspection_endpoint) and receive the user from ZITADEL.
|
||||
|
||||
The API application utilizes [JWT with Private Key](https://zitadel.com/docs/apis/openidoauth/authn-methods#jwt-with-private-key) for authentication against ZITADEL and accessing the introspection endpoint. Make sure to create an API Application within Zitadel and download the JSON. In this instance, we use this service account, so make sure to provide the secrets in the example application via environmental variables.
|
||||
|
||||
## Overview
|
||||
|
||||
The NestJS API includes a private endpoint `GET http://localhost:${APP_PORT}/api/v1/app`, which returns "Hello World" when authenticated. The authentication is performed using a JWT obtained through the token introspection strategy.
|
||||
|
||||
## Running the Example
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Make sure you have Node.js and npm installed on your machine.
|
||||
|
||||
### ZITADEL Configuration for the API
|
||||
|
||||
1. Create a ZITADEL instance and a project by following the steps [here](https://zitadel.com/docs/guides/start/quickstart#2-create-your-first-instance).
|
||||
|
||||
2. Set up an API application within your project:
|
||||
- Create a new application of type "API" with authentication method "Private Key".
|
||||
- Create a and save the Private Key JSON file.
|
||||
|
||||
### Create and Run the API
|
||||
|
||||
Clone or download the [example repository](https://github.com/ehwplus/zitadel-nodejs-nestjs):
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ehwplus/zitadel-nodejs-nestjs && cd zitadel-nodejs-nestjs
|
||||
```
|
||||
|
||||
and follow the instructions here: https://github.com/ehwplus/zitadel-nodejs-nestjs/blob/main/README.md#installation
|
||||
|
||||
### Test the API
|
||||
|
||||
Call the API without authorization headers:
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url http://localhost:${APP_PORT}/api/v1/app
|
||||
```
|
||||
|
||||
You should get a response with Status Code 401 and an error message.
|
||||
|
||||
Now, add an authorization header with a valid JWT obtained through ZITADEL:
|
||||
|
||||
```bash
|
||||
export JWT=your-valid-jwt
|
||||
|
||||
curl --request GET \
|
||||
--url http://localhost:${APP_PORT}/api/v1/app \
|
||||
--header "authorization: Bearer $JWT"
|
||||
```
|
||||
|
||||
You should now receive a response with Status Code 200 and the message:
|
||||
|
||||
```json
|
||||
"Hello World!"
|
||||
```
|
||||
|
||||
Congratulations! You have successfully integrated ZITADEL authentication into your NestJS API using the Token Introspection strategy.
|
@ -31,9 +31,11 @@ curl --request POST \
|
||||
--header 'Authorization: Bearer '"$TOKEN"''\
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"idp_id": "$IDP_ID",
|
||||
"successUrl": "https://custom.com/login/idp/success",
|
||||
"failureUrl": "https://custom.com/login/idp/fail"
|
||||
"idpId": "$IDP_ID",
|
||||
"urls": {
|
||||
"successUrl": "https://custom.com/login/idp/success",
|
||||
"failureUrl": "https://custom.com/login/idp/fail"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
|
@ -13,10 +13,11 @@ At the moment we provide only "Credit Card" payment
|
||||
|
||||
Once a payment method is configured, it can be selected directly in the instance creation process.
|
||||
|
||||
## Customer
|
||||
## Customer
|
||||
|
||||
To be able to create correct billings we will need some customer information from you.
|
||||
This includes the following fields:
|
||||
|
||||
- Name
|
||||
- Country
|
||||
- Email address
|
||||
@ -25,6 +26,16 @@ This includes the following fields:
|
||||
- Postal Code
|
||||
- City
|
||||
|
||||
## Tax ID
|
||||
|
||||
If available, enter your tax ID type and VAT number.
|
||||
The tax ID will be shown on the invoice.
|
||||
|
||||
:::info Reverse Charge
|
||||
When you enter the tax ID we will automatically calculate taxability.
|
||||
Depending on your billing address we will mark the invoice as reverse charge.
|
||||
:::
|
||||
|
||||
## Update Billing Information
|
||||
|
||||
You will only need to add billing information if your instance is in the paid tier. There are two options on how to add your billing info.
|
||||
@ -32,7 +43,6 @@ You will only need to add billing information if your instance is in the paid ti
|
||||
2. Go to the billing menu and add a new payment method. You will be able to choose the added method, when upgrading the instance to the paid tier.
|
||||
3. Add the billing information directly during the upgrade process.
|
||||
|
||||
|
||||
## Invoices
|
||||
|
||||
We show all you invoices, and you are able to download them directly in the Customer Portal.
|
42
docs/docs/guides/manage/cloud/settings.md
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
title: Settings
|
||||
---
|
||||
|
||||
Manage your team, email subscriptions, and billing information on the [Settings](https://zitadel.com/admin/settings) page.
|
||||
|
||||
## Team name
|
||||
|
||||
Change your ZITADEL Cloud team name by entering a new name.
|
||||
Confirm the changes by clicking the Change button.
|
||||
|
||||
## Notifications and newsletters
|
||||
|
||||
You can subscribe and unsubscribe to notifications and newsletters:
|
||||
|
||||
- Onboarding: Welcome information for new users
|
||||
- Newsletter: Regular newsletter on ZITADEL
|
||||
- Product News: Receive product updates
|
||||
- Security: Receive notifications related to security issues
|
||||
|
||||
:::info Technical Advisories
|
||||
If you want to stay up to date on our technical advisories, we recommend [subscribing here to the mailing list](https://zitadel.com/docs/support/technical_advisory#subscribe-to-our-mailing-list).
|
||||
|
||||
Technical advisories are notices that report major issues with ZITADEL Self-Hosted or the ZITADEL Cloud platform that could potentially impact security or stability in production environments.
|
||||
:::
|
||||
|
||||
You can also manage your subscriptions by clicking the unsubscribe link in the emails.
|
||||
|
||||
:::info Mandatory Information
|
||||
We are required to inform you about changes to the terms of service or based on regulatory requirements. You can't unsubscribe to these notifications.
|
||||
:::
|
||||
|
||||
## Delete team
|
||||
|
||||
Permanently delete your ZITADEL Cloud account.
|
||||
This will delete your team and delete all associated information.
|
||||
|
||||
Click **Delete Account** and confirm the next step.
|
||||
|
||||
## Update billing information
|
||||
|
||||
Refer to the [billing guide](./billing.md).
|
@ -105,7 +105,7 @@ Go to the "Advanced" section, per default login with phone number should be allo
|
||||
## Embedding ZITADEL in an iFrame
|
||||
|
||||
To maximise the security during login and in the Console UI, ZITADEL follows security best practices by setting a
|
||||
Content-Security-Policy (CSP) and X-Frame-Options:
|
||||
Content-Security-Policy (CSP), X-Frame-Options and cookies with SameSite Lax:
|
||||
|
||||
```
|
||||
Content-Security-Policy: frame-ancestors 'none'
|
||||
@ -136,7 +136,13 @@ This will change the CSP to the following:
|
||||
Content-Security-Policy: frame-ancestors https://custom-domain.com
|
||||
```
|
||||
|
||||
and remove the X-Frame-Options header.
|
||||
remove the X-Frame-Options header and change the SameSite to `None`.
|
||||
|
||||
:::note
|
||||
Please note, that SameSite None requires the cookie to be flagged `secure`, which means it must be sent over TLS (HTTPS) or localhost.
|
||||
This also means that domains other than localhost must use TLS for this option to work.
|
||||
This is due to browser restrictions: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#none
|
||||
:::
|
||||
|
||||
### Disable Multi-factor (MFA) Prompt
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Frontend and Back-end API Communication in ZITADEL
|
||||
sidebar_label: Frontent and API Communcation
|
||||
sidebar_label: Frontend and API Communication
|
||||
---
|
||||
|
||||
This guide contains a use case and ZITADEL integration.
|
||||
|
@ -32,7 +32,7 @@ Service users that authenticate or access the management API are counted against
|
||||
|
||||
### Active external identity providers
|
||||
|
||||
To calculate the monthly amount we take maximum activated external identity providers on each day over a given month.
|
||||
To calculate the monthly amount we take the sum of activated external identity providers over all instances on each day and calculate the average over a given month, rounded up to the next integer.
|
||||
Excluded are configured identity providers that are not activated.
|
||||
|
||||
### Action minutes
|
||||
|
@ -31,7 +31,7 @@ Support features for ZITADEL Cloud subscriptions are as follows:
|
||||
Subscription Plans | Free | Production | Enterprise Cloud
|
||||
--- | --- | --- | ---
|
||||
[Support hours](#support-hours) | Business hours | Business hours | bespoke (up to 24x7)
|
||||
[Response Time](#slo---initial-response-time) (Severity 1) | Best effort | 48 business hours | bespoke (as low as 30min)
|
||||
[Response Time](#slo---initial-response-time) (Severity 1) | n/a | 48 business hours | bespoke (as low as 30min)
|
||||
[Community support](#community-support) | yes | yes | yes
|
||||
[Professional support](#professional-support) | no | yes | yes
|
||||
[Enterprise supported features](/docs/support/software-release-cycles-support.md#enterprise-supported) | no | no | yes
|
||||
@ -101,6 +101,9 @@ If we fail to provide the initial response time objective, you will be entitled
|
||||
|
||||
Community support for ZITADEL is available on our website, our [public chat](https://zitadel.com/chat), and [GitHub](https://github.com/zitadel/).
|
||||
|
||||
We do only guarantee response times to Tickets reported via [professional support](#professional-support) channels only.
|
||||
If you are an eligible customer, please use Tickets for critical or urgent issues.
|
||||
|
||||
#### Professional support
|
||||
|
||||
- Support is available in English
|
||||
|
@ -3,91 +3,6 @@ title: Set up ZITADEL on Kubernetes
|
||||
sidebar_label: Kubernetes
|
||||
---
|
||||
|
||||
import Disclaimer from './_disclaimer.mdx'
|
||||
import DefaultUser from './_defaultuser.mdx'
|
||||
import Next from './_next.mdx'
|
||||
import NoteInstanceNotFound from './troubleshooting/_note_instance_not_found.mdx';
|
||||
For getting started with an easily testable insecure setup with Postgres, follow the [Insecure Postgres Example](https://github.com/zitadel/zitadel-charts/tree/main/examples/1-postgres-insecure).
|
||||
|
||||
|
||||
Installation and configuration details are described in the [open source ZITADEL charts repo](https://github.com/zitadel/zitadel-charts).
|
||||
By default, the chart installs a secure and highly available ZITADEL instance.
|
||||
For running an easily testable, insecure, non-HA ZITADEL instance, run the following commands.
|
||||
|
||||
|
||||
## Add the Helm Repositories for CockroachDB and ZITADEL
|
||||
|
||||
```bash
|
||||
helm repo add cockroachdb https://charts.cockroachdb.com/
|
||||
helm repo add zitadel https://charts.zitadel.com
|
||||
```
|
||||
|
||||
After you have your repositories added,
|
||||
you can setup ZITADEL and either
|
||||
- initialize an [IAM owner who is a human user](#setup-zitadel-and-a-human-admin) or
|
||||
- initialize an [IAM owner who is a service account](#setup-zitadel-and-a-service-account-admin)
|
||||
|
||||
## Setup ZITADEL and a Human Admin
|
||||
|
||||
```bash
|
||||
# Install CockroachDB
|
||||
helm install crdb cockroachdb/cockroachdb \
|
||||
--set fullnameOverride=crdb \
|
||||
--set conf.single-node=true \
|
||||
--set statefulset.replicas=1
|
||||
|
||||
# Install ZITADEL
|
||||
helm install my-zitadel zitadel/zitadel \
|
||||
--set zitadel.masterkey="MasterkeyNeedsToHave32Characters" \
|
||||
--set zitadel.configmapConfig.ExternalSecure=false \
|
||||
--set zitadel.configmapConfig.TLS.Enabled=false \
|
||||
--set zitadel.secretConfig.Database.cockroach.User.Password="a-zitadel-db-user-password" \
|
||||
--set replicaCount=1
|
||||
|
||||
# Make ZITADEL locally accessible
|
||||
kubectl port-forward svc/my-zitadel 8080
|
||||
```
|
||||
|
||||
<DefaultUser components={props.components} />
|
||||
|
||||
<NoteInstanceNotFound/>
|
||||
|
||||
## Setup ZITADEL and a Service Account Admin
|
||||
|
||||
With this setup, you don't create a human user that has the IAM_OWNER role.
|
||||
Instead, you create a service account that has the IAM_OWNER role.
|
||||
ZITADEL will also create a key for your, with which you can authenticate to the ZITADEL API.
|
||||
For example, you can install ZITADEL and seemlessly provision ZITADEL resources after installation using [Terraform](/docs/guides/manage/terraform/basics.md).
|
||||
|
||||
:::caution
|
||||
With this setup you only get a key for a service account. Logging in at ZITADEL using the login screen is not possible until you create a user with the ZITADEL API.
|
||||
:::
|
||||
|
||||
```bash
|
||||
# Install CockroachDB
|
||||
helm install crdb cockroachdb/cockroachdb \
|
||||
--set fullnameOverride=crdb \
|
||||
--set conf.single-node=true \
|
||||
--set statefulset.replicas=1
|
||||
|
||||
# Install ZITADEL
|
||||
helm install my-zitadel zitadel/zitadel \
|
||||
--set zitadel.masterkey="MasterkeyNeedsToHave32Characters" \
|
||||
--set zitadel.configmapConfig.ExternalSecure=false \
|
||||
--set zitadel.configmapConfig.TLS.Enabled=false \
|
||||
--set zitadel.secretConfig.Database.cockroach.User.Password="a-zitadel-db-user-password" \
|
||||
--set replicaCount=1 \
|
||||
--set zitadel.configmapConfig.FirstInstance.Org.Machine.Machine.Username="zitadel-admin-sa" \
|
||||
--set zitadel.configmapConfig.FirstInstance.Org.Machine.Machine.Name="Admin" \
|
||||
--set zitadel.configmapConfig.FirstInstance.Org.Machine.MachineKey.Type=1
|
||||
|
||||
# Make ZITADEL locally accessible
|
||||
kubectl port-forward svc/my-zitadel 8080
|
||||
```
|
||||
|
||||
When Helm is done, you can print your service account key from a Kubernetes secret:
|
||||
```bash
|
||||
kubectl get secret zitadel-admin-sa -o jsonpath='{ .data.zitadel-admin-sa\.json }' | base64 --decode
|
||||
```
|
||||
|
||||
<Next components={props.components} />
|
||||
<Disclaimer components={props.components} />
|
||||
For more information and configuration examples, go to the [ZITADEL charts repo](https://github.com/zitadel/zitadel-charts).
|
||||
|
@ -7,6 +7,26 @@ If you have a self-hosted ZITADEL environment, you can limit the usage of your [
|
||||
For example, if you provide your customers [their own virtual instances](/concepts/structure/instance#multiple-virtual-instances) with access on their own domains, you can design a pricing model based on the usage of their instances.
|
||||
The usage control features are currently limited to the instance level only.
|
||||
|
||||
## Block Instances
|
||||
|
||||
You can block an instance using the [system API](/category/apis/resources/system/limits).
|
||||
|
||||
Most requests to a blocked instance are rejected with the HTTP status *429 Too Many Requests* or the gRPC status *8 Resource Exhausted*.
|
||||
However, requests to the [system API](/apis/introduction#system) are still allowed.
|
||||
Requests to paths with the prefix */ui/login* return a redirect with HTTP status *302 Found* to */ui/console*, where the user is guided to *InstanceManagementURL*.
|
||||
Blocked HTTP requests additionally set a cookie to make it easy to block traffic before it reaches your ZITADEL runtime, for example with a WAF rule.
|
||||
|
||||
You can block new instances by default using the *DefaultInstance.Limits.Block* runtime configuration.
|
||||
The following snippets shows the default YAML:
|
||||
|
||||
```yaml
|
||||
DefaultInstance:
|
||||
Limits:
|
||||
# If Block is true, all requests except to /ui/console or the system API are blocked and /ui/login is redirected to /ui/console.
|
||||
# /ui/console shows a message that the instance is blocked with a link to Console.InstanceManagementURL
|
||||
Block: # ZITADEL_DEFAULTINSTANCE_LIMITS_BLOCK
|
||||
```
|
||||
|
||||
## Limit Audit Trails
|
||||
|
||||
You can restrict the maximum age of events returned by the following APIs:
|
||||
@ -107,8 +127,9 @@ DefaultInstance:
|
||||
|
||||
### Exhausted Authenticated Requests
|
||||
|
||||
If a quota is configured to limit requests and the quotas amount is exhausted, all further requests are blocked except requests to the System API.
|
||||
Also, a cookie is set, to make it easier to block further traffic before it reaches your ZITADEL runtime.
|
||||
If a quota is configured to limit requests and the quotas amount is exhausted, all further authenticated requests are blocked except requests to the [system API](/apis/introduction#system).
|
||||
Also, a cookie is set, to make it easier to block further traffic before it reaches your ZITADEL runtime, for example with a WAF rule.
|
||||
The console is still served, but it only shows a dialog that says that the instance is blocked with a link to *InstanceManagementURL*.
|
||||
|
||||
### Exhausted Action Run Seconds
|
||||
|
||||
|
@ -73,3 +73,40 @@ The WebFinger requirement and setup is a step a user has to take outside of thei
|
||||
On their custom domain, e.g example.com, users need to host a WebFinger endpoint at https://example.com/.well-known/webfinger. When queried, this endpoint returns a JSON response detailing the issuer. Users would need to host the endpoint with the link to the ZITADEL issuer. Tailscale only looks up this endpoint once when a user signs up, and will only look up this endpoint again if the user needs to make a configuration change to their identity provider.
|
||||
|
||||
The requirements and a set up guide is detailed in the [Tailscale documentation](https://tailscale.com/kb/1240/sso-custom-oidc/).
|
||||
|
||||
## Login not possible. The organization of the user must be granted to the project
|
||||
|
||||

|
||||
|
||||
ZITADEL is not only capable of handling authentication but also authorization.
|
||||
This error message tells you, that a project grant is missing from the owner organization to the organization of the authenticating user.
|
||||
|
||||
You do have two organizations, an owner (Organization A) and a customer (Organization B).
|
||||
The Organization A owns a Project, and has to grant it to Organization B, so users are allowed to authenticate.
|
||||
The error message is shown to users of Organization B that the permission is required, but the project is not granted to Organization B.
|
||||

|
||||
|
||||
|
||||
You do have two possibilities.
|
||||
1. Disable the permission check
|
||||
2. Give the permission to the organization
|
||||
|
||||
### Disable the permission check
|
||||
|
||||
1. Go to the organization, who owns the project, where the user tries to authenticate.
|
||||
2. Navigate to the general settings of the needed project
|
||||
3. Disable "Check for Project on Authentication"
|
||||
|
||||

|
||||
|
||||
|
||||
### Give the needed permission to the organization
|
||||
|
||||
1. Go to the organization, who owns the project, where the user tries to authenticate.
|
||||
2. Navigate to the grants page of the needed project
|
||||
3. Click on the "New" button
|
||||
4. Search for the organization to which you want to grant the project (e.g Organization B)
|
||||
5. Select the roles you want to grant
|
||||
6. Click save
|
||||
|
||||

|
||||
|
@ -178,7 +178,7 @@ module.exports = {
|
||||
selector: "div#",
|
||||
},
|
||||
prism: {
|
||||
additionalLanguages: ["csharp", "dart", "groovy", "regex"],
|
||||
additionalLanguages: ["csharp", "dart", "groovy", "regex", "java", "php"],
|
||||
},
|
||||
colorMode: {
|
||||
defaultMode: "dark",
|
||||
|
@ -33,7 +33,7 @@
|
||||
"docusaurus-plugin-openapi-docs": "^1.7.3",
|
||||
"docusaurus-theme-openapi-docs": "^1.7.3",
|
||||
"mdx-mermaid": "^1.1.0",
|
||||
"postcss": "^8.4.19",
|
||||
"postcss": "^8.4.31",
|
||||
"raw-loader": "^4.0.2",
|
||||
"react": "17.0.2",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
|
191
docs/sidebars.js
@ -11,11 +11,14 @@ module.exports = {
|
||||
type: "category",
|
||||
label: "Frontend",
|
||||
items: [
|
||||
"examples/login/angular",
|
||||
"examples/login/react",
|
||||
"examples/login/vue",
|
||||
"examples/login/angular",
|
||||
"examples/login/flutter",
|
||||
"examples/login/nextjs",
|
||||
"examples/login/go",
|
||||
"examples/login/symfony",
|
||||
"examples/login/java-spring",
|
||||
],
|
||||
collapsed: true,
|
||||
},
|
||||
@ -25,7 +28,9 @@ module.exports = {
|
||||
items: [
|
||||
"examples/secure-api/go",
|
||||
"examples/secure-api/python-flask",
|
||||
"examples/secure-api/dot-net"
|
||||
"examples/secure-api/dot-net",
|
||||
"examples/secure-api/nodejs-nestjs",
|
||||
"examples/secure-api/java-spring",
|
||||
],
|
||||
collapsed: true,
|
||||
},
|
||||
@ -38,15 +43,15 @@ module.exports = {
|
||||
items: [
|
||||
"examples/introduction",
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Frontend', // The link label
|
||||
href: '/examples/introduction#frontend', // The internal path
|
||||
type: "link",
|
||||
label: "Frontend", // The link label
|
||||
href: "/examples/introduction#frontend", // The internal path
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Backend', // The link label
|
||||
href: '/examples/introduction#backend', // The internal path
|
||||
}
|
||||
type: "link",
|
||||
label: "Backend", // The link label
|
||||
href: "/examples/introduction#backend", // The internal path
|
||||
},
|
||||
],
|
||||
collapsed: true,
|
||||
},
|
||||
@ -128,9 +133,9 @@ module.exports = {
|
||||
"guides/migrate/sources/zitadel",
|
||||
"guides/migrate/sources/auth0",
|
||||
"guides/migrate/sources/keycloak",
|
||||
]
|
||||
],
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
@ -151,8 +156,7 @@ module.exports = {
|
||||
type: "generated-index",
|
||||
title: "Authenticate Human Users",
|
||||
slug: "guides/integrate/human-users",
|
||||
description:
|
||||
"How to authenticate human users with OpenID Connect",
|
||||
description: "How to authenticate human users with OpenID Connect",
|
||||
},
|
||||
items: [
|
||||
"guides/integrate/login-users",
|
||||
@ -197,9 +201,7 @@ module.exports = {
|
||||
type: "category",
|
||||
label: "Role Management",
|
||||
collapsed: true,
|
||||
items: [
|
||||
"guides/integrate/retrieve-user-roles"
|
||||
],
|
||||
items: ["guides/integrate/retrieve-user-roles"],
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
@ -209,8 +211,7 @@ module.exports = {
|
||||
title: "Build your own Login UI",
|
||||
slug: "/guides/integrate/login-ui",
|
||||
description:
|
||||
"In the following guides you will learn how to create your own login UI with our APIs. The different scenarios like username/password, external identity provider, etc. will be shown."
|
||||
|
||||
"In the following guides you will learn how to create your own login UI with our APIs. The different scenarios like username/password, external identity provider, etc. will be shown.",
|
||||
},
|
||||
collapsed: true,
|
||||
items: [
|
||||
@ -221,7 +222,7 @@ module.exports = {
|
||||
"guides/integrate/login-ui/select-account",
|
||||
"guides/integrate/login-ui/password-reset",
|
||||
"guides/integrate/login-ui/logout",
|
||||
"guides/integrate/login-ui/oidc-standard"
|
||||
"guides/integrate/login-ui/oidc-standard",
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -229,11 +230,11 @@ module.exports = {
|
||||
label: "Configure Identity Providers",
|
||||
link: {
|
||||
type: "generated-index",
|
||||
title: "Let Users Login with Preferred Identity Provider in ZITADEL",
|
||||
title:
|
||||
"Let Users Login with Preferred Identity Provider in ZITADEL",
|
||||
slug: "/guides/integrate/identity-providers",
|
||||
description:
|
||||
"In the following guides you will learn how to configure and setup your preferred external identity provider in ZITADEL.",
|
||||
|
||||
},
|
||||
collapsed: true,
|
||||
items: [
|
||||
@ -255,9 +256,9 @@ module.exports = {
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Authenticate Service Users',
|
||||
href: '/guides/integrate/serviceusers',
|
||||
type: "link",
|
||||
label: "Authenticate Service Users",
|
||||
href: "/guides/integrate/serviceusers",
|
||||
},
|
||||
"guides/integrate/access-zitadel-apis",
|
||||
"guides/integrate/access-zitadel-system-api",
|
||||
@ -282,48 +283,47 @@ module.exports = {
|
||||
slug: "/guides/integrate/services",
|
||||
description:
|
||||
"With the guides in this section you will learn how to integrate ZITADEL with your services.",
|
||||
|
||||
},
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
type: 'autogenerated',
|
||||
dirName: 'guides/integrate/services',
|
||||
type: "autogenerated",
|
||||
dirName: "guides/integrate/services",
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Bold BI (boldbi.com)',
|
||||
href: 'https://support.boldbi.com/kb/article/13708/how-to-configure-zitadel-oauth-login-in-bold-bi',
|
||||
type: "link",
|
||||
label: "Bold BI (boldbi.com)",
|
||||
href: "https://support.boldbi.com/kb/article/13708/how-to-configure-zitadel-oauth-login-in-bold-bi",
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Cloudflare workers',
|
||||
href: 'https://zitadel.com/blog/increase-spa-security-with-cloudflare-workers',
|
||||
type: "link",
|
||||
label: "Cloudflare workers",
|
||||
href: "https://zitadel.com/blog/increase-spa-security-with-cloudflare-workers",
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Firezone (firezone.dev)',
|
||||
href: 'https://www.firezone.dev/docs/authenticate/oidc/zitadel',
|
||||
type: "link",
|
||||
label: "Firezone (firezone.dev)",
|
||||
href: "https://www.firezone.dev/docs/authenticate/oidc/zitadel",
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Nextcloud',
|
||||
href: 'https://zitadel.com/blog/zitadel-as-sso-provider-for-selfhosting',
|
||||
type: "link",
|
||||
label: "Nextcloud",
|
||||
href: "https://zitadel.com/blog/zitadel-as-sso-provider-for-selfhosting",
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Netbird (netbird.io)',
|
||||
href: 'https://docs.netbird.io/selfhosted/identity-providers',
|
||||
type: "link",
|
||||
label: "Netbird (netbird.io)",
|
||||
href: "https://docs.netbird.io/selfhosted/identity-providers",
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Psono (psono.com)',
|
||||
href: 'https://doc.psono.com/admin/configuration/oidc-zitadel.html',
|
||||
type: "link",
|
||||
label: "Psono (psono.com)",
|
||||
href: "https://doc.psono.com/admin/configuration/oidc-zitadel.html",
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Zoho Desk (zoho.com)',
|
||||
href: 'https://help.zoho.com/portal/en/kb/desk/user-management-and-security/data-security/articles/setting-up-saml-single-signon-for-help-center#Zitadel_IDP',
|
||||
type: "link",
|
||||
label: "Zoho Desk (zoho.com)",
|
||||
href: "https://help.zoho.com/portal/en/kb/desk/user-management-and-security/data-security/articles/setting-up-saml-single-signon-for-help-center#Zitadel_IDP",
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -336,18 +336,17 @@ module.exports = {
|
||||
slug: "/guides/integrate/tools",
|
||||
description:
|
||||
"With the guides in this section you will learn how to integrate ZITADEL with your favorite tools.",
|
||||
|
||||
},
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Argo CD',
|
||||
href: 'https://argo-cd.readthedocs.io/en/latest/operator-manual/user-management/zitadel/',
|
||||
type: "link",
|
||||
label: "Argo CD",
|
||||
href: "https://argo-cd.readthedocs.io/en/latest/operator-manual/user-management/zitadel/",
|
||||
},
|
||||
"guides/integrate/tools/apache2",
|
||||
"guides/integrate/authenticated-mongodb-charts",
|
||||
"examples/identity-proxy/oauth2-proxy"
|
||||
"examples/identity-proxy/oauth2-proxy",
|
||||
],
|
||||
},
|
||||
],
|
||||
@ -398,7 +397,7 @@ module.exports = {
|
||||
"concepts/features/actions",
|
||||
"concepts/features/audit-trail",
|
||||
"concepts/features/selfservice",
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
@ -418,7 +417,7 @@ module.exports = {
|
||||
"concepts/eventstore/implementation",
|
||||
],
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
@ -428,26 +427,26 @@ module.exports = {
|
||||
"support/software-release-cycles-support",
|
||||
"support/troubleshooting",
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Support Service Descriptions',
|
||||
href: '/legal/service-description/support-services',
|
||||
type: "link",
|
||||
label: "Support Service Descriptions",
|
||||
href: "/legal/service-description/support-services",
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
type: "category",
|
||||
label: "Technical Advisory",
|
||||
link: {
|
||||
type: 'doc',
|
||||
id: 'support/technical_advisory',
|
||||
type: "doc",
|
||||
id: "support/technical_advisory",
|
||||
},
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
type: 'autogenerated',
|
||||
dirName: 'support/advisory',
|
||||
},
|
||||
{
|
||||
type: "autogenerated",
|
||||
dirName: "support/advisory",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
],
|
||||
apis: [
|
||||
@ -460,8 +459,7 @@ module.exports = {
|
||||
type: "generated-index",
|
||||
title: "Core Resources",
|
||||
slug: "/apis/resources/",
|
||||
description:
|
||||
"Resource based API definitions",
|
||||
description: "Resource based API definitions",
|
||||
},
|
||||
items: [
|
||||
{
|
||||
@ -473,7 +471,6 @@ module.exports = {
|
||||
slug: "/apis/resources/auth",
|
||||
description:
|
||||
"The authentication API (aka Auth API) is used for all operations on the currently logged in user. The user id is taken from the sub claim in the token.",
|
||||
|
||||
},
|
||||
items: require("./docs/apis/resources/auth/sidebar.js"),
|
||||
},
|
||||
@ -523,8 +520,8 @@ module.exports = {
|
||||
title: "User Service API (Beta)",
|
||||
slug: "/apis/resources/user_service",
|
||||
description:
|
||||
"This API is intended to manage users in a ZITADEL instance.\n"+
|
||||
"\n"+
|
||||
"This API is intended to manage users in a ZITADEL instance.\n" +
|
||||
"\n" +
|
||||
"This project is in beta state. It can AND will continue breaking until the services provide the same functionality as the current login.",
|
||||
},
|
||||
items: require("./docs/apis/resources/user_service/sidebar.js"),
|
||||
@ -537,8 +534,8 @@ module.exports = {
|
||||
title: "Session Service API (Beta)",
|
||||
slug: "/apis/resources/session_service",
|
||||
description:
|
||||
"This API is intended to manage sessions in a ZITADEL instance.\n"+
|
||||
"\n"+
|
||||
"This API is intended to manage sessions in a ZITADEL instance.\n" +
|
||||
"\n" +
|
||||
"This project is in beta state. It can AND will continue breaking until the services provide the same functionality as the current login.",
|
||||
},
|
||||
items: require("./docs/apis/resources/session_service/sidebar.js"),
|
||||
@ -551,8 +548,8 @@ module.exports = {
|
||||
title: "OIDC Service API (Beta)",
|
||||
slug: "/apis/resources/oidc_service",
|
||||
description:
|
||||
"Get OIDC Auth Request details and create callback URLs.\n"+
|
||||
"\n"+
|
||||
"Get OIDC Auth Request details and create callback URLs.\n" +
|
||||
"\n" +
|
||||
"This project is in beta state. It can AND will continue breaking until the services provide the same functionality as the current login.",
|
||||
},
|
||||
items: require("./docs/apis/resources/oidc_service/sidebar.js"),
|
||||
@ -565,8 +562,8 @@ module.exports = {
|
||||
title: "Settings Service API (Beta)",
|
||||
slug: "/apis/resources/settings_service",
|
||||
description:
|
||||
"This API is intended to manage settings in a ZITADEL instance.\n"+
|
||||
"\n"+
|
||||
"This API is intended to manage settings in a ZITADEL instance.\n" +
|
||||
"\n" +
|
||||
"This project is in beta state. It can AND will continue to break until the services provide the same functionality as the current login.",
|
||||
},
|
||||
items: require("./docs/apis/resources/settings_service/sidebar.js"),
|
||||
@ -577,7 +574,7 @@ module.exports = {
|
||||
collapsed: true,
|
||||
items: ["apis/assets/assets"],
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
@ -617,12 +614,12 @@ module.exports = {
|
||||
"apis/actions/complement-token",
|
||||
"apis/actions/customize-samlresponse",
|
||||
"apis/actions/objects",
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "doc",
|
||||
label: "gRPC Status Codes",
|
||||
id: "apis/statuscodes"
|
||||
id: "apis/statuscodes",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
@ -631,9 +628,9 @@ module.exports = {
|
||||
items: ["apis/observability/metrics", "apis/observability/health"],
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
label: 'Rate Limits (Cloud)', // The link label
|
||||
href: '/legal/policies/rate-limit-policy', // The internal path
|
||||
type: "link",
|
||||
label: "Rate Limits (Cloud)", // The link label
|
||||
href: "/legal/policies/rate-limit-policy", // The internal path
|
||||
},
|
||||
],
|
||||
selfHosting: [
|
||||
@ -649,7 +646,7 @@ module.exports = {
|
||||
"self-hosting/deploy/knative",
|
||||
"self-hosting/deploy/kubernetes",
|
||||
"self-hosting/deploy/loadbalancing-example/loadbalancing-example",
|
||||
"self-hosting/deploy/troubleshooting/troubleshooting"
|
||||
"self-hosting/deploy/troubleshooting/troubleshooting",
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -672,7 +669,7 @@ module.exports = {
|
||||
"self-hosting/manage/reverseproxy/traefik/traefik",
|
||||
"self-hosting/manage/reverseproxy/nginx/nginx",
|
||||
"self-hosting/manage/reverseproxy/caddy/caddy",
|
||||
// "self-hosting/manage/reverseproxy/httpd/httpd", grpc NOT WORKING
|
||||
// "self-hosting/manage/reverseproxy/httpd/httpd", grpc NOT WORKING
|
||||
"self-hosting/manage/reverseproxy/cloudflare/cloudflare",
|
||||
"self-hosting/manage/reverseproxy/cloudflare_tunnel/cloudflare_tunnel",
|
||||
"self-hosting/manage/reverseproxy/zitadel_cloud/zitadel_cloud",
|
||||
@ -683,7 +680,7 @@ module.exports = {
|
||||
"self-hosting/manage/tls_modes",
|
||||
"self-hosting/manage/database/database",
|
||||
"self-hosting/manage/updating_scaling",
|
||||
"self-hosting/manage/usage_control"
|
||||
"self-hosting/manage/usage_control",
|
||||
],
|
||||
},
|
||||
],
|
||||
@ -712,13 +709,14 @@ module.exports = {
|
||||
type: "generated-index",
|
||||
title: "Service description",
|
||||
slug: "/legal/service-description",
|
||||
description: "Description of services and service levels for ZITADEL Cloud and Enterprise subscriptions.",
|
||||
description:
|
||||
"Description of services and service levels for ZITADEL Cloud and Enterprise subscriptions.",
|
||||
},
|
||||
items: [
|
||||
{
|
||||
type: 'autogenerated',
|
||||
dirName: 'legal/service-description',
|
||||
}
|
||||
type: "autogenerated",
|
||||
dirName: "legal/service-description",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -729,16 +727,17 @@ module.exports = {
|
||||
type: "generated-index",
|
||||
title: "Policies",
|
||||
slug: "/legal/policies",
|
||||
description: "Policies and guidelines in addition to our terms of services.",
|
||||
description:
|
||||
"Policies and guidelines in addition to our terms of services.",
|
||||
},
|
||||
items: [
|
||||
{
|
||||
type: 'autogenerated',
|
||||
dirName: 'legal/policies',
|
||||
}
|
||||
]
|
||||
type: "autogenerated",
|
||||
dirName: "legal/policies",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
BIN
docs/static/img/java-spring/api-create-auth.png
vendored
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
docs/static/img/java-spring/api-create-clientid-secret.png
vendored
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
docs/static/img/java-spring/api-create.png
vendored
Normal file
After Width: | Height: | Size: 178 KiB |
BIN
docs/static/img/java-spring/api-project-auth.png
vendored
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
docs/static/img/java-spring/api-project-role.png
vendored
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
docs/static/img/java-spring/app-create-auth.png
vendored
Normal file
After Width: | Height: | Size: 161 KiB |
BIN
docs/static/img/java-spring/app-create-clientid.png
vendored
Normal file
After Width: | Height: | Size: 31 KiB |