mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-04 13:22:16 +00:00
# Which Problems Are Solved - Clearing OIDC redirect URI lists in the console does not persist correctly resulting in no changes error. # How the Problems Are Solved - Normalizes empty OIDC URI list updates to [""] before sending the save request. - Uses the application v2 update call for the affected OIDC config save path. # References - Closes #12053
This commit is contained in:
@@ -6,8 +6,17 @@ import { MatCheckboxChange } from '@angular/material/checkbox';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { MessageInitShape } from '@bufbuild/protobuf';
|
||||
import { Buffer } from 'buffer';
|
||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||
import { LoginVersionSchema } from '@zitadel/proto/zitadel/application/v2/login_pb';
|
||||
import { UpdateApplicationRequestSchema } from '@zitadel/proto/zitadel/application/v2/application_service_pb';
|
||||
import {
|
||||
OIDCApplicationType as OIDCV2ApplicationType,
|
||||
OIDCAuthMethodType as OIDCV2AuthMethodType,
|
||||
OIDCGrantType as OIDCV2GrantType,
|
||||
OIDCResponseType as OIDCV2ResponseType,
|
||||
OIDCTokenType as OIDCV2TokenType,
|
||||
} from '@zitadel/proto/zitadel/application/v2/oidc_pb';
|
||||
import { mergeMap, Subject, Subscription } from 'rxjs';
|
||||
import { map, take } from 'rxjs/operators';
|
||||
import { RadioItemAuthType } from 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component';
|
||||
@@ -35,7 +44,6 @@ import {
|
||||
import {
|
||||
GetOIDCInformationResponse,
|
||||
UpdateAPIAppConfigRequest,
|
||||
UpdateOIDCAppConfigRequest,
|
||||
UpdateSAMLAppConfigRequest,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||
@@ -43,6 +51,7 @@ import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { ApplicationService } from 'src/app/services/application.service';
|
||||
import { EnvironmentService } from 'src/app/services/environment.service';
|
||||
import { AppSecretDialogComponent } from '../app-secret-dialog/app-secret-dialog.component';
|
||||
import {
|
||||
@@ -192,6 +201,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
private _location: Location,
|
||||
private dialog: MatDialog,
|
||||
private mgmtService: ManagementService,
|
||||
private applicationService: ApplicationService,
|
||||
private authService: GrpcAuthService,
|
||||
private router: Router,
|
||||
private breadcrumbService: BreadcrumbService,
|
||||
@@ -669,48 +679,60 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
this.app.oidcConfig.devMode = !!this.devMode?.value;
|
||||
this.app.oidcConfig.skipNativeAppSuccessPage = !!this.skipNativeAppSuccessPage?.value;
|
||||
|
||||
const req = new UpdateOIDCAppConfigRequest();
|
||||
req.setProjectId(this.projectId);
|
||||
req.setAppId(this.app.id);
|
||||
const loginVersion: MessageInitShape<typeof LoginVersionSchema> = this.oidcLoginV2?.value
|
||||
? {
|
||||
version: {
|
||||
case: 'loginV2',
|
||||
value: { baseUri: this.oidcLoginV2BaseURL?.value },
|
||||
},
|
||||
}
|
||||
: {
|
||||
version: {
|
||||
case: 'loginV1',
|
||||
value: {},
|
||||
},
|
||||
};
|
||||
|
||||
// configuration
|
||||
req.setResponseTypesList(this.app.oidcConfig.responseTypesList);
|
||||
req.setAuthMethodType(this.app.oidcConfig.authMethodType);
|
||||
req.setGrantTypesList(this.app.oidcConfig.grantTypesList);
|
||||
req.setAppType(this.app.oidcConfig.appType);
|
||||
req.setBackChannelLogoutUri(this.app.oidcConfig.backChannelLogoutUri);
|
||||
const login = new LoginVersion();
|
||||
if (this.oidcLoginV2?.value) {
|
||||
const loginV2 = new LoginV2();
|
||||
loginV2.setBaseUri(this.oidcLoginV2BaseURL?.value);
|
||||
login.setLoginV2(loginV2);
|
||||
} else {
|
||||
login.setLoginV1(new LoginV1());
|
||||
}
|
||||
req.setLoginVersion(login);
|
||||
const req: MessageInitShape<typeof UpdateApplicationRequestSchema> = {
|
||||
projectId: this.projectId,
|
||||
applicationId: this.app.id,
|
||||
applicationType: {
|
||||
case: 'oidcConfiguration',
|
||||
value: {
|
||||
// configuration
|
||||
responseTypes: this.app.oidcConfig.responseTypesList.map((type) => this.toOIDCV2ResponseType(type)),
|
||||
authMethodType: this.app.oidcConfig.authMethodType as unknown as OIDCV2AuthMethodType,
|
||||
grantTypes: this.app.oidcConfig.grantTypesList as unknown as OIDCV2GrantType[],
|
||||
applicationType: this.app.oidcConfig.appType as unknown as OIDCV2ApplicationType,
|
||||
backChannelLogoutUri: this.app.oidcConfig.backChannelLogoutUri,
|
||||
loginVersion,
|
||||
|
||||
// token
|
||||
req.setAccessTokenType(this.app.oidcConfig.accessTokenType);
|
||||
req.setAccessTokenRoleAssertion(this.app.oidcConfig.accessTokenRoleAssertion);
|
||||
req.setIdTokenRoleAssertion(this.app.oidcConfig.idTokenRoleAssertion);
|
||||
req.setIdTokenUserinfoAssertion(this.app.oidcConfig.idTokenUserinfoAssertion);
|
||||
// token
|
||||
accessTokenType: this.app.oidcConfig.accessTokenType as unknown as OIDCV2TokenType,
|
||||
accessTokenRoleAssertion: this.app.oidcConfig.accessTokenRoleAssertion,
|
||||
idTokenRoleAssertion: this.app.oidcConfig.idTokenRoleAssertion,
|
||||
idTokenUserinfoAssertion: this.app.oidcConfig.idTokenUserinfoAssertion,
|
||||
|
||||
// redirects
|
||||
req.setRedirectUrisList(this.app.oidcConfig.redirectUrisList);
|
||||
req.setAdditionalOriginsList(this.app.oidcConfig.additionalOriginsList);
|
||||
req.setPostLogoutRedirectUrisList(this.app.oidcConfig.postLogoutRedirectUrisList);
|
||||
req.setDevMode(this.app.oidcConfig.devMode);
|
||||
req.setSkipNativeAppSuccessPage(this.app.oidcConfig.skipNativeAppSuccessPage);
|
||||
// redirects
|
||||
redirectUris: this.normalizeOIDCListForUpdate(this.app.oidcConfig.redirectUrisList),
|
||||
additionalOrigins: this.app.oidcConfig.additionalOriginsList,
|
||||
postLogoutRedirectUris: this.normalizeOIDCListForUpdate(this.app.oidcConfig.postLogoutRedirectUrisList),
|
||||
developmentMode: this.app.oidcConfig.devMode,
|
||||
skipNativeAppSuccessPage: this.app.oidcConfig.skipNativeAppSuccessPage,
|
||||
...(this.clockSkewSeconds?.value
|
||||
? {
|
||||
clockSkew: {
|
||||
seconds: BigInt(Math.floor(this.clockSkewSeconds?.value)),
|
||||
nanos: Math.floor(this.clockSkewSeconds?.value % 1) * 10000,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (this.clockSkewSeconds?.value) {
|
||||
const dur = new Duration();
|
||||
dur.setSeconds(Math.floor(this.clockSkewSeconds?.value));
|
||||
dur.setNanos(Math.floor(this.clockSkewSeconds?.value % 1) * 10000);
|
||||
req.setClockSkew(dur);
|
||||
}
|
||||
|
||||
this.mgmtService
|
||||
.updateOIDCAppConfig(req)
|
||||
this.applicationService
|
||||
.updateApplication(req)
|
||||
.then(() => {
|
||||
if (this.app?.oidcConfig) {
|
||||
const config = { oidc: this.app.oidcConfig };
|
||||
@@ -728,6 +750,21 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
private normalizeOIDCListForUpdate(values: string[]): string[] {
|
||||
return values.length === 0 ? [''] : values;
|
||||
}
|
||||
|
||||
private toOIDCV2ResponseType(type: OIDCResponseType): OIDCV2ResponseType {
|
||||
switch (type) {
|
||||
case OIDCResponseType.OIDC_RESPONSE_TYPE_CODE:
|
||||
return OIDCV2ResponseType.OIDC_RESPONSE_TYPE_CODE;
|
||||
case OIDCResponseType.OIDC_RESPONSE_TYPE_ID_TOKEN:
|
||||
return OIDCV2ResponseType.OIDC_RESPONSE_TYPE_ID_TOKEN;
|
||||
case OIDCResponseType.OIDC_RESPONSE_TYPE_ID_TOKEN_TOKEN:
|
||||
return OIDCV2ResponseType.OIDC_RESPONSE_TYPE_ID_TOKEN_TOKEN;
|
||||
}
|
||||
}
|
||||
|
||||
public saveAPIApp(): void {
|
||||
if (this.apiForm.valid && this.app?.apiConfig) {
|
||||
this.app.apiConfig.authMethodType = this.apiAuthMethodType?.value;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageInitShape } from '@bufbuild/protobuf';
|
||||
import { UpdateApplicationRequestSchema } from '@zitadel/proto/zitadel/application/v2/application_service_pb';
|
||||
|
||||
import { GrpcService } from './grpc.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ApplicationService {
|
||||
constructor(private readonly grpcService: GrpcService) {}
|
||||
|
||||
public updateApplication(req: MessageInitShape<typeof UpdateApplicationRequestSchema>) {
|
||||
return this.grpcService.application.updateApplication(req);
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,13 @@ import { createAdminServiceClient, createAuthServiceClient, createManagementServ
|
||||
import { createGrpcWebTransport } from '@connectrpc/connect-web';
|
||||
import { createClientFor } from '@zitadel/client';
|
||||
|
||||
import { WebKeyService } from '@zitadel/proto/zitadel/webkey/v2/webkey_service_pb';
|
||||
import { ActionService } from '@zitadel/proto/zitadel/action/v2/action_service_pb';
|
||||
import { ApplicationService } from '@zitadel/proto/zitadel/application/v2/application_service_pb';
|
||||
import { WebKeyService } from '@zitadel/proto/zitadel/webkey/v2/webkey_service_pb';
|
||||
|
||||
const createWebKeyServiceClient = createClientFor(WebKeyService);
|
||||
const createActionServiceClient = createClientFor(ActionService);
|
||||
const createApplicationServiceClient = createClientFor(ApplicationService);
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@@ -49,6 +51,7 @@ export class GrpcService {
|
||||
public webKey!: ReturnType<typeof createWebKeyServiceClient>;
|
||||
public organizationNew!: ReturnType<typeof createOrganizationServiceClient>;
|
||||
public adminNew!: ReturnType<typeof createAdminServiceClient>;
|
||||
public application!: ReturnType<typeof createApplicationServiceClient>;
|
||||
|
||||
public assets!: void;
|
||||
|
||||
@@ -108,6 +111,7 @@ export class GrpcService {
|
||||
this.webKey = createWebKeyServiceClient(transport);
|
||||
this.organizationNew = createOrganizationServiceClient(transport);
|
||||
this.adminNew = createAdminServiceClient(transportOldAPIs);
|
||||
this.application = createApplicationServiceClient(transport);
|
||||
|
||||
const authConfig: AuthConfig = {
|
||||
scope: 'openid profile email',
|
||||
|
||||
Reference in New Issue
Block a user