@dereekb/dbx-firebase 13.12.3 → 13.12.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import { input, computed, output, ChangeDetectionStrategy, Component, inject, In
3
3
  import * as i1 from '@dereekb/dbx-web';
4
4
  import { DbxBasicLoadingComponent, DbxErrorComponent, DbxButtonComponent, DbxAvatarComponent, DbxButtonSpacerDirective, DbxActionSnackbarErrorDirective, AbstractDbxSelectionListWrapperDirective, DbxListWrapperComponentImportsModule, DEFAULT_LIST_WRAPPER_COMPONENT_CONFIGURATION_TEMPLATE, AbstractDbxSelectionListViewDirective, DbxSelectionValueListViewComponentImportsModule, provideDbxListView, DEFAULT_DBX_SELECTION_VALUE_LIST_COMPONENT_CONFIGURATION_TEMPLATE, AbstractDbxValueListViewItemComponent, provideDbxListViewWrapper, DbxSpacerDirective, DbxActionConfirmDirective, DbxContentPitDirective, DbxDetailBlockComponent, DbxClickToCopyTextComponent } from '@dereekb/dbx-web';
5
5
  import { readableError, SPACE_STRING_SPLIT_JOIN, separateValues, generatePkceCodeVerifier, generatePkceCodeChallenge } from '@dereekb/util';
6
- import { DbxInjectionComponent, DbxActionDirective, DbxActionHandlerDirective, DbxActionValueDirective, DbxActionButtonDirective, DBX_INJECTION_COMPONENT_DATA, DbxRouterService, dbxRouteParamReaderInstance, completeOnDestroy, DbxActionEnforceModifiedDirective, DbxAppAuthRouterService } from '@dereekb/dbx-core';
6
+ import { DbxInjectionComponent, DbxActionDirective, DbxActionHandlerDirective, DbxActionValueDirective, DbxActionButtonDirective, DBX_INJECTION_COMPONENT_DATA, DbxRouterService, clean, dbxRouteParamReaderInstance, completeOnDestroy, DbxActionEnforceModifiedDirective, DbxAppAuthRouterService } from '@dereekb/dbx-core';
7
7
  import { of, map, first, switchMap, tap, BehaviorSubject } from 'rxjs';
8
8
  import * as i1$1 from '@dereekb/dbx-form';
9
9
  import { dbxForgeListSelectionField, AbstractConfigAsyncForgeFormDirective, DbxForgeFormComponentImportsModule, dbxForgeFormComponentProviders, DBX_FORGE_FORM_COMPONENT_TEMPLATE, DbxActionFormDirective, dbxForgeValueSelectionField, dbxForgeTextField, dbxForgeSearchableStringChipField, isWebsiteUrlValidator, dbxForgeContainer, dbxForgePickableChipField, pickableValueFieldValuesConfigForStaticLabeledValues, DbxFormSourceDirective, DbxFormValueChangeDirective } from '@dereekb/dbx-form';
@@ -11,7 +11,7 @@ import { successResult } from '@dereekb/rxjs';
11
11
  import { toSignal } from '@angular/core/rxjs-interop';
12
12
  import { DbxFirebaseAuthService, AbstractDbxFirebaseDocumentStore, firebaseDocumentStoreCreateFunction, firebaseDocumentStoreUpdateFunction, firebaseDocumentStoreDeleteFunction, AbstractDbxFirebaseCollectionStore, DbxFirebaseCollectionStoreDirective, provideDbxFirebaseCollectionStoreDirective, DbxFirebaseCollectionListDirective, DbxFirebaseCollectionChangeDirective, DbxFirebaseDocumentStoreDirective, provideDbxFirebaseDocumentStoreDirective } from '@dereekb/dbx-firebase';
13
13
  import { HttpClient } from '@angular/common/http';
14
- import { ALL_OIDC_TOKEN_ENDPOINT_AUTH_METHOD_OPTIONS, PRIVATE_KEY_JWT_TOKEN_ENDPOINT_AUTH_METHOD, OidcModelFunctions, OidcModelFirestoreCollections, OIDC_ENTRY_CLIENT_TYPE, oidcGrantEntriesByUidQuery } from '@dereekb/firebase';
14
+ import { ALL_OIDC_TOKEN_ENDPOINT_AUTH_METHOD_OPTIONS, PRIVATE_KEY_JWT_TOKEN_ENDPOINT_AUTH_METHOD, OidcModelFunctions, OidcModelFirestoreCollections, OIDC_ENTRY_CLIENT_TYPE, oidcGrantEntriesByUidQuery, PUBLIC_PKCE_TOKEN_ENDPOINT_AUTH_METHOD } from '@dereekb/firebase';
15
15
  import { DatePipe, CommonModule } from '@angular/common';
16
16
 
17
17
  /**
@@ -717,7 +717,7 @@ class DbxFirebaseOAuthLoginComponent {
717
717
  dbxRouterService = inject(DbxRouterService);
718
718
  dbxFirebaseAuthService = inject(DbxFirebaseAuthService);
719
719
  interactionService = inject(DbxFirebaseOidcInteractionService);
720
- uidParamReader = dbxRouteParamReaderInstance(this.dbxRouterService, DEFAULT_OIDC_INTERACTION_UID_PARAM_KEY);
720
+ uidParamReader = clean(dbxRouteParamReaderInstance(this.dbxRouterService, DEFAULT_OIDC_INTERACTION_UID_PARAM_KEY));
721
721
  interactionUid = toSignal(this.uidParamReader.value$);
722
722
  isLoggedIn = toSignal(this.dbxFirebaseAuthService.isLoggedIn$);
723
723
  submitting = signal(false, ...(ngDevMode ? [{ debugName: "submitting" }] : /* istanbul ignore next */ []));
@@ -753,9 +753,6 @@ class DbxFirebaseOAuthLoginComponent {
753
753
  }
754
754
  });
755
755
  }
756
- ngOnDestroy() {
757
- this.uidParamReader.destroy();
758
- }
759
756
  retry() {
760
757
  this.errorMessage.set(null);
761
758
  this._submitIdToken();
@@ -1844,10 +1841,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
1844
1841
  *
1845
1842
  * The client secret is only shown immediately after creation or after rotating.
1846
1843
  * When no secret is available, a "Rotate Secret" button is shown.
1844
+ *
1845
+ * Public PKCE clients (`token_endpoint_auth_method === 'none'`) have no secret: the secret
1846
+ * block, the one-time "copy it now" messaging, and the rotate button are all hidden in favor
1847
+ * of a note explaining the client authenticates with PKCE alone.
1847
1848
  */
1848
1849
  class DbxFirebaseOidcEntryClientViewComponent {
1849
1850
  oidcEntryDocumentStore = inject(OidcEntryDocumentStore);
1850
1851
  clientIdSignal = toSignal(this.oidcEntryDocumentStore.data$.pipe(map((data) => data.payload?.client_id)));
1852
+ tokenEndpointAuthMethodSignal = toSignal(this.oidcEntryDocumentStore.data$.pipe(map((data) => data.payload?.token_endpoint_auth_method)));
1853
+ isPublicClientSignal = computed(() => this.tokenEndpointAuthMethodSignal() === PUBLIC_PKCE_TOKEN_ENDPOINT_AUTH_METHOD, ...(ngDevMode ? [{ debugName: "isPublicClientSignal" }] : /* istanbul ignore next */ []));
1851
1854
  latestClientSecretSignal = toSignal(this.oidcEntryDocumentStore.latestClientSecret$);
1852
1855
  rotateSecretConfirmConfig = {
1853
1856
  title: 'Rotate Client Secret',
@@ -1863,17 +1866,23 @@ class DbxFirebaseOidcEntryClientViewComponent {
1863
1866
  <dbx-detail-block class="dbx-pb4" icon="key" header="Client ID">
1864
1867
  <dbx-click-to-copy-text [copyText]="clientIdSignal()">{{ clientIdSignal() }}</dbx-click-to-copy-text>
1865
1868
  </dbx-detail-block>
1866
- <dbx-detail-block icon="lock" header="Client Secret">
1867
- @if (latestClientSecretSignal()) {
1868
- <dbx-click-to-copy-text class="dbx-block dbx-pb2" [copyText]="latestClientSecretSignal()">{{ latestClientSecretSignal() }}</dbx-click-to-copy-text>
1869
- <dbx-click-to-copy-text [copyText]="latestClientSecretSignal()" [showIcon]="false"><div class="dbx-hint dbx-u">This secret is only shown once. Copy it now.</div></dbx-click-to-copy-text>
1870
- } @else {
1871
- <div>
1872
- <div class="dbx-hint dbx-pb3">The client secret was shown once when created. You can invalidate the old one and get a new one.</div>
1873
- <dbx-button dbxAction [dbxActionHandler]="handleRotateClientSecret" [dbxActionConfirm]="rotateSecretConfirmConfig" dbxActionButton text="Rotate Secret" icon="refresh" color="warn" [raised]="true"></dbx-button>
1874
- </div>
1875
- }
1876
- </dbx-detail-block>
1869
+ @if (isPublicClientSignal()) {
1870
+ <dbx-detail-block icon="lock_open" header="Client Secret">
1871
+ <div class="dbx-hint">This is a public client (PKCE) with no client secret. It authenticates the authorization code flow using PKCE alone.</div>
1872
+ </dbx-detail-block>
1873
+ } @else {
1874
+ <dbx-detail-block icon="lock" header="Client Secret">
1875
+ @if (latestClientSecretSignal()) {
1876
+ <dbx-click-to-copy-text class="dbx-block dbx-pb2" [copyText]="latestClientSecretSignal()">{{ latestClientSecretSignal() }}</dbx-click-to-copy-text>
1877
+ <dbx-click-to-copy-text [copyText]="latestClientSecretSignal()" [showIcon]="false"><div class="dbx-hint dbx-u">This secret is only shown once. Copy it now.</div></dbx-click-to-copy-text>
1878
+ } @else {
1879
+ <div>
1880
+ <div class="dbx-hint dbx-pb3">The client secret was shown once when created. You can invalidate the old one and get a new one.</div>
1881
+ <dbx-button dbxAction [dbxActionHandler]="handleRotateClientSecret" [dbxActionConfirm]="rotateSecretConfirmConfig" dbxActionButton text="Rotate Secret" icon="refresh" color="warn" [raised]="true"></dbx-button>
1882
+ </div>
1883
+ }
1884
+ </dbx-detail-block>
1885
+ }
1877
1886
  </dbx-content-pit>
1878
1887
  `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: DbxContentPitDirective, selector: "dbx-content-pit, [dbxContentPit]", inputs: ["scrollable", "rounded"] }, { kind: "component", type: DbxDetailBlockComponent, selector: "dbx-detail-block", inputs: ["icon", "header", "alignHeader", "bigHeader"] }, { kind: "component", type: DbxClickToCopyTextComponent, selector: "dbx-click-to-copy-text", inputs: ["copyText", "showIcon", "highlighted", "clipboardSnackbarMessagesConfig", "clipboardSnackbarMessagesEnabled", "clickToCopyIcon", "clickIconToCopyOnly"] }, { kind: "component", type: DbxButtonComponent, selector: "dbx-button", inputs: ["bar", "type", "buttonStyle", "color", "spinnerColor", "customButtonColor", "customTextColor", "customSpinnerColor", "basic", "tonal", "raised", "stroked", "flat", "iconOnly", "fab", "customContent", "allowClickPropagation", "mode"] }, { kind: "directive", type: DbxActionDirective, selector: "dbx-action,[dbxAction]", exportAs: ["action", "dbxAction"] }, { kind: "directive", type: DbxActionHandlerDirective, selector: "[dbxActionHandler]", inputs: ["dbxActionHandler"] }, { kind: "directive", type: DbxActionButtonDirective, selector: "[dbxActionButton]", inputs: ["dbxActionButtonEcho"] }, { kind: "directive", type: DbxActionConfirmDirective, selector: "[dbxActionConfirm]", inputs: ["dbxActionConfirm", "dbxActionConfirmSkip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1879
1888
  }
@@ -1886,17 +1895,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
1886
1895
  <dbx-detail-block class="dbx-pb4" icon="key" header="Client ID">
1887
1896
  <dbx-click-to-copy-text [copyText]="clientIdSignal()">{{ clientIdSignal() }}</dbx-click-to-copy-text>
1888
1897
  </dbx-detail-block>
1889
- <dbx-detail-block icon="lock" header="Client Secret">
1890
- @if (latestClientSecretSignal()) {
1891
- <dbx-click-to-copy-text class="dbx-block dbx-pb2" [copyText]="latestClientSecretSignal()">{{ latestClientSecretSignal() }}</dbx-click-to-copy-text>
1892
- <dbx-click-to-copy-text [copyText]="latestClientSecretSignal()" [showIcon]="false"><div class="dbx-hint dbx-u">This secret is only shown once. Copy it now.</div></dbx-click-to-copy-text>
1893
- } @else {
1894
- <div>
1895
- <div class="dbx-hint dbx-pb3">The client secret was shown once when created. You can invalidate the old one and get a new one.</div>
1896
- <dbx-button dbxAction [dbxActionHandler]="handleRotateClientSecret" [dbxActionConfirm]="rotateSecretConfirmConfig" dbxActionButton text="Rotate Secret" icon="refresh" color="warn" [raised]="true"></dbx-button>
1897
- </div>
1898
- }
1899
- </dbx-detail-block>
1898
+ @if (isPublicClientSignal()) {
1899
+ <dbx-detail-block icon="lock_open" header="Client Secret">
1900
+ <div class="dbx-hint">This is a public client (PKCE) with no client secret. It authenticates the authorization code flow using PKCE alone.</div>
1901
+ </dbx-detail-block>
1902
+ } @else {
1903
+ <dbx-detail-block icon="lock" header="Client Secret">
1904
+ @if (latestClientSecretSignal()) {
1905
+ <dbx-click-to-copy-text class="dbx-block dbx-pb2" [copyText]="latestClientSecretSignal()">{{ latestClientSecretSignal() }}</dbx-click-to-copy-text>
1906
+ <dbx-click-to-copy-text [copyText]="latestClientSecretSignal()" [showIcon]="false"><div class="dbx-hint dbx-u">This secret is only shown once. Copy it now.</div></dbx-click-to-copy-text>
1907
+ } @else {
1908
+ <div>
1909
+ <div class="dbx-hint dbx-pb3">The client secret was shown once when created. You can invalidate the old one and get a new one.</div>
1910
+ <dbx-button dbxAction [dbxActionHandler]="handleRotateClientSecret" [dbxActionConfirm]="rotateSecretConfirmConfig" dbxActionButton text="Rotate Secret" icon="refresh" color="warn" [raised]="true"></dbx-button>
1911
+ </div>
1912
+ }
1913
+ </dbx-detail-block>
1914
+ }
1900
1915
  </dbx-content-pit>
1901
1916
  `,
1902
1917
  standalone: true,