@nauticana/sail 1.1.4 → 1.1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nauticana/sail",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "Metadata-driven Angular component library for CRUD admin frontends backed by the keel Go backend. Tables, forms, navigation, OTP/2FA/social auth, billing, payout onboarding.",
5
5
  "main": "src/index.ts",
6
6
  "scripts": {
@@ -9,6 +9,7 @@ import { SAIL_GUI_CONFIG, SailGuiConfig, DEFAULT_CONFIG } from '../../config';
9
9
  import {
10
10
  ConsentState, LoginResponseSocial, SignupConsent, SocialProvider,
11
11
  } from '../../model/auth';
12
+ import { firstValueFrom } from 'rxjs';
12
13
 
13
14
  declare const google: any;
14
15
  declare const AppleID: any;
@@ -66,9 +67,11 @@ export class SocialLoginComponent extends BaseAsync implements OnInit {
66
67
 
67
68
  private async initGoogle() {
68
69
  await loadScript(GSI_URL);
70
+ const nonce = await firstValueFrom(this.auth.getSocialNonce());
69
71
  google.accounts.id.initialize({
70
72
  client_id: this.guiConfig.googleClientId,
71
73
  callback: (res: { credential: string }) => this.onIdToken('google', res.credential),
74
+ ...(nonce ? { nonce } : {}),
72
75
  });
73
76
  // Render into the template anchor once the view is ready.
74
77
  queueMicrotask(() => {
@@ -80,11 +83,13 @@ export class SocialLoginComponent extends BaseAsync implements OnInit {
80
83
 
81
84
  private async initApple() {
82
85
  await loadScript(APPLE_URL);
86
+ const nonce = await firstValueFrom(this.auth.getSocialNonce());
83
87
  AppleID.auth.init({
84
88
  clientId: this.guiConfig.appleServiceId,
85
89
  scope: 'name email',
86
90
  redirectURI: this.guiConfig.appleRedirectUri ?? window.location.origin,
87
91
  usePopup: true,
92
+ ...(nonce ? { nonce } : {}),
88
93
  });
89
94
  }
90
95
 
@@ -11,7 +11,7 @@ import {
11
11
  UserProfile,
12
12
  } from '../model/auth';
13
13
  import { RestURL } from './rest_url';
14
- import { Observable, ReplaySubject } from 'rxjs';
14
+ import { Observable, ReplaySubject, catchError, of } from 'rxjs';
15
15
  import { ApplicationMenu, ConstantValue } from '../model/common';
16
16
  import { CanActivateFn, CanDeactivateFn, Router, Routes } from '@angular/router';
17
17
  import { SAIL_GUI_CONFIG, SailGuiConfig, DEFAULT_CONFIG } from '../config';
@@ -381,6 +381,16 @@ export abstract class BaseAuthService extends BaseRestService {
381
381
  );
382
382
  }
383
383
 
384
+ // Single-use nonce for the social id_token flow (replay protection): GET on
385
+ // the same social-login route. Empty when the backend hasn't enabled it —
386
+ // callers then sign in without one.
387
+ getSocialNonce(): Observable<string> {
388
+ return this.http.get<{ nonce: string }>(this.loginSocialUrl).pipe(
389
+ map((res) => res?.nonce ?? ''),
390
+ catchError(() => of('')),
391
+ );
392
+ }
393
+
384
394
  // ── Account lifecycle ──
385
395
 
386
396
  /**