feat(console): specify login UI for SAML apps (#9486)

# Which Problems Are Solved

Users were not yet able to specify (and test) the new login UI or
self-hosted login UI for SAML applications through Console.

# How the Problems Are Solved

Added the configuration for SAML apps (as already available for OIDC) in
Console.

# Additional Changes

None

# Additional Context

- closes #9354
This commit is contained in:
Livio Spring 2025-03-12 13:37:43 +01:00 committed by GitHub
parent b578137139
commit d527a1c824
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 64 additions and 8 deletions

View File

@ -149,10 +149,10 @@
</mat-checkbox> </mat-checkbox>
<mat-checkbox <mat-checkbox
*ngIf="loginV2" *ngIf="oidcLoginV2"
color="primary" color="primary"
class="rt" class="rt"
[formControl]="loginV2" [formControl]="oidcLoginV2"
name="loginV2" name="loginV2"
matTooltip="{{ 'APP.LOGINV2DESC' | translate }}" matTooltip="{{ 'APP.LOGINV2DESC' | translate }}"
> >
@ -239,6 +239,26 @@
></ngx-codemirror> ></ngx-codemirror>
</div> </div>
<div class="saml-login-version">
<form [formGroup]="samlForm">
<mat-checkbox
*ngIf="samlLoginV2"
color="primary"
class="rt"
[formControl]="samlLoginV2"
name="loginV2"
matTooltip="{{ 'APP.LOGINV2DESC' | translate }}"
>
{{ 'APP.LOGINV2.USEV2' | translate }}
</mat-checkbox>
<cnsl-form-field class="app-formfield">
<cnsl-label>{{ 'APP.LOGINV2.BASEURL' | translate }}</cnsl-label>
<input cnslInput formControlName="loginV2BaseURL" />
</cnsl-form-field>
</form>
</div>
<div class="btn-container"> <div class="btn-container">
<button <button
class="submit-button" class="submit-button"

View File

@ -201,6 +201,16 @@
pointer-events: none; pointer-events: none;
} }
} }
.saml-login-version {
margin-top: 2rem;
form {
display: flex;
grid-gap: 1rem;
align-items: center;
}
}
} }
} }

View File

@ -228,6 +228,8 @@ export class AppDetailComponent implements OnInit, OnDestroy {
entityId: ['', []], entityId: ['', []],
acsURL: ['', []], acsURL: ['', []],
metadataXml: [{ value: '', disabled: true }], metadataXml: [{ value: '', disabled: true }],
loginV2: [{ value: false, disabled: true }],
loginV2BaseURL: [{ value: '', disabled: true }],
}); });
this.samlForm.valueChanges.subscribe(() => { this.samlForm.valueChanges.subscribe(() => {
@ -413,6 +415,12 @@ export class AppDetailComponent implements OnInit, OnDestroy {
{ id: 'configuration', i18nKey: 'APP.CONFIGURATION' }, { id: 'configuration', i18nKey: 'APP.CONFIGURATION' },
{ id: 'urls', i18nKey: 'APP.URLS' }, { id: 'urls', i18nKey: 'APP.URLS' },
]; ];
if (this.app.samlConfig?.loginVersion?.loginV1) {
this.samlForm.controls['loginV2'].setValue(false);
} else if (this.app.samlConfig?.loginVersion?.loginV2) {
this.samlForm.controls['loginV2'].setValue(true);
this.samlForm.controls['loginV2BaseURL'].setValue(this.app.samlConfig.loginVersion.loginV2.baseUri);
}
} }
if (allowed) { if (allowed) {
@ -668,9 +676,9 @@ export class AppDetailComponent implements OnInit, OnDestroy {
req.setGrantTypesList(this.app.oidcConfig.grantTypesList); req.setGrantTypesList(this.app.oidcConfig.grantTypesList);
req.setAppType(this.app.oidcConfig.appType); req.setAppType(this.app.oidcConfig.appType);
const login = new LoginVersion(); const login = new LoginVersion();
if (this.loginV2?.value) { if (this.oidcLoginV2?.value) {
const loginV2 = new LoginV2(); const loginV2 = new LoginV2();
loginV2.setBaseUri(this.loginV2BaseURL?.value); loginV2.setBaseUri(this.oidcLoginV2BaseURL?.value);
login.setLoginV2(loginV2); login.setLoginV2(loginV2);
} else { } else {
login.setLoginV1(new LoginV1()); login.setLoginV1(new LoginV1());
@ -757,13 +765,23 @@ export class AppDetailComponent implements OnInit, OnDestroy {
req.setProjectId(this.projectId); req.setProjectId(this.projectId);
req.setAppId(this.app.id); req.setAppId(this.app.id);
if (this.app.samlConfig?.metadataUrl.length > 0) { if (this.app.samlConfig?.metadataUrl?.length > 0) {
req.setMetadataUrl(this.app.samlConfig?.metadataUrl); req.setMetadataUrl(this.app.samlConfig?.metadataUrl);
} }
if (this.app.samlConfig?.metadataXml.length > 0) { if (this.app.samlConfig?.metadataXml?.length > 0) {
req.setMetadataXml(this.app.samlConfig?.metadataXml); req.setMetadataXml(this.app.samlConfig?.metadataXml);
} }
const login = new LoginVersion();
if (this.samlLoginV2?.value) {
const loginV2 = new LoginV2();
loginV2.setBaseUri(this.samlLoginV2BaseURL?.value);
login.setLoginV2(loginV2);
} else {
login.setLoginV1(new LoginV1());
}
req.setLoginVersion(login);
this.mgmtService this.mgmtService
.updateSAMLAppConfig(req) .updateSAMLAppConfig(req)
.then(() => { .then(() => {
@ -860,11 +878,11 @@ export class AppDetailComponent implements OnInit, OnDestroy {
return this.oidcForm.get('authMethodType'); return this.oidcForm.get('authMethodType');
} }
public get loginV2(): FormControl<boolean> | null { public get oidcLoginV2(): FormControl<boolean> | null {
return this.oidcForm.get('loginV2') as FormControl<boolean>; return this.oidcForm.get('loginV2') as FormControl<boolean>;
} }
public get loginV2BaseURL(): AbstractControl | null { public get oidcLoginV2BaseURL(): AbstractControl | null {
return this.oidcForm.get('loginV2BaseURL'); return this.oidcForm.get('loginV2BaseURL');
} }
@ -912,6 +930,14 @@ export class AppDetailComponent implements OnInit, OnDestroy {
return this.samlForm.get('acsURL'); return this.samlForm.get('acsURL');
} }
public get samlLoginV2(): FormControl<boolean> | null {
return this.samlForm.get('loginV2') as FormControl<boolean>;
}
public get samlLoginV2BaseURL(): AbstractControl | null {
return this.samlForm.get('loginV2BaseURL');
}
get decodedBase64(): string { get decodedBase64(): string {
if ( if (
this.app && this.app &&