feat(console): OAuth provider template (#5377)

implements oauth template for console
Co-authored-by: Elio Bischof <elio@zitadel.com>
This commit is contained in:
Max Peintner 2023-03-10 16:28:18 +01:00 committed by GitHub
parent 1ec6c451ca
commit 0c704966a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 764 additions and 1 deletions

View File

@ -46,6 +46,10 @@
<mat-icon class="idp-icon" svgIcon="mdi_openid" alt="oidc" />
Generic OIDC
</div>
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_OAUTH">
<img class="idp-logo" src="../../../assets/images/idp/oauth.svg" alt="oauth" />
Generic OAuth
</div>
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_JWT">
<mat-icon class="idp-icon" svgIcon="mdi_jwt" alt="jwt" />
Generic JWT

View File

@ -228,6 +228,8 @@ export class IdpTableComponent implements OnInit {
switch (row.type) {
case ProviderType.PROVIDER_TYPE_OIDC:
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'oidc', row.id];
case ProviderType.PROVIDER_TYPE_OAUTH:
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'oauth', row.id];
case ProviderType.PROVIDER_TYPE_JWT:
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'jwt', row.id];
case ProviderType.PROVIDER_TYPE_GOOGLE:

View File

@ -68,6 +68,23 @@
</div>
</a>
<a
class="item card"
[routerLink]="
serviceType === PolicyComponentServiceType.ADMIN
? ['/instance', 'provider', 'oauth', 'create']
: serviceType === PolicyComponentServiceType.MGMT
? ['/org', 'provider', 'oauth', 'create']
: []
"
>
<img class="idp-logo" src="../../../assets/images/idp/oauth.svg" alt="oauth" />
<div class="text-container">
<span class="title">Generic OAuth</span>
</div>
</a>
<a
class="item card"
[routerLink]="

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProviderOAuthComponent } from './provider-oauth.component';
const routes: Routes = [
{
path: '',
component: ProviderOAuthComponent,
data: { animation: 'DetailPage' },
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ProviderOAuthRoutingModule {}

View File

@ -0,0 +1,111 @@
<cnsl-create-layout
title="{{ id ? ('IDP.DETAIL.TITLE' | translate) : ('IDP.CREATE.TITLE' | translate) }}"
(closed)="close()"
>
<div class="oauth-create-content">
<div class="title-row">
<img class="idp-logo" src="../../../assets/images/idp/oauth.svg" alt="oauth" />
<h1>{{ 'IDP.CREATE.OAUTH.TITLE' | translate }}</h1>
<mat-spinner diameter="25" *ngIf="loading" color="primary"></mat-spinner>
</div>
<p class="desc cnsl-secondary-text">{{ 'IDP.CREATE.OAUTH.DESCRIPTION' | translate }}</p>
<form [formGroup]="form" (ngSubmit)="submitForm()">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.AUTHORIZATIONENDPOINT' | translate }}</cnsl-label>
<input cnslInput formControlName="authorizationEndpoint" />
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.TOKENENDPOINT' | translate }}</cnsl-label>
<input cnslInput formControlName="tokenEndpoint" />
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.USERENDPOINT' | translate }}</cnsl-label>
<input cnslInput formControlName="userEndpoint" />
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.IDATTRIBUTE' | translate }}</cnsl-label>
<input cnslInput formControlName="idAttribute" />
</cnsl-form-field>
<div class="oauth-content">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.CLIENTID' | translate }}</cnsl-label>
<input cnslInput formControlName="clientId" />
</cnsl-form-field>
<mat-checkbox *ngIf="provider" [(ngModel)]="updateClientSecret" [ngModelOptions]="{ standalone: true }">{{
'IDP.UPDATECLIENTSECRET' | translate
}}</mat-checkbox>
<cnsl-form-field *ngIf="!provider || (provider && updateClientSecret)" class="formfield">
<cnsl-label>{{ 'IDP.CLIENTSECRET' | translate }}</cnsl-label>
<input cnslInput formControlName="clientSecret" />
</cnsl-form-field>
<div class="optional-h-wrapper">
<h2>{{ 'IDP.OPTIONAL' | translate }}</h2>
<button (click)="showOptional = !showOptional" type="button" mat-icon-button>
<mat-icon *ngIf="showOptional">keyboard_arrow_up</mat-icon
><mat-icon *ngIf="!showOptional">keyboard_arrow_down</mat-icon>
</button>
</div>
<div *ngIf="showOptional">
<div class="idp-scopes">
<div class="flex-line">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.SCOPESLIST' | translate }}</cnsl-label>
<input
cnslInput
[matChipInputFor]="chipScopesList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addScope($event)"
/>
</cnsl-form-field>
<button class="scope-add-button" (click)="addScope($any($event))" mat-icon-button>
<mat-icon>add</mat-icon>
</button>
</div>
<cnsl-form-field class="formfield">
<mat-chip-list #chipScopesList aria-label="scope selection">
<mat-chip
class="chip"
*ngFor="let scope of scopesList?.value"
selectable="false"
removable
(removed)="removeScope(scope)"
>
{{ scope }} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</cnsl-form-field>
</div>
<cnsl-provider-options
[initialOptions]="provider?.config?.options"
(optionsChanged)="options = $event"
></cnsl-provider-options>
</div>
</div>
<div class="oauth-create-actions">
<button color="primary" mat-raised-button class="continue-button" [disabled]="form.invalid" type="submit">
<span *ngIf="id">{{ 'ACTIONS.SAVE' | translate }}</span>
<span *ngIf="!id">{{ 'ACTIONS.CREATE' | translate }}</span>
</button>
</div>
</form>
</div>
</cnsl-create-layout>

View File

@ -0,0 +1,84 @@
.desc {
font-size: 14px;
}
.oauth-create-content {
.title-row {
display: flex;
align-items: center;
.idp-logo {
height: 36px;
width: 36px;
margin-right: 1rem;
flex-shrink: 0;
}
h1 {
margin: 0 1rem 0 0;
}
}
.formfield {
display: block;
max-width: 400px;
.mat-chip-input {
width: 100%;
margin: 0;
}
.chip {
border-radius: 0.5rem;
height: 40px;
}
@media only screen and (max-width: 450px) {
max-width: none;
}
}
.oauth-content {
.desc {
margin-bottom: 1rem;
}
.idp-scopes {
padding-bottom: 0.5rem;
.flex-line {
display: flex;
align-items: flex-start;
max-width: 400px;
.formfield {
flex: 1;
}
.scope-add-button {
margin-top: 1.75rem;
}
}
}
}
}
.oauth-create-actions {
display: flex;
margin-top: 1rem;
button[mat-raised-button] {
border-radius: 0.5rem;
margin-right: 1rem;
padding: 0.5rem 4rem;
}
}
.optional-h-wrapper {
display: flex;
align-items: center;
h2 {
margin-right: 0.25rem;
}
}

View File

@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ProviderOAuthComponent } from './provider-oauth.component';
describe('ProviderOAuthComponent', () => {
let component: ProviderOAuthComponent;
let fixture: ComponentFixture<ProviderOAuthComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ProviderOAuthComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProviderOAuthComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,298 @@
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
import { Location } from '@angular/common';
import { Component, Injector, Type } from '@angular/core';
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
import { ActivatedRoute, Router } from '@angular/router';
import { take } from 'rxjs';
import {
AddGenericOAuthProviderRequest as AdminAddGenericOAuthProviderRequest,
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateGenericOAuthProviderRequest as AdminUpdateGenericOAuthProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddGenericOAuthProviderRequest as MgmtAddGenericOAuthProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
UpdateGenericOAuthProviderRequest as MgmtUpdateGenericOAuthProviderRequest,
} from 'src/app/proto/generated/zitadel/management_pb';
import { AdminService } from 'src/app/services/admin.service';
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
@Component({
selector: 'cnsl-provider-oauth',
templateUrl: './provider-oauth.component.html',
styleUrls: ['./provider-oauth.component.scss'],
})
export class ProviderOAuthComponent {
public showOptional: boolean = false;
public options: Options = new Options();
public id: string | null = '';
public updateClientSecret: boolean = false;
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
private service!: ManagementService | AdminService;
public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];
public form!: UntypedFormGroup;
public loading: boolean = false;
public provider?: Provider.AsObject;
constructor(
private router: Router,
private route: ActivatedRoute,
private toast: ToastService,
private injector: Injector,
private _location: Location,
breadcrumbService: BreadcrumbService,
) {
this.form = new UntypedFormGroup({
name: new UntypedFormControl('', [Validators.required]),
clientId: new UntypedFormControl('', [Validators.required]),
clientSecret: new UntypedFormControl('', [Validators.required]),
authorizationEndpoint: new UntypedFormControl('', [Validators.required]),
tokenEndpoint: new UntypedFormControl('', [Validators.required]),
userEndpoint: new UntypedFormControl('', [Validators.required]),
idAttribute: new UntypedFormControl('', [Validators.required]),
scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []),
});
this.route.data.pipe(take(1)).subscribe((data) => {
this.serviceType = data.serviceType;
switch (this.serviceType) {
case PolicyComponentServiceType.MGMT:
this.service = this.injector.get(ManagementService as Type<ManagementService>);
const bread: Breadcrumb = {
type: BreadcrumbType.ORG,
routerLink: ['/org'],
};
breadcrumbService.setBreadcrumb([bread]);
break;
case PolicyComponentServiceType.ADMIN:
this.service = this.injector.get(AdminService as Type<AdminService>);
const iamBread = new Breadcrumb({
type: BreadcrumbType.ORG,
name: 'Instance',
routerLink: ['/instance'],
});
breadcrumbService.setBreadcrumb([iamBread]);
break;
}
this.id = this.route.snapshot.paramMap.get('id');
if (this.id) {
this.clientSecret?.setValidators([]);
this.getData(this.id);
}
});
}
private getData(id: string): void {
this.loading = true;
const req =
this.serviceType === PolicyComponentServiceType.ADMIN
? new AdminGetProviderByIDRequest()
: new MgmtGetProviderByIDRequest();
req.setId(id);
this.service
.getProviderByID(req)
.then((resp) => {
this.provider = resp.idp;
this.loading = false;
if (this.provider?.config?.oauth) {
this.form.patchValue(this.provider.config.oauth);
this.name?.setValue(this.provider.name);
}
})
.catch((error) => {
this.toast.showError(error);
this.loading = false;
});
}
public submitForm(): void {
this.provider ? this.updateGenericOAuthProvider() : this.addGenericOAuthProvider();
}
public addGenericOAuthProvider(): void {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
const req = new MgmtAddGenericOAuthProviderRequest();
req.setName(this.name?.value);
req.setAuthorizationEndpoint(this.authorizationEndpoint?.value);
req.setIdAttribute(this.idAttribute?.value);
req.setTokenEndpoint(this.tokenEndpoint?.value);
req.setUserEndpoint(this.userEndpoint?.value);
req.setClientId(this.clientId?.value);
req.setClientSecret(this.clientSecret?.value);
req.setScopesList(this.scopesList?.value);
this.loading = true;
(this.service as ManagementService)
.addGenericOAuthProvider(req)
.then((idp) => {
setTimeout(() => {
this.loading = false;
this.router.navigate(['/org-settings'], { queryParams: { id: 'idp' } });
}, 2000);
})
.catch((error) => {
this.toast.showError(error);
this.loading = false;
});
} else if (PolicyComponentServiceType.ADMIN) {
const req = new AdminAddGenericOAuthProviderRequest();
req.setName(this.name?.value);
req.setAuthorizationEndpoint(this.authorizationEndpoint?.value);
req.setIdAttribute(this.idAttribute?.value);
req.setTokenEndpoint(this.tokenEndpoint?.value);
req.setUserEndpoint(this.userEndpoint?.value);
req.setClientId(this.clientId?.value);
req.setClientSecret(this.clientSecret?.value);
req.setScopesList(this.scopesList?.value);
this.loading = true;
(this.service as AdminService)
.addGenericOAuthProvider(req)
.then((idp) => {
setTimeout(() => {
this.loading = false;
this.router.navigate(['/settings'], { queryParams: { id: 'idp' } });
}, 2000);
})
.catch((error) => {
this.toast.showError(error);
this.loading = false;
});
}
}
public updateGenericOAuthProvider(): void {
if (this.provider) {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
const req = new MgmtUpdateGenericOAuthProviderRequest();
req.setId(this.provider.id);
req.setName(this.name?.value);
req.setAuthorizationEndpoint(this.authorizationEndpoint?.value);
req.setIdAttribute(this.idAttribute?.value);
req.setTokenEndpoint(this.tokenEndpoint?.value);
req.setUserEndpoint(this.userEndpoint?.value);
req.setClientId(this.clientId?.value);
req.setClientSecret(this.clientSecret?.value);
req.setScopesList(this.scopesList?.value);
this.loading = true;
(this.service as ManagementService)
.updateGenericOAuthProvider(req)
.then((idp) => {
setTimeout(() => {
this.loading = false;
this.router.navigate(['/org-settings'], { queryParams: { id: 'idp' } });
}, 2000);
})
.catch((error) => {
this.toast.showError(error);
this.loading = false;
});
} else if (PolicyComponentServiceType.ADMIN) {
const req = new AdminUpdateGenericOAuthProviderRequest();
req.setId(this.provider.id);
req.setName(this.name?.value);
req.setAuthorizationEndpoint(this.authorizationEndpoint?.value);
req.setIdAttribute(this.idAttribute?.value);
req.setTokenEndpoint(this.tokenEndpoint?.value);
req.setUserEndpoint(this.userEndpoint?.value);
req.setClientId(this.clientId?.value);
req.setClientSecret(this.clientSecret?.value);
req.setScopesList(this.scopesList?.value);
this.loading = true;
(this.service as AdminService)
.updateGenericOAuthProvider(req)
.then((idp) => {
setTimeout(() => {
this.loading = false;
this.router.navigate(['/settings'], { queryParams: { id: 'idp' } });
}, 2000);
})
.catch((error) => {
this.toast.showError(error);
this.loading = false;
});
}
}
}
public close(): void {
this._location.back();
}
public addScope(event: MatChipInputEvent): void {
const input = event.chipInput?.inputElement;
const value = event.value.trim();
if (value !== '') {
if (this.scopesList?.value) {
this.scopesList.value.push(value);
if (input) {
input.value = '';
}
}
}
}
public removeScope(uri: string): void {
if (this.scopesList?.value) {
const index = this.scopesList.value.indexOf(uri);
if (index !== undefined && index >= 0) {
this.scopesList.value.splice(index, 1);
}
}
}
public get name(): AbstractControl | null {
return this.form.get('name');
}
public get authorizationEndpoint(): AbstractControl | null {
return this.form.get('authorizationEndpoint');
}
public get tokenEndpoint(): AbstractControl | null {
return this.form.get('tokenEndpoint');
}
public get userEndpoint(): AbstractControl | null {
return this.form.get('userEndpoint');
}
public get idAttribute(): AbstractControl | null {
return this.form.get('idAttribute');
}
public get clientId(): AbstractControl | null {
return this.form.get('clientId');
}
public get clientSecret(): AbstractControl | null {
return this.form.get('clientSecret');
}
public get issuer(): AbstractControl | null {
return this.form.get('issuer');
}
public get scopesList(): AbstractControl | null {
return this.form.get('scopesList');
}
}

View File

@ -0,0 +1,43 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatIconModule } from '@angular/material/icon';
import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button';
import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox';
import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips';
import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner';
import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select';
import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { InputModule } from 'src/app/modules/input/input.module';
import { CardModule } from '../../card/card.module';
import { CreateLayoutModule } from '../../create-layout/create-layout.module';
import { InfoSectionModule } from '../../info-section/info-section.module';
import { ProviderOptionsModule } from '../../provider-options/provider-options.module';
import { ProviderOAuthRoutingModule } from './provider-oauth-routing.module';
import { ProviderOAuthComponent } from './provider-oauth.component';
@NgModule({
declarations: [ProviderOAuthComponent],
imports: [
ProviderOAuthRoutingModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
CreateLayoutModule,
InfoSectionModule,
InputModule,
MatButtonModule,
MatSelectModule,
MatIconModule,
MatChipsModule,
CardModule,
MatCheckboxModule,
MatTooltipModule,
TranslateModule,
ProviderOptionsModule,
MatLegacyProgressSpinnerModule,
],
})
export default class ProviderOAuthModule {}

View File

@ -44,6 +44,19 @@ const routes: Routes = [
},
],
},
{
path: 'oauth',
children: [
{
path: 'create',
loadChildren: () => import('src/app/modules/providers/provider-oauth/provider-oauth.module'),
},
{
path: ':id',
loadChildren: () => import('src/app/modules/providers/provider-oauth/provider-oauth.module'),
},
],
},
{
path: 'jwt',
children: [

View File

@ -19,6 +19,19 @@ const routes: Routes = [
serviceType: PolicyComponentServiceType.MGMT,
},
children: [
{
path: 'oauth',
children: [
{
path: 'create',
loadChildren: () => import('src/app/modules/providers/provider-oauth/provider-oauth.module'),
},
{
path: ':id',
loadChildren: () => import('src/app/modules/providers/provider-oauth/provider-oauth.module'),
},
],
},
{
path: 'oidc',
children: [

View File

@ -8,6 +8,8 @@ import {
ActivateSMSProviderResponse,
AddCustomDomainPolicyRequest,
AddCustomOrgIAMPolicyResponse,
AddGenericOAuthProviderRequest,
AddGenericOAuthProviderResponse,
AddGenericOIDCProviderRequest,
AddGenericOIDCProviderResponse,
AddGoogleProviderRequest,
@ -194,6 +196,8 @@ import {
UpdateCustomDomainPolicyResponse,
UpdateDomainPolicyRequest,
UpdateDomainPolicyResponse,
UpdateGenericOAuthProviderRequest,
UpdateGenericOAuthProviderResponse,
UpdateGenericOIDCProviderRequest,
UpdateGenericOIDCProviderResponse,
UpdateGoogleProviderRequest,
@ -912,6 +916,16 @@ export class AdminService {
return this.grpcService.admin.updateGenericOIDCProvider(req, null).then((resp) => resp.toObject());
}
public addGenericOAuthProvider(req: AddGenericOAuthProviderRequest): Promise<AddGenericOAuthProviderResponse.AsObject> {
return this.grpcService.admin.addGenericOAuthProvider(req, null).then((resp) => resp.toObject());
}
public updateGenericOAuthProvider(
req: UpdateGenericOAuthProviderRequest,
): Promise<UpdateGenericOAuthProviderResponse.AsObject> {
return this.grpcService.admin.updateGenericOAuthProvider(req, null).then((resp) => resp.toObject());
}
public addJWTProvider(req: AddJWTProviderRequest): Promise<AddJWTProviderResponse.AsObject> {
return this.grpcService.admin.addJWTProvider(req, null).then((resp) => resp.toObject());
}

View File

@ -29,6 +29,8 @@ import {
AddCustomPasswordComplexityPolicyResponse,
AddCustomPrivacyPolicyRequest,
AddCustomPrivacyPolicyResponse,
AddGenericOAuthProviderRequest,
AddGenericOAuthProviderResponse,
AddGenericOIDCProviderRequest,
AddGenericOIDCProviderResponse,
AddGoogleProviderRequest,
@ -427,6 +429,8 @@ import {
UpdateCustomPasswordComplexityPolicyResponse,
UpdateCustomPrivacyPolicyRequest,
UpdateCustomPrivacyPolicyResponse,
UpdateGenericOAuthProviderRequest,
UpdateGenericOAuthProviderResponse,
UpdateGenericOIDCProviderRequest,
UpdateGenericOIDCProviderResponse,
UpdateGoogleProviderRequest,
@ -871,6 +875,16 @@ export class ManagementService {
return this.grpcService.mgmt.updateGenericOIDCProvider(req, null).then((resp) => resp.toObject());
}
public addGenericOAuthProvider(req: AddGenericOAuthProviderRequest): Promise<AddGenericOAuthProviderResponse.AsObject> {
return this.grpcService.mgmt.addGenericOAuthProvider(req, null).then((resp) => resp.toObject());
}
public updateGenericOAuthProvider(
req: UpdateGenericOAuthProviderRequest,
): Promise<UpdateGenericOAuthProviderResponse.AsObject> {
return this.grpcService.mgmt.updateGenericOAuthProvider(req, null).then((resp) => resp.toObject());
}
public addJWTProvider(req: AddJWTProviderRequest): Promise<AddJWTProviderResponse.AsObject> {
return this.grpcService.mgmt.addJWTProvider(req, null).then((resp) => resp.toObject());
}

View File

@ -1674,6 +1674,10 @@
"SETAVAILABLE": "verfügbar setzen",
"SETUNAVAILABLE": "auf nicht verfügbar setzen",
"NAME": "Name",
"AUTHORIZATIONENDPOINT": "Authorization Endpunkt",
"TOKENENDPOINT": "Token Endpunkt",
"USERENDPOINT": "User Endpunkt",
"IDATTRIBUTE": "ID Attribut",
"CONFIG": "Konfiguration",
"STATE": "Status",
"ISSUER": "Issuer",
@ -1694,10 +1698,13 @@
"DELETE_SELECTION_DESCRIPTION": "Sie sind im Begriff mehrere Identity Provider zu löschen. Die dadurch hervorgerufenen Änderungen sind unwiderruflich. Wollen Sie dies wirklich tun?",
"EMPTY": "Kein IDP vorhanden",
"OIDC": {
"GENERAL": "Generelle Information",
"TITLE": "OIDC Konfiguration",
"DESCRIPTION": "Geben Sie die Daten OIDC Identity Providers ein."
},
"OAUTH": {
"TITLE": "OAuth Konfiguration",
"DESCRIPTION": "Geben Sie die Daten OAuth Identity Providers ein."
},
"JWT": {
"TITLE": "JWT Konfiguration",
"DESCRIPTION": "Geben Sie die Daten JWT Identity Providers ein. ",

View File

@ -1623,6 +1623,10 @@
"TITLE": "OIDC Provider",
"DESCRIPTION": "Enter the required data for your OIDC provider."
},
"OAUTH": {
"TITLE": "OAuth Provider",
"DESCRIPTION": "Enter the required data for your OAuth provider."
},
"JWT": {
"TITLE": "JWT Provider",
"DESCRIPTION": "Enter the required data for your JWT provider."
@ -1665,6 +1669,10 @@
"OWNER": "Owner",
"ID": "ID",
"NAME": "Name",
"AUTHORIZATIONENDPOINT": "Authorization Endpoint",
"TOKENENDPOINT": "Token Endpoint",
"USERENDPOINT": "User Endpoint",
"IDATTRIBUTE": "ID Attribute",
"AVAILABILITY": "Availability",
"AVAILABLE": "available",
"AVAILABLEBUTINACTIVE": "available but inactive",

View File

@ -1622,6 +1622,10 @@
"TITLE": "Fournisseur OIDC",
"DESCRIPTION": "Entrez les données requises pour votre fournisseur OIDC."
},
"OAuth": {
"TITLE": "Fournisseur OAuth",
"DESCRIPTION": "Entrez les données requises pour votre fournisseur OAuth."
},
"JWT": {
"TITLE": "Fournisseur JWT",
"DESCRIPTION": "Entrez les données requises pour votre fournisseur JWT."
@ -1669,6 +1673,10 @@
"OWNER": "Propriétaire",
"ID": "ID",
"NAME": "Nom",
"AUTHORIZATIONENDPOINT": "Authorization Endpoint",
"TOKENENDPOINT": "Token Endpoint",
"USERENDPOINT": "User Endpoint",
"IDATTRIBUTE": "Attribut d'identification",
"AVAILABILITY": "Disponibilité",
"AVAILABLE": "disponible",
"AVAILABLEBUTINACTIVE": "disponible mais inactif",

View File

@ -1623,6 +1623,10 @@
"TITLE": "OIDC Provider",
"DESCRIPTION": "Inserisci i dati necessari per il tuo provider OIDC."
},
"OAuth": {
"TITLE": "OAuth Provider",
"DESCRIPTION": "Inserisci i dati necessari per il tuo provider OAuth."
},
"JWT": {
"TITLE": "JWT Provider",
"DESCRIPTION": "Inserisci i dati necessari per il tuo provider JWT."
@ -1670,6 +1674,10 @@
"OWNER": "Owner",
"ID": "ID",
"NAME": "Nome",
"AUTHORIZATIONENDPOINT": "Authorization Endpoint",
"TOKENENDPOINT": "Token Endpoint",
"USERENDPOINT": "User Endpoint",
"IDATTRIBUTE": "Attributo ID",
"AVAILABILITY": "Disponibilità",
"AVAILABLE": "disponibile",
"AVAILABLEBUTINACTIVE": "disponible ma inattivo",

View File

@ -1622,6 +1622,10 @@
"TITLE": "OIDC Provider",
"DESCRIPTION": "Wprowadź wymagane dane dla swojego dostawcy OIDC."
},
"OAUTH": {
"TITLE": "OAuth Provider",
"DESCRIPTION": "Wprowadź wymagane dane dla swojego dostawcy OAuth."
},
"JWT": {
"TITLE": "JWT Provider",
"DESCRIPTION": "Wprowadź wymagane dane dla swojego dostawcy JWT."
@ -1669,6 +1673,10 @@
"OWNER": "Właściciel",
"ID": "ID",
"NAME": "Nazwa",
"AUTHORIZATIONENDPOINT": "Authorization Endpoint",
"TOKENENDPOINT": "Token Endpoint",
"USERENDPOINT": "User Endpoint",
"IDATTRIBUTE": "Atrybut identyfikatora",
"AVAILABILITY": "Dostępność",
"AVAILABLE": "dostępny",
"AVAILABLEBUTINACTIVE": "dostępny ale nieaktywny",

View File

@ -1621,6 +1621,10 @@
"TITLE": "OIDC供应商",
"DESCRIPTION": "输入你的OIDC供应商的必要数据。"
},
"OAUTH": {
"TITLE": "OAuth供应商",
"DESCRIPTION": "输入你的OAuth供应商的必要数据。"
},
"JWT": {
"TITLE": "JWT供应商",
"DESCRIPTION": "输入你的JWT供应商所需的数据。"
@ -1668,6 +1672,10 @@
"OWNER": "所有者",
"ID": "ID",
"NAME": "名称",
"AUTHORIZATIONENDPOINT": "授权端点",
"TOKENENDPOINT": "令牌端点",
"USERENDPOINT": "用户端点",
"IDATTRIBUTE": "标识属性",
"AVAILABILITY": "可用性",
"AVAILABLE": "可用的",
"AVAILABLEBUTINACTIVE": "可用但已停用",

View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" x="0px" y="0px" width="598.48541" height="599.83948" viewBox="0 0 598.486 671.089" enable-background="new 0 0 598.486 671.089">
<g transform="translate(0,35.625)">
<path fill="#fff" d="M 277.7249,0.87048682 C 410.2899,-8.3215132 498.1879,56.550487 548.4459,135.58949 C 573.6459,175.21949 598.3709,235.40949 598.4849,297.25249 C 598.6069,364.44649 576.8389,422.63549 548.4459,465.33049 C 519.2639,509.21349 481.5199,545.45849 434.2559,569.25749 C 355.2499,609.04049 244.8359,610.12849 172.5149,571.82349 C 91.972897,529.16549 30.046897,468.27849 7.0028967,362.68749 C -2.2191033,320.43149 -3.2791033,265.83249 9.5688967,218.98749 C 12.583897,207.99849 18.062897,196.43349 22.399897,185.62849 C 43.241897,133.70449 78.716897,88.552487 122.4769,57.323487 C 140.0609,44.775487 161.3929,32.295487 180.2139,23.964487 C 203.6319,13.599487 243.0599,3.2734868 277.7249,0.87048682 z" />
<path fill="#000" d="M 529.1839,304.72449 C 529.1839,430.01249 427.6179,531.57149 302.3319,531.57149 C 177.0459,531.57149 75.481897,430.01249 75.481897,304.72449 C 75.481897,179.43949 177.0459,77.872487 302.3319,77.872487 C 427.6169,77.872487 529.1839,179.43949 529.1839,304.72449 z" />
<path fill="#000" d="M 277.7249,0.87048682 C 410.2899,-8.3215132 498.1879,56.550487 548.4459,135.58949 C 573.6459,175.21949 598.3709,235.40949 598.4849,297.25249 C 598.6069,364.44649 576.8389,422.63549 548.4459,465.33049 C 519.2639,509.21349 481.5199,545.45849 434.2559,569.25749 C 355.2499,609.04049 244.8359,610.12849 172.5149,571.82349 C 91.972897,529.16549 30.046897,468.27849 7.0028967,362.68749 C -2.2191033,320.43149 -3.2791033,265.83249 9.5688967,218.98749 C 12.583897,207.99849 18.062897,196.43349 22.399897,185.62849 C 43.241897,133.70449 78.716897,88.552487 122.4769,57.323487 C 140.0609,44.775487 161.3929,32.295487 180.2139,23.964487 C 203.6319,13.599487 243.0599,3.2734868 277.7249,0.87048682 z M 232.8179,22.682487 C 183.5789,35.448487 147.4759,58.319487 116.0619,82.985487 C 70.762897,118.55349 41.884897,168.18849 24.965897,227.96849 C 6.1428967,294.47649 18.233897,374.95849 44.211897,425.55649 C 71.150897,478.02849 107.3219,518.75949 158.4019,547.44549 C 208.0969,575.35349 277.9929,593.27349 350.8589,579.52149 C 415.5989,567.30349 464.7679,539.10049 504.8239,497.40649 C 558.4159,441.62149 601.4889,338.87249 572.8259,230.53449 C 565.1639,201.57949 555.1469,171.40149 539.4659,145.85349 C 530.9939,132.05149 518.5619,118.47349 506.1069,104.79649 C 459.1009,53.175487 383.1279,8.6924868 285.4229,14.983487 C 266.8289,16.180487 250.4879,18.100487 232.8179,22.682487 z" />
<g style="fill:none;stroke:#fff;stroke-width:2" id="hashpattern">
<g>
<line y2="314.658" x2="578.188" y1="576.79" x1="316.05"/>
<line y2="292.754" x2="556.415" y1="556.03" x1="293.134"/>
<line y2="270.851" x2="534.643" y1="535.273" x1="270.217"/>
<line y2="248.948" x2="512.87" y1="514.513" x1="247.3"/>
<line y2="227.044" x2="491.098" y1="493.754" x1="224.384"/>
<line y2="205.141" x2="469.324" y1="473" x1="201.467"/>
<line y2="183.238" x2="447.552" y1="452.236" x1="178.55"/>
<line y2="161.334" x2="425.778" y1="431.477" x1="155.633"/>
<line y2="139.431" x2="404" y1="410.718" x1="132.716"/>
<line y2="117.528" x2="382.233" y1="389.958" x1="109.8"/>
<line y2="95.625" x2="360.46" y1="369.2" x1="86.883"/>
<line y2="73.721" x2="338.688" y1="348.441" x1="63.966"/>
<line y2="51.818" x2="316.915" y1="327.681" x1="41.049"/>
<line y2="29.915" x2="295.142" y1="306.922" x1="18.132"/>
</g>
<g>
<line y2="576.96" x2="285.419" y1="309.572" x1="18.043" />
<line y2="555.488" x2="307.622" y1="287.579" x1="39.726" />
<line y2="534.014" x2="329.825" y1="265.586" x1="61.409" />
<line y2="512.542" x2="352.029" y1="243.593" x1="83.092" />
<line y2="491.068" x2="374.231" y1="221.6" x1="104.774"/>
<line y2="469.595" x2="396.436" y1="199.607" x1="126.457"/>
<line y2="448.122" x2="418.639" y1="177.614" x1="148.14" />
<line y2="426.648" x2="440.842" y1="155.621" x1="169.822"/>
<line y2="405.175" x2="463.046" y1="133.628" x1="191.505"/>
<line y2="383.7" x2="485.248" y1="111.635" x1="213.188"/>
<line y2="362.229" x2="507.452" y1="89.642" x1="234.871"/>
<line y2="340.755" x2="529.655" y1="67.649" x1="256.553"/>
<line y2="319.283" x2="551.858" y1="45.657" x1="278.236"/>
<line y2="297.809" x2="574.062" y1="23.664" x1="299.92" />
</g>
</g>
<path d="M 490.7099,106.07949 C 467.1169,82.486487 438.1109,61.226487 403.4629,48.342487 C 367.5489,34.987487 326.9229,23.730487 279.0079,27.813487 C 202.6819,34.319487 149.0919,68.564487 108.3629,108.64549 C 79.834897,136.71849 58.375897,171.11949 44.210897,211.28849 C 23.412897,270.26949 24.674897,339.88649 48.059897,399.89549 C 68.006897,451.08249 100.6549,492.36849 146.8539,524.35049 C 190.2849,554.41749 252.6189,577.73649 322.6299,571.82349 C 407.9019,564.62149 470.2939,520.87349 511.2369,470.46349 C 521.7129,457.56749 532.1289,442.99049 538.1799,425.55749 C 544.1089,412.99649 547.0109,404.45749 549.7279,399.89649 C 561.0999,374.41449 567.1249,347.52849 568.9729,317.78249 C 574.6579,226.29049 539.4559,154.82649 490.7099,106.07949 z M 465.5789,384.82749 C 465.4159,385.17549 465.2699,385.49949 465.0999,385.85849 C 460.8699,397.96349 453.5829,408.08549 446.2589,417.04149 C 417.6249,452.04549 373.9959,482.42349 314.3639,487.42549 C 265.4029,491.52949 221.8119,475.33849 191.4409,454.46049 C 165.0489,436.31749 144.9869,413.85949 130.9189,386.86949 C 130.0609,385.24549 121.8909,366.42249 121.8669,365.59449 C 110.7219,331.02549 109.7549,275.43949 121.1939,242.08249 C 128.8279,219.81949 141.5509,195.73149 158.4019,176.64749 C 181.6679,150.29649 204.9509,133.41149 241.7999,121.47649 C 258.6249,116.02649 273.6869,110.47949 294.4039,109.92949 C 344.9239,108.58449 396.3689,131.26749 423.9909,156.11849 C 449.3749,178.95549 478.3049,223.44049 485.5779,265.17649 C 493.0629,308.13349 485.0749,350.07449 465.5789,384.82749 z" />
<path stroke="#000" stroke-width="6" fill="#fff" d="M 377.768,426.033 C 365.328,426.033 354.411,418.155 350.601,406.429 L 336.745,364.211 L 267.43,364.211 L 254.556,406.044 C 250.67,417.998 239.67,426 227.166,426 C 224.164,426 221.182,425.525 218.303,424.591 C 203.357,420.104 194.872,404.017 199.451,388.751 L 257.957,203.428 C 261.756,191.639 272.94,183.416 285.157,183.416 L 316.267,183.416 C 328.553,183.416 339.736,191.499 343.461,203.073 L 404.99,388.327 C 409.91,403.473 401.763,419.732 386.839,424.59 C 383.888,425.548 380.837,426.033 377.768,426.033 L 377.768,426.033 z" />
<g id="OAUTH" fill="#fff">
<g>
<path d="M 148.001,124.354 L 147.928,124.255 C 140.632,114.256 142.773,100.268 153.518,92.426 C 164.263,84.585 178.066,86.786 185.362,96.784 L 185.435,96.883 C 192.731,106.882 190.59,120.871 179.845,128.712 C 169.1,136.553 155.297,134.353 148.001,124.354 z M 175.658,104.171 L 175.585,104.072 C 171.919,99.048 165.093,97.32 159.771,101.204 C 154.498,105.052 154.088,111.907 157.754,116.932 L 157.827,117.031 C 161.494,122.055 168.319,123.783 173.592,119.935 C 178.915,116.051 179.325,109.196 175.658,104.171 z" />
<path d="M 218.344,58.817 L 229.309,55.299 L 260.048,91.033 L 247.851,94.946 L 242.509,88.576 L 226.676,93.656 L 226.096,101.927 L 214.134,105.765 L 218.344,58.817 z M 236.384,80.775 L 228.066,70.573 L 227.177,83.729 L 236.384,80.775 z" />
<path d="M 279.795,69.567 L 279.891,45.364 L 292.023,45.412 L 291.928,69.369 C 291.903,75.589 295.032,78.557 299.836,78.577 C 304.64,78.596 307.792,75.776 307.815,69.741 L 307.912,45.477 L 320.044,45.525 L 319.949,69.42 C 319.894,83.338 311.926,89.404 299.67,89.355 C 287.415,89.305 279.742,83.054 279.795,69.567 z" />
<path d="M 363.859,65.338 L 351.491,61.563 L 354.547,51.55 L 390.71,62.587 L 387.654,72.6 L 375.286,68.826 L 365.759,100.042 L 354.333,96.555 L 363.859,65.338 z" />
<path d="M 423.012,76.559 L 432.958,83.178 L 424.02,96.61 L 436.786,105.106 L 445.725,91.673 L 455.671,98.292 L 431.788,134.181 L 421.841,127.562 L 430.917,113.924 L 418.15,105.428 L 409.075,119.066 L 399.129,112.447 L 423.012,76.559 z"/>
</g>
<g>
<path d="M 458.146,468.883 L 458.222,468.98 C 465.896,478.693 464.29,492.755 453.852,501.001 C 443.414,509.247 429.536,507.575 421.862,497.862 L 421.786,497.765 C 414.112,488.051 415.719,473.99 426.156,465.744 C 436.594,457.499 450.472,459.17 458.146,468.883 z M 431.277,490.11 L 431.353,490.207 C 435.209,495.088 442.096,496.554 447.267,492.469 C 452.389,488.422 452.538,481.556 448.681,476.675 L 448.605,476.578 C 444.75,471.697 437.862,470.231 432.74,474.278 C 427.569,478.363 427.421,485.229 431.277,490.11 z"/>
<path d="M 390.707,537.182 L 379.907,541.179 L 347.625,506.833 L 359.638,502.386 L 365.256,508.516 L 380.85,502.744 L 381.065,494.456 L 392.847,490.095 L 390.707,537.182 z M 371.718,516.04 L 380.477,525.865 L 380.786,512.683 L 371.718,516.04 z"/>
<path d="M 328.888,528.985 L 329.955,553.164 L 317.835,553.699 L 316.778,529.766 C 316.504,523.552 313.236,520.738 308.437,520.95 C 303.638,521.162 300.625,524.131 300.891,530.16 L 301.961,554.4 L 289.841,554.935 L 288.787,531.064 C 288.173,517.16 295.841,510.718 308.084,510.178 C 320.328,509.637 328.293,515.511 328.888,528.985 z"/>
<path d="M 244.671,536.891 L 257.158,540.262 L 254.429,550.37 L 217.918,540.515 L 220.647,530.406 L 233.134,533.777 L 241.641,502.261 L 253.177,505.375 L 244.671,536.891 z"/>
<path d="M 185.65,528.108 L 175.401,521.966 L 183.696,508.125 L 170.543,500.241 L 162.248,514.082 L 152,507.94 L 174.164,470.961 L 184.412,477.104 L 175.99,491.156 L 189.144,499.04 L 197.566,484.988 L 207.814,491.131 L 185.65,528.108 z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.6 KiB