From 2d91df1d22509263b711cee8de025d6663181be8 Mon Sep 17 00:00:00 2001 From: Ryan Galletto Date: Tue, 8 Oct 2024 13:05:46 -0400 Subject: [PATCH 1/3] Added URI validation and improve layout for Cert PEM & JWKS Endpoint fields --- .../jwt-signer/jwt-signer-form.component.html | 23 ++++++++++++----- .../jwt-signer/jwt-signer-form.component.ts | 25 +++++++++++++++++-- .../src/lib/services/validation.service.ts | 9 +++++++ 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html index 6831d149..eab51146 100644 --- a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html @@ -146,12 +146,23 @@ - - - +
+
+
+ OR +
+
+
+
+
+
+
+ JWKS Endpoint +
+
+ +
+
{ this.growlerService.show(growlerData); }); diff --git a/projects/ziti-console-lib/src/lib/services/validation.service.ts b/projects/ziti-console-lib/src/lib/services/validation.service.ts index 01bf774a..5baaaf88 100644 --- a/projects/ziti-console-lib/src/lib/services/validation.service.ts +++ b/projects/ziti-console-lib/src/lib/services/validation.service.ts @@ -110,6 +110,15 @@ export class ValidationService { return isBase64(base64Content); } + isValidURI(uri) { + try { + new URL(uri); + return true; + } catch (e) { + return false; + } + } + redefineObject(obj) { for (let prop in obj) { if (Array.isArray(obj[prop]) && obj[prop].length==0) { From fac93c94599552edacf467ca3972dcfb8f642d56 Mon Sep 17 00:00:00 2001 From: Ryan Galletto Date: Fri, 11 Oct 2024 16:12:43 -0400 Subject: [PATCH 2/3] * Added missing fields for JWT Signer: clientId, scopes * Improved behavior of selecting between of JWKS Endpoint and Cert PEM * Changed styling for toggle fields --- .../text-list/text-list-input.component.scss | 106 ------------- .../jwt-signer/jwt-signer-form.component.html | 147 ++++++++++++------ .../jwt-signer/jwt-signer-form.component.scss | 75 +++++++++ .../jwt-signer/jwt-signer-form.component.ts | 106 +++++++++---- .../jwt-signer/jwt-signer-form.service.ts | 2 +- .../src/lib/models/jwt-signer.ts | 4 +- .../src/lib/services/node-data.service.ts | 22 +++ .../services/ziti-controller-data.service.ts | 20 +++ .../src/lib/services/ziti-data.service.ts | 1 + .../src/lib/shared-assets/styles/global.scss | 112 ++++++++++++- .../src/lib/ziti-console-lib.module.ts | 2 + 11 files changed, 410 insertions(+), 187 deletions(-) diff --git a/projects/ziti-console-lib/src/lib/features/dynamic-widgets/text-list/text-list-input.component.scss b/projects/ziti-console-lib/src/lib/features/dynamic-widgets/text-list/text-list-input.component.scss index c1d40a03..e69de29b 100644 --- a/projects/ziti-console-lib/src/lib/features/dynamic-widgets/text-list/text-list-input.component.scss +++ b/projects/ziti-console-lib/src/lib/features/dynamic-widgets/text-list/text-list-input.component.scss @@ -1,106 +0,0 @@ -::ng-deep .p-element { - - .p-chips.p-component { - width: 100%; - font-weight: 400; - font-family: 'Open Sans', Arial, sans-serif; - height: var(--defaultInputHeight); - border-color: var(--stroke); - border-style: solid; - border-width: var(--inputBorderWidth); - border-radius: var(--inputBorderRadius); - padding-left: 10px; - padding-right: 10px; - outline: none; - box-sizing: border-box; - font-size: 15px; - background-color: var(--background) !important; - color: var(--text); - -webkit-appearance: none; - - .p-inputtext.p-chips-multiple-container { - width: 100%; - padding: 0; - border-width: var(--inputBorderWidth); - - &.p-focus { - border-color: var(--primaryColor) !important; - box-shadow: 0 0 7px 0 var(--primaryColorOpaque) !important; - - &.error { - border-color: var(--red) !important; - } - } - } - } - - .p-chips .p-chips-multiple-container .p-chips-input-token input { - height: 25px; - font-size: 14px; - color: #495057; - padding: 0; - margin: 0; - border: 0 none; - outline: 0 none; - background-color: transparent; - box-shadow: none; - border-radius: 0; - width: 100% - } - - .p-chips .p-chips-multiple-container .p-chips-token { - margin-right: .5rem; - font-family: Open Sans, sans-serif; - font-weight: 600; - margin-top: 5px; - margin-bottom: 5px; - background: var(--primary); - color: var(--white); - border-radius: var(--inputBorderRadius); - cursor: default; - display: inline-flex; - align-items: center; - flex: 0 0 auto; - max-width: 100% - } - - .p-chips-token-icon { - margin-left: 0.5rem; - cursor: pointer; - color:blue; - fill: red; - } - - .p-chips { - display: inline-flex - } - - .p-chips-token-label { - min-width: 0; - overflow: auto - } - - .p-chips-token-label::-webkit-scrollbar { - display: none - } - - .p-fluid .p-chips { - display: flex - } - - .p-chips-clear-icon { - position: absolute; - top: 50%; - margin-top: -.5rem; - cursor: pointer; - } - - .p-chips-clearable .p-inputtext { - position: relative - } - - .p-inputtext { - border:none; - } -} - diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html index eab51146..1fd85abe 100644 --- a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html @@ -43,57 +43,33 @@ Claims Property
- +
Audience
-
-
- External Auth Url -
-
- -
-
-
-
ENABLED
-
- YES - NO -
+
+
Use External ID
+
-
-
- -
-
-
Use External ID
+ +
+
+
+ Client ID +
+
+ +
+
+
+ External Auth Url +
+
+ +
+
+
+
+ Scopes +
+
+ + +
+
-
+
+
+
+
+
+ JWKS Endpoint +
+
+
+
+
+ Cert PEM +
+
+
+
+
+
+ JWKS Endpoint +
+
+ +
+
+
@@ -146,21 +192,22 @@
-
-
-
- OR -
-
-
-
-
-
-
- JWKS Endpoint -
+ + +
+
+
ENABLED
+
+ YES + NO +
-
diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.scss b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.scss index e469669a..68e27d65 100644 --- a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.scss +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.scss @@ -25,6 +25,7 @@ cursor: pointer; border-radius: var(--inputBorderRadius); gap: var(--marginMedium); + margin-top: -5px; &:hover { filter: brightness(.8); @@ -83,3 +84,77 @@ } } } + +.radio-group-container { + display: flex; + gap: var(--marginLarge); + + &:focus { + .radio-button-container { + .radio-button-circle { + border-color: var(--primaryColor); + } + } + } + + .radio-button-container { + display: flex; + flex-direction: row; + align-items: center; + background-color: var(--formGroup); + border-radius: var(--inputBorderRadius); + width: 100%; + padding-left: var(--paddingMedium); + padding-right: var(--paddingMedium); + padding-top: var(--paddingLarge); + padding-bottom: var(--paddingLarge); + cursor: pointer; + gap: var(--marginMedium); + + .radio-button-circle { + display: flex; + width: 21px; + height: 21px; + border-radius: 21px; + border-width: 2px; + border-style: solid; + border-color: var(--offWhite); + align-items: center; + justify-content: center; + background-color: var(--offWhite); + + .radio-button-inner-circle { + display: none; + width: 15px; + height: 15px; + border-radius: 15px; + align-items: center; + justify-content: center; + background-color: var(--primaryColor); + } + } + + &.selected { + .radio-button-circle { + .radio-button-inner-circle { + display: flex; + } + } + } + + &:active { + .radio-button-circle { + .radio-button-inner-circle { + display: flex; + background-color: var(--menu); + } + } + } + + .radio-button-label { + color: var(--offWhite); + font-size: 14px; + font-weight: 600; + } + } +} diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.ts b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.ts index 2e0f2c4a..16d9be61 100644 --- a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.ts +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.ts @@ -56,6 +56,7 @@ export class JwtSignerFormComponent extends ProjectableForm implements OnInit, O items: any = []; settings: any = {}; fileSelectOpening = false; + signatureMethod = "JWKS_ENDPOINT"; override entityType = 'external-jwt-signers'; override entityClass = JwtSigner; @@ -171,34 +172,48 @@ export class JwtSignerFormComponent extends ProjectableForm implements OnInit, O `Please enter a value for the highlighted fields: ${missingFields}`, )); } - if (!isEmpty(this.formData.certPem) && !isEmpty(this.formData.jwksEndpoint)) { - this.errors.certPem = true; - this.errors.jwksEndpoint = true; - growlers.push(new GrowlerModel( - 'error', - 'Invalid', - `Cert PEM or JWKS Endpoint`, - `Only one of Cert PEM or JWKS Endpoint are allowed. Remove one and try again.`, - )); - } - if (!isEmpty(this.formData.certPem?.trim()) && !this.validationService.isValidPEM(this.formData.certPem?.trim())) { - this.errors.certPem = true; - growlers.push(new GrowlerModel( - 'error', - 'Invalid', - `Cert PEM Invalid`, - `The value you have entered for the Cert PEM field is invalid. Please check your input and try again.`, - )); + if (!isEmpty(growlers)) { + growlers.forEach((growlerData) => { + this.growlerService.show(growlerData); + }); + return isEmpty(this.errors); } - - if (!isEmpty(this.formData.jwksEndpoint) && !this.validationService.isValidURI(this.formData.jwksEndpoint)) { - this.errors.certPem = true; - growlers.push(new GrowlerModel( - 'error', - 'Invalid', - `JWKS Endpoint Invalid`, - `The value you have entered for the JWKS Endpoint field is invalid. Please check your input and try again.`, - )); + if (this.signatureMethod === 'JWKS_ENDPOINT') { + if (isEmpty(this.formData.jwksEndpoint)) { + this.errors.jwksEndpoint = true; + growlers.push(new GrowlerModel( + 'error', + 'Invalid', + `Missing JWKS Endpoint`, + `Please enter a URI for the JWKS Endpoint.`, + )); + } else if (!this.validationService.isValidURI(this.formData.jwksEndpoint)) { + this.errors.jwksEndpoint = true; + growlers.push(new GrowlerModel( + 'error', + 'Invalid', + `JWKS Endpoint Invalid`, + `The value you have entered for the JWKS Endpoint field is invalid. Please check your input and try again.`, + )); + } + } else if (this.signatureMethod === 'CERT_PEM') { + if (isEmpty(this.formData.certPem)) { + this.errors.certPem = true; + growlers.push(new GrowlerModel( + 'error', + 'Invalid', + `Missing Cert PEM`, + `Please enter a URI for the JWKS Endpoint.`, + )); + } else if (!this.validationService.isValidPEM(this.formData.certPem?.trim())) { + this.errors.certPem = true; + growlers.push(new GrowlerModel( + 'error', + 'Invalid', + `Cert PEM Invalid`, + `The Cert PEM you entered is invalid. Please check your input and try again.`, + )); + } } growlers.forEach((growlerData) => { @@ -216,12 +231,14 @@ export class JwtSignerFormComponent extends ProjectableForm implements OnInit, O name: this.formData.name || '', audience: this.formData.audience || '', issuer: this.formData.issuer || '', + clientId: this.formData.clientId || '', certPem: this.formData.certPem || '', claimsProperty: this.formData.claimsProperty || '', enabled: this.formData.enabled, useExternalId: this.formData.useExternalId, - externalAuthUrl: this.formData.externalAuthUrl || '', kid: this.formData.kid || '', + externalAuthUrl: this.formData.externalAuthUrl || '', + scopes: this.formData.scopes || [], tags: this.formData.tags || {} }; if (!isEmpty(this.formData.jwksEndpoint)) { @@ -233,6 +250,11 @@ export class JwtSignerFormComponent extends ProjectableForm implements OnInit, O if (this.formData.id) { data.id = this.formData.id; } + if (this.signatureMethod === 'JWKS_ENDPOINT') { + data.certPem = undefined; + } else { + data.jwksEndpoint = undefined; + } this._apiData = data; return this._apiData; } @@ -254,6 +276,23 @@ export class JwtSignerFormComponent extends ProjectableForm implements OnInit, O this.formData.useExternalId = !this.formData.useExternalId; } + radioKeyDownHandler(event: any) { + switch (event.key) { + case 'ArrowLeft': + this.signatureMethod = 'JWKS_ENDPOINT'; + break; + case 'ArrowRight': + this.signatureMethod = 'CERT_PEM'; + break; + default: + break; + } + } + + selectSignatureMethod(method) { + this.signatureMethod = method; + } + openFileSelect(event: any) { this.filterInput.nativeElement.click(); this.fileSelectOpening = true; @@ -330,4 +369,15 @@ export class JwtSignerFormComponent extends ProjectableForm implements OnInit, O ); this.growlerService.show(growlerData); } + + scopesOnKeyup(event: any) { + const key = event.key?.toLowerCase(); + if (key === " " || key === 'enter') { + event.preventDefault(); + event.stopPropagation(); + const element = event.target as HTMLElement; + element.blur(); + element.focus(); + } + } } diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.service.ts b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.service.ts index 73d4d4ca..b0674720 100644 --- a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.service.ts +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.service.ts @@ -29,7 +29,7 @@ export class JwtSignerFormService { const data: any = this.getJwtSignerDataModel(formData, isUpdate); let prom; if (isUpdate) { - prom = this.dataService.patch('external-jwt-signers', data, formData.id, true); + prom = this.dataService.put('external-jwt-signers', data, formData.id, true); } else { prom = this.dataService.post('external-jwt-signers', data, true); } diff --git a/projects/ziti-console-lib/src/lib/models/jwt-signer.ts b/projects/ziti-console-lib/src/lib/models/jwt-signer.ts index 820f2e15..7af6a84c 100644 --- a/projects/ziti-console-lib/src/lib/models/jwt-signer.ts +++ b/projects/ziti-console-lib/src/lib/models/jwt-signer.ts @@ -2,12 +2,14 @@ export class JwtSigner { name: string = ''; audience: string = ''; issuer: string = ''; - certPem: string = ''; + clientId: string = ''; claimsProperty: string = ''; enabled: boolean = true; useExternalId: boolean = false; externalAuthUrl: string = ''; kid: string = ''; + scopes: string[] = []; jwksEndpoint: string = undefined; + certPem: string = undefined; tags: any = {}; }; \ No newline at end of file diff --git a/projects/ziti-console-lib/src/lib/services/node-data.service.ts b/projects/ziti-console-lib/src/lib/services/node-data.service.ts index 91113fd8..bc9e5fe4 100644 --- a/projects/ziti-console-lib/src/lib/services/node-data.service.ts +++ b/projects/ziti-console-lib/src/lib/services/node-data.service.ts @@ -64,6 +64,28 @@ export class NodeDataService extends ZitiDataService { ); } + put(type, model, id, chained = false) { + let clientSub; + const nodeServerURL = window.location.origin; + const serviceUrl = nodeServerURL + '/api/dataSave'; + const body = {paging: this.DEFAULT_PAGING, type: type, save: model, id: id, chained: chained}; + + return firstValueFrom(this.httpClient.post(serviceUrl,body,{}).pipe( + catchError((err: any) => { + const error = "Server Not Accessible"; + if (err.code !== "ECONNREFUSED") throw(err); + throw({error: error}); + }), + map((results: any) => { + if(!isEmpty(results.error)) { + throw({error: results.error}); + } + return results; + }) + ) + ); + } + patch(type, model, id, chained = false) { let clientSub; const nodeServerURL = window.location.origin; diff --git a/projects/ziti-console-lib/src/lib/services/ziti-controller-data.service.ts b/projects/ziti-console-lib/src/lib/services/ziti-controller-data.service.ts index ecdfd43a..2cbdd8b6 100644 --- a/projects/ziti-console-lib/src/lib/services/ziti-controller-data.service.ts +++ b/projects/ziti-console-lib/src/lib/services/ziti-controller-data.service.ts @@ -61,6 +61,26 @@ export class ZitiControllerDataService extends ZitiDataService { ); } + put(type, model, id, chained = false): Promise { + const apiVersions = this.settingsService.apiVersions || {}; + const prefix = apiVersions["edge-management"]?.v1?.path || '/edge/management/v1'; + const url = this.settingsService.settings.selectedEdgeController; + const serviceUrl = url + prefix + "/" + type + '/' + id; + this.httpClient.patch(serviceUrl, model, {}); + + return firstValueFrom(this.httpClient.put(serviceUrl, model, {}).pipe( + catchError((err: any) => { + const error = "Server Not Accessible"; + if (err.code !== "ECONNREFUSED") throw(err); + throw({error: error}); + }), + map((result: any) => { + return result; + }) + ) + ); + } + patch(type, model, id, chained = false): Promise { const apiVersions = this.settingsService.apiVersions || {}; const prefix = apiVersions["edge-management"]?.v1?.path || '/edge/management/v1'; diff --git a/projects/ziti-console-lib/src/lib/services/ziti-data.service.ts b/projects/ziti-console-lib/src/lib/services/ziti-data.service.ts index b0e832b1..e8060699 100644 --- a/projects/ziti-console-lib/src/lib/services/ziti-data.service.ts +++ b/projects/ziti-console-lib/src/lib/services/ziti-data.service.ts @@ -53,6 +53,7 @@ export abstract class ZitiDataService { ) {} abstract post(type, model, chained?): Promise; + abstract put(type, model, id, chained?): Promise; abstract patch(type, model, id, chained?): Promise; abstract get(type: string, paging: any, filters: FilterObj[], url?): Promise; abstract getSubdata(entityType: string, id: any, dataType: string, paging?: any): Promise; diff --git a/projects/ziti-console-lib/src/lib/shared-assets/styles/global.scss b/projects/ziti-console-lib/src/lib/shared-assets/styles/global.scss index 53e1c3cb..218ee86d 100644 --- a/projects/ziti-console-lib/src/lib/shared-assets/styles/global.scss +++ b/projects/ziti-console-lib/src/lib/shared-assets/styles/global.scss @@ -773,12 +773,16 @@ lib-form-field-container { justify-content: space-between; padding: 20px; width: 100%; - background-color: var(--stroke); + background-color: var(--formGroup); border-radius: 5px; &.toggle-container { padding-top: 10px; padding-bottom: 10px; + + .config-container-label { + color: var(--offWhite); + } } } @@ -1109,3 +1113,109 @@ p-dropdown { } } } + +.p-element { + + .p-chips.p-component { + width: 100%; + font-weight: 400; + font-family: 'Open Sans', Arial, sans-serif; + height: var(--defaultInputHeight); + border-color: var(--stroke); + border-style: solid; + border-width: var(--inputBorderWidth); + border-radius: var(--inputBorderRadius); + padding-left: 10px; + padding-right: 10px; + outline: none; + box-sizing: border-box; + font-size: 15px; + background-color: var(--background) !important; + color: var(--text); + -webkit-appearance: none; + + .p-inputtext.p-chips-multiple-container { + width: 100%; + padding: 0; + border-width: var(--inputBorderWidth); + + &.p-focus { + border-color: var(--primaryColor) !important; + box-shadow: 0 0 7px 0 var(--primaryColorOpaque) !important; + + &.error { + border-color: var(--red) !important; + } + } + } + } + + .p-chips .p-chips-multiple-container .p-chips-input-token input { + height: 25px; + font-size: 14px; + color: #495057; + padding: 0; + margin: 0; + border: 0 none; + outline: 0 none; + background-color: transparent; + box-shadow: none; + border-radius: 0; + width: 100% + } + + .p-chips .p-chips-multiple-container .p-chips-token { + margin-right: .5rem; + font-family: Open Sans, sans-serif; + font-weight: 600; + margin-top: 5px; + margin-bottom: 5px; + background: var(--primary); + color: var(--white); + border-radius: var(--inputBorderRadius); + cursor: default; + display: inline-flex; + align-items: center; + flex: 0 0 auto; + max-width: 100% + } + + .p-chips-token-icon { + margin-left: 0.5rem; + cursor: pointer; + color:blue; + fill: red; + } + + .p-chips { + display: inline-flex + } + + .p-chips-token-label { + min-width: 0; + overflow: auto + } + + .p-chips-token-label::-webkit-scrollbar { + display: none + } + + .p-fluid .p-chips { + display: flex + } + + .p-chips-clear-icon { + position: absolute; + top: 50%; + margin-top: -.5rem; + cursor: pointer; + } + + .p-chips-clearable .p-inputtext { + position: relative + } + + .p-inputtext { + border:none; + } +} diff --git a/projects/ziti-console-lib/src/lib/ziti-console-lib.module.ts b/projects/ziti-console-lib/src/lib/ziti-console-lib.module.ts index e73580af..d97c4589 100644 --- a/projects/ziti-console-lib/src/lib/ziti-console-lib.module.ts +++ b/projects/ziti-console-lib/src/lib/ziti-console-lib.module.ts @@ -44,6 +44,7 @@ import {PasswordInputComponent} from './features/dynamic-widgets/password/passwo import {ConfigurationsPageComponent} from './pages/configurations/configurations-page.component'; import {ListPageHeaderComponent} from './features/list-page-features/list-page-header/list-page-header.component'; import {MatDialogModule} from "@angular/material/dialog"; +import {MatRadioModule} from '@angular/material/radio'; import {TerminatorFormComponent} from "./features/projectable-forms/terminator/terminator-form.component"; import {ListPageFormComponent} from './features/list-page-features/list-page-form/list-page-form.component'; import {DataTableComponent} from "./features/data-table/data-table.component"; @@ -197,6 +198,7 @@ export function playerFactory() { CommonModule, FormsModule, MatDialogModule, + MatRadioModule, HttpClientModule, ZacRoutingModule, ChipsModule, From 6d7f7221b81319cc08991d69669e26b41e89fbd2 Mon Sep 17 00:00:00 2001 From: Ryan Galletto Date: Fri, 11 Oct 2024 16:14:43 -0400 Subject: [PATCH 3/3] Fixed spacing of additional field under "show more" --- .../jwt-signer/jwt-signer-form.component.html | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html index 1fd85abe..730d8c10 100644 --- a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html @@ -89,28 +89,26 @@ class="form-field-advanced" >
-
-
- Client ID -
-
- +
+ Client ID +
-
-
- External Auth Url -
-
- + +
+
+
+ External Auth Url +
+