feat(saml): option to create minimal SAML metadata file (#6671)

* feat: initial look and feel

* feat: initial textarea

* feat: app details and i18n

* fix: add @peintnermax suggestions

* fix: detail component move code to valueChanges.subscribe and clear inputs if metadataurl set

---------

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Elio Bischof <elio@zitadel.com>
Co-authored-by: Fabi <fabienne@zitadel.com>
Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
This commit is contained in:
Miguel Cabrerizo 2023-10-25 19:39:28 +02:00 committed by GitHub
parent b51ad53e5a
commit 9d77dcb467
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 349 additions and 83 deletions

View File

@ -170,26 +170,56 @@
<mat-step *ngIf="appType?.value?.createType === AppCreateType.SAML" [editable]="true">
<ng-template matStepLabel>{{ 'APP.SAML.CONFIGSECTION' | translate }}</ng-template>
<form [formGroup]="samlConfigForm">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'APP.SAML.URL' | translate }}</cnsl-label>
<input cnslInput formControlName="metadataUrl" placeholder="https://" />
</cnsl-form-field>
</form>
<h3 class="title cnsl-secondary-text">
{{ 'APP.SAML.CHOOSEMETADATASOURCE' | translate }}
</h3>
<span class="cnsl-app-or cnsl-secondary-text">{{ 'APP.SAML.OR' | translate }}</span>
<div class="cnsl-secondary-text metadata-option">
<span class="saml-config-option">{{ 'APP.SAML.METADATAOPT1' | translate }}</span>
<form [formGroup]="samlConfigForm">
<cnsl-form-field class="formfield">
<cnsl-label></cnsl-label>
<input cnslInput formControlName="metadataUrl" placeholder="https://" />
</cnsl-form-field>
</form>
</div>
<input
#xmlFileInput
style="display: none"
class="file-input"
type="file"
accept="text/xml,application/xml"
(change)="onDropXML($any($event.target).files)"
/>
<button type="button" mat-stroked-button (click)="$event.preventDefault(); xmlFileInput.click()">
{{ 'APP.SAML.XML' | translate }}
</button>
<div class="cnsl-secondary-text metadata-option">
<span class="saml-config-option">{{ 'APP.SAML.METADATAOPT2' | translate }}</span>
<form>
<input
#xmlFileInput
style="display: none"
class="file-input"
type="file"
accept="text/xml,application/xml"
(change)="onDropXML($any($event.target).files)"
/>
<button
type="button"
class="upload-button"
mat-stroked-button
(click)="$event.preventDefault(); xmlFileInput.click()"
>
{{ 'APP.SAML.UPLOAD' | translate }}
</button>
</form>
</div>
<div class="cnsl-secondary-text metadata-option">
<span class="saml-config-option">{{ 'APP.SAML.METADATAOPT3' | translate }}</span>
<form [formGroup]="samlConfigForm">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'APP.SAML.ENTITYID' | translate }}</cnsl-label>
<input cnslInput formControlName="entityId" placeholder="https://" />
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'APP.SAML.ACSURL' | translate }}</cnsl-label>
<input cnslInput formControlName="acsURL" placeholder="https://" />
</cnsl-form-field>
</form>
</div>
<div
class="saml-xml"
@ -199,6 +229,7 @@
<!-- <p class="preview-text cnsl-secondary-text">PREVIEW</p> -->
<ngx-codemirror
[(ngModel)]="decodedBase64"
[ngModelOptions]="{ standalone: true }"
[options]="{
lineNumbers: true,
theme: 'material',
@ -419,31 +450,64 @@
<div class="content">
<ng-container *ngIf="formappType?.value?.createType === AppCreateType.SAML">
<div class="saml">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'APP.SAML.URL' | translate }}</cnsl-label>
<input cnslInput formControlName="metadataUrl" placeholder="https://" />
</cnsl-form-field>
<h3 class="title cnsl-secondary-text">
{{ 'APP.SAML.CHOOSEMETADATASOURCE' | translate }}
</h3>
<div class="cnsl-secondary-text metadata-option">
<span class="saml-config-option">{{ 'APP.SAML.METADATAOPT1' | translate }}</span>
<form [formGroup]="samlConfigForm">
<cnsl-form-field class="formfield">
<cnsl-label></cnsl-label>
<input cnslInput formControlName="metadataUrl" placeholder="https://" />
</cnsl-form-field>
</form>
</div>
<span class="cnsl-app-or cnsl-secondary-text">{{ 'APP.SAML.OR' | translate }}</span>
<div class="cnsl-secondary-text metadata-option">
<span class="saml-config-option">{{ 'APP.SAML.METADATAOPT2' | translate }}</span>
<input
#xmlFileInput
style="display: none"
class="file-input"
type="file"
(change)="onDropXML($any($event.target).files)"
/>
<button type="button" mat-stroked-button (click)="$event.preventDefault(); xmlFileInput.click()">
{{ 'APP.SAML.XML' | translate }}
</button>
<form>
<input
#xmlFileInput
style="display: none"
class="file-input"
type="file"
accept="text/xml,application/xml"
(change)="onDropXML($any($event.target).files)"
/>
<button
type="button"
class="upload-button"
mat-stroked-button
(click)="$event.preventDefault(); xmlFileInput.click()"
>
{{ 'APP.SAML.UPLOAD' | translate }}
</button>
</form>
</div>
<div class="cnsl-secondary-text metadata-option">
<span class="saml-config-option">{{ 'APP.SAML.METADATAOPT3' | translate }}</span>
<form [formGroup]="samlConfigForm">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'APP.SAML.ENTITYID' | translate }}</cnsl-label>
<input cnslInput formControlName="entityId" placeholder="https://" />
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'APP.SAML.ACSURL' | translate }}</cnsl-label>
<input cnslInput formControlName="acsURL" placeholder="https://" />
</cnsl-form-field>
</form>
</div>
<div
class="saml-xml"
[ngClass]="{ disabled: !!formMetadataUrl?.value }"
[ngClass]="{ disabled: !!metadataUrl?.value }"
*ngIf="decodedBase64 && samlAppRequest.toObject().metadataXml && !samlAppRequest.toObject().metadataUrl"
>
<ngx-codemirror
[(ngModel)]="decodedBase64"
[ngModelOptions]="{ standalone: true }"
[options]="{
lineNumbers: true,
theme: 'material',

View File

@ -129,6 +129,10 @@ p.desc {
display: block;
width: 100%;
margin: 0 0.5rem;
.formfield {
margin: 0;
}
}
}
@ -138,3 +142,20 @@ p.desc {
padding: 0.5rem 4rem;
}
}
.metadata-option {
margin-top: 2rem;
margin-bottom: 2rem;
display: flex;
flex-direction: column;
.upload-button {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
width: 25%;
}
.saml-config-option {
font-size: 14px;
}
}

View File

@ -150,6 +150,8 @@ export class AppCreateComponent implements OnInit, OnDestroy {
this.samlConfigForm = this.fb.group({
metadataUrl: ['', []],
entityId: ['', []],
acsURL: ['', []],
});
this.firstFormGroup.valueChanges.subscribe((value) => {
@ -218,9 +220,24 @@ export class AppCreateComponent implements OnInit, OnDestroy {
});
this.samlConfigForm.valueChanges.subscribe((form) => {
let minimalMetadata =
this.entityId?.value && this.acsURL?.value
? `<?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="${this.entityId?.value}">
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol">
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="${this.acsURL?.value}" index="0"/>
</md:SPSSODescriptor>
</md:EntityDescriptor>`
: '';
if (form.metadataUrl && form.metadataUrl.length > 0) {
this.samlAppRequest.setMetadataUrl(form.metadataUrl);
}
if (this.samlAppRequest) {
const base64 = Buffer.from(minimalMetadata, 'utf-8').toString('base64');
this.samlAppRequest.setMetadataXml(base64);
}
});
}
@ -352,6 +369,8 @@ export class AppCreateComponent implements OnInit, OnDestroy {
public onDropXML(filelist: FileList): void {
const file = filelist.item(0);
this.metadataUrl?.setValue('');
this.entityId?.setValue('');
this.acsURL?.setValue('');
if (file) {
if (file.size > MAX_ALLOWED_SIZE) {
this.toast.showInfo('POLICY.PRIVATELABELING.MAXSIZEEXCEEDED', true);
@ -547,4 +566,12 @@ export class AppCreateComponent implements OnInit, OnDestroy {
public get metadataUrl(): AbstractControl | null {
return this.samlConfigForm.get('metadataUrl');
}
public get entityId(): AbstractControl | null {
return this.samlConfigForm.get('entityId');
}
public get acsURL(): AbstractControl | null {
return this.samlConfigForm.get('acsURL');
}
}

View File

@ -157,17 +157,22 @@
</form>
</cnsl-card>
<cnsl-card *ngIf="samlForm && app?.samlConfig">
<form [formGroup]="samlForm">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'APP.SAML.URL' | translate }}</cnsl-label>
<input cnslInput formControlName="metadataUrl" placeholder="https://" />
</cnsl-form-field>
</form>
<cnsl-card *ngIf="samlForm && app?.samlConfig" title="{{ 'APP.SAML.CONFIGSECTION' | translate }}">
<h3 class="title cnsl-secondary-text">
{{ 'APP.SAML.CHOOSEMETADATASOURCE' | translate }}
</h3>
<div class="cnsl-saml-config-line">
<span class="cnsl-app-or cnsl-secondary-text">{{ 'APP.SAML.OR' | translate }}</span>
<div class="metadata-option">
<span class="saml-config-option">{{ 'APP.SAML.METADATAOPT1' | translate }}</span>
<form [formGroup]="samlForm">
<cnsl-form-field class="formfield">
<input cnslInput formControlName="metadataUrl" placeholder="https://" />
</cnsl-form-field>
</form>
</div>
<div class="metadata-option">
<span class="saml-config-option">{{ 'APP.SAML.METADATAOPT2' | translate }}</span>
<input
#xmlFileInput
style="display: none"
@ -176,11 +181,25 @@
accept="text/xml,application/xml"
(change)="onDropXML($any($event.target).files)"
/>
<button mat-stroked-button (click)="$event.preventDefault(); xmlFileInput.click()">
{{ 'APP.SAML.XML' | translate }}
<button class="upload-button" mat-stroked-button (click)="$event.preventDefault(); xmlFileInput.click()">
{{ 'APP.SAML.UPLOAD' | translate }}
</button>
</div>
<div class="metadata-option">
<span class="saml-config-option">{{ 'APP.SAML.METADATAOPT3' | translate }}</span>
<form [formGroup]="samlForm">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'APP.SAML.ENTITYID' | translate }}</cnsl-label>
<input cnslInput formControlName="entityId" placeholder="https://" />
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'APP.SAML.ACSURL' | translate }}</cnsl-label>
<input cnslInput formControlName="acsURL" placeholder="https://" />
</cnsl-form-field>
</form>
</div>
<div
class="saml-xml"
[ngClass]="{ disabled: !!metadataUrl?.value }"

View File

@ -10,6 +10,27 @@
$button-disabled-text-color: map-get($foreground, disabled-button);
$divider-color: map-get($foreground, dividers);
.title {
margin-bottom: 1rem;
}
.metadata-option {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
display: flex;
flex-direction: column;
.upload-button {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
width: 25%;
}
.saml-config-option {
font-size: 14px;
}
}
.app-zitadel-warning {
font-size: 14px;
color: $warn-color;

View File

@ -1,6 +1,6 @@
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
import { Location } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { MatLegacyCheckboxChange as MatCheckboxChange } from '@angular/material/legacy-checkbox';
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
@ -183,8 +183,33 @@ export class AppDetailComponent implements OnInit, OnDestroy {
this.samlForm = this.fb.group({
metadataUrl: [{ value: '', disabled: true }],
entityId: ['', []],
acsURL: ['', []],
metadataXml: [{ value: '', disabled: true }],
});
this.samlForm.valueChanges.subscribe((form) => {
let minimalMetadata =
this.entityId?.value && this.acsURL?.value
? `<?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="${this.entityId?.value}">
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol">
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="${this.acsURL?.value}" index="0"/>
</md:SPSSODescriptor>
</md:EntityDescriptor>`
: '';
if (this.metadataUrl && this.metadataUrl.value.length > 0) {
if (this.app && this.app.samlConfig && this.app.samlConfig.metadataXml) {
this.app.samlConfig.metadataXml = '';
}
}
if (this.app && this.app.samlConfig && this.app.samlConfig.metadataXml && minimalMetadata) {
const base64 = Buffer.from(minimalMetadata, 'utf-8').toString('base64');
this.app.samlConfig.metadataXml = base64;
}
});
}
public formatClockSkewLabel(seconds: number): string {
@ -406,6 +431,8 @@ export class AppDetailComponent implements OnInit, OnDestroy {
this.toast.showInfo('POLICY.PRIVATELABELING.MAXSIZEEXCEEDED', true);
} else {
this.metadataUrl?.setValue('');
this.entityId?.setValue('');
this.acsURL?.setValue('');
const reader = new FileReader();
reader.onload = ((aXML) => {
return (e) => {
@ -779,6 +806,14 @@ export class AppDetailComponent implements OnInit, OnDestroy {
return this.samlForm.get('metadataUrl');
}
public get entityId(): AbstractControl | null {
return this.samlForm.get('entityId');
}
public get acsURL(): AbstractControl | null {
return this.samlForm.get('acsURL');
}
get decodedBase64(): string {
if (
this.app &&

View File

@ -2071,11 +2071,16 @@
"DESCRIPTION": "SAML приложения"
},
"CONFIGSECTION": "SAML конфигурация",
"URL": "Url, където се намира файлът с метаданни",
"OR": "или",
"XML": "Качете XML метаданни",
"CHOOSEMETADATASOURCE": "Предоставете вашата SAML конфигурация, като използвате една от следните опции:",
"METADATAOPT1": "Опция 1. Посочете URL адреса, където се намира файлът с метаданни",
"METADATAOPT2": "Опция 2. Качете файл, съдържащ вашите XML метаданни",
"METADATAOPT3": "Опция 3. Създайте минимален файл с метаданни в движение, предоставяйки ENTITYID и ACS URL",
"UPLOAD": "Качете XML файл",
"METADATA": "Метаданни",
"METADATAFROMFILE": "Метаданни от файл"
"METADATAFROMFILE": "Метаданни от файл",
"CREATEMETADATA": "Създайте метаданни",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {

View File

@ -2080,11 +2080,16 @@
"DESCRIPTION": "SAML Applikationen"
},
"CONFIGSECTION": "SAML Konfiguration",
"URL": "Url der Metadaten-Datei",
"OR": "oder",
"XML": "Metadaten XML hochladen",
"CHOOSEMETADATASOURCE": "Stellen Sie Ihre SAML-Konfiguration mit einer der folgenden Optionen bereit:",
"METADATAOPT1": "Option 1: Geben Sie die URL an, unter der sich die Metadatendatei befindet",
"METADATAOPT2": "Option 2: Laden Sie eine Datei hoch, die Ihre XML-Metadaten enthält",
"METADATAOPT3": "Option 3: Erstellen Sie spontan eine minimale Metadatendatei mit ENTITYID und ACS-URL",
"UPLOAD": "XML-Datei hochladen",
"METADATA": "Metadaten",
"METADATAFROMFILE": "Metadata aus Datei"
"METADATAFROMFILE": "Metadata aus Datei",
"CREATEMETADATA": "Create metadata",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {

View File

@ -2089,11 +2089,16 @@
"DESCRIPTION": "SAML Applications"
},
"CONFIGSECTION": "SAML Configuration",
"URL": "Url where Metadata file is located",
"OR": "or",
"XML": "Upload Metadata XML",
"CHOOSEMETADATASOURCE": "Provide your SAML configuration using one of the following options:",
"METADATAOPT1": "Option 1. Specify the url where metadata file is located",
"METADATAOPT2": "Option 2. Upload a file containing your metadata XML",
"METADATAOPT3": "Option 3. Create a minimal metadata file on the fly providing ENTITYID and ACS URL",
"UPLOAD": "Upload XML file",
"METADATA": "Metadata",
"METADATAFROMFILE": "Metadata from File"
"METADATAFROMFILE": "Metadata from file",
"CREATEMETADATA": "Create metadata",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {

View File

@ -2077,11 +2077,16 @@
"DESCRIPTION": "Aplicaciones SAML"
},
"CONFIGSECTION": "Configuración SAML",
"URL": "URL donde está ubicado el fichero de metadatos",
"OR": "o",
"XML": "Sube un fichero XML de metadatos",
"CHOOSEMETADATASOURCE": "Proporciona tu configuración SAML usando una de las siguientes opciones:",
"METADATAOPT1": "Opción 1. Especifica la URL donde se encuentra el fichero de metadatos",
"METADATAOPT2": "Opción 2. Sube un fichero que contenga tus metadatos XML",
"METADATAOPT3": "Opción 3. Crea, al vuelo, un fichero de metadatos mínimo proporcionando el ENTITYID y la ACS URL",
"UPLOAD": "Subir fichero XML",
"METADATA": "Metadatos",
"METADATAFROMFILE": "Metadatos desde un fichero"
"METADATAFROMFILE": "Metadatos desde un fichero",
"CREATEMETADATA": "Crear metadatos",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {

View File

@ -2075,6 +2075,23 @@
"1": "Clé privée JWT"
}
},
"SAML": {
"SELECTION": {
"TITLE": "SAML",
"DESCRIPTION": "Applications SAML"
},
"CONFIGSECTION": "Configuration SAML",
"CHOOSEMETADATASOURCE": "Fournissez votre configuration SAML à l'aide de l'une des options suivantes :",
"METADATAOPT1": "Option 1. Spécifiez l'URL où se trouve le fichier de métadonnées",
"METADATAOPT2": "Option 2. Téléchargez un fichier contenant vos métadonnées XML",
"METADATAOPT3": "Option 3. Créer un fichier de métadonnées minimal à la volée fournissant l'ENTITYID et l'URL ACS",
"UPLOAD": "Télécharger le fichier XML",
"METADATA": "Métadonnées",
"METADATAFROMFILE": "Métadonnées du fichier",
"CREATEMETADATA": "Créer des métadonnées",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {
"TITLE": "Code",

View File

@ -2081,11 +2081,16 @@
"DESCRIPTION": "Applicazioni SAMML"
},
"CONFIGSECTION": "Configurazione SAML",
"URL": "URL in cui si trova il file di metadati",
"OR": "o",
"XML": "Carica Metadata XML",
"CHOOSEMETADATASOURCE": "Fornisci la tua configurazione SAML utilizzando una delle seguenti opzioni:",
"METADATAOPT1": "Opzione 1. Specificare l'URL in cui si trova il file di metadati",
"METADATAOPT2": "Opzione 2. Carica un file contenente il tuo XML di metadati",
"METADATAOPT3": "Opzione 3. Crea al volo un file di metadati minimo fornendo ENTITYID e URL ACS",
"UPLOAD": "Carica il file XML",
"METADATA": "Metadata",
"METADATAFROMFILE": "Metadati dal file"
"METADATAFROMFILE": "Metadati dal file",
"CREATEMETADATA": "Crea metadati",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {

View File

@ -2072,11 +2072,16 @@
"DESCRIPTION": "SAMLアプリケーション"
},
"CONFIGSECTION": "SAML構成",
"URL": "メタデータファイルが配置されているURL",
"OR": "または",
"XML": "メタデータXMLをアップロードする",
"CHOOSEMETADATASOURCE": "次のオプションのいずれかを使用して SAML 構成を指定します。",
"METADATAOPT1": "オプション 1. メタデータ ファイルが存在する URL を指定する",
"METADATAOPT2": "オプション 2. メタデータ XML を含むファイルをアップロードする",
"METADATAOPT3": "オプション 3. ENTITYID と ACS URL を指定して最小限のメタデータ ファイルをオンザフライで作成する",
"UPLOAD": "XMLファイルをアップロードする",
"METADATA": "メタデータ",
"METADATAFROMFILE": "ファイルからのメタデータ"
"METADATAFROMFILE": "ファイルからのメタデータ",
"CREATEMETADATA": "メタデータの作成",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {

View File

@ -2078,11 +2078,16 @@
"DESCRIPTION": "SAML Апликации"
},
"CONFIGSECTION": "SAML Конфигурација",
"URL": "URL каде што се наоѓа Metadata датотеката",
"OR": "или",
"XML": "Подигни Metadata XML",
"METADATA": "Metadata",
"METADATAFROMFILE": "Metadata од датотека"
"CHOOSEMETADATASOURCE": "Обезбедете ја вашата SAML конфигурација користејќи една од следниве опции:",
"METADATAOPT1": "Опција 1. Наведете ја адресата каде што се наоѓа датотеката со метаподатоци",
"METADATAOPT2": "Опција 2. Поставете датотека што ги содржи вашите метаподатоци XML",
"METADATAOPT3": "Опција 3. Создадете датотека со минимални метаподатоци во лет, обезбедувајќи ENTITYID и ACS URL",
"UPLOAD": "Поставете XML датотека",
"METADATA": "Метаподатоци",
"METADATAFROMFILE": "Метаподатоци од датотека",
"CREATEMETADATA": "Креирајте метаподатоци",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {

View File

@ -2081,11 +2081,16 @@
"DESCRIPTION": "Aplikacje SAML"
},
"CONFIGSECTION": "Konfiguracja SAML",
"URL": "Adres URL, gdzie znajduje się plik metadanych",
"OR": "lub",
"XML": "Prześlij plik XML metadanych",
"CHOOSEMETADATASOURCE": "Podaj konfigurację SAML, korzystając z jednej z następujących opcji:",
"METADATAOPT1": "Opcja 1. Podaj adres URL, pod którym znajduje się plik metadanych",
"METADATAOPT2": "Opcja 2. Prześlij plik zawierający metadane XML",
"METADATAOPT3": "Opcja 3. Utwórz na bieżąco minimalny plik metadanych, podając ENTITYID i adres URL ACS",
"UPLOAD": "Prześlij plik XML",
"METADATA": "Metadane",
"METADATAFROMFILE": "Metadane z pliku"
"METADATAFROMFILE": "Metadane z pliku",
"CREATEMETADATA": "Utwórz metadane",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {

View File

@ -2076,11 +2076,16 @@
"DESCRIPTION": "Aplicativos SAML"
},
"CONFIGSECTION": "Configuração SAML",
"URL": "URL onde o arquivo de Metadados está localizado",
"OR": "ou",
"XML": "Carregar XML de Metadados",
"CHOOSEMETADATASOURCE": "Forneça sua configuração SAML usando uma das seguintes opções:",
"METADATAOPT1": "Opção 1. Especifique o URL onde o arquivo de metadados está localizado",
"METADATAOPT2": "Opção 2. Faça upload de um arquivo contendo seu XML de metadados",
"METADATAOPT3": "Opção 3. Crie um arquivo mínimo de metadados instantaneamente fornecendo ENTITYID e URL ACS",
"UPLOAD": "Prześlij plik XML",
"METADATA": "Metadados",
"METADATAFROMFILE": "Metadados do Arquivo"
"METADATAFROMFILE": "Metadados do Arquivo",
"CREATEMETADATA": "Criar metadados",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {

View File

@ -2074,6 +2074,23 @@
"1": "Private Key JWT"
}
},
"SAML": {
"SELECTION": {
"TITLE": "SAML",
"DESCRIPTION": "SAML 应用"
},
"CONFIGSECTION": "SAML 配置",
"CHOOSEMETADATASOURCE": "使用以下选项之一提供您的 SAML 配置:",
"METADATAOPT1": "选项 1.指定元数据文件所在的 url",
"METADATAOPT2": "选项 2. 上传包含元数据 XML 的文件",
"METADATAOPT3": "选项 3. 动态创建最小元数据文件,提供 ENTITYID 和 ACS URL",
"UPLOAD": "上传 XML 文件",
"METADATA": "元数据",
"METADATAFROMFILE": "文件中的元数据",
"CREATEMETADATA": "创建元数据",
"ENTITYID": "Entity ID",
"ACSURL": "ACS endpoint URL"
},
"AUTHMETHODS": {
"CODE": {
"TITLE": "Code",