@moonbase.sh/storefront 3.9.0 → 3.10.0

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/README.md CHANGED
@@ -500,6 +500,45 @@ Available events include:
500
500
  - `checkout-closed`
501
501
  - `checkout-completed`
502
502
 
503
+ `signed-in` and `signed-up` fire on the page where the customer signs in, including through a link in an email. `signed-out` also fires when the session ends without anyone signing out on the page: in another tab, or elsewhere (for example a password change on another device), which the widget finds out when it next renews the token.
504
+
505
+ ## Calling your own API
506
+
507
+ `Moonbase.getAccessToken()` resolves to the signed-in customer's access token, or `null` when nobody is signed in. Send it to your own API to act on the customer's behalf. It's renewed first when it's about to run out, so call it for each request rather than keeping a copy.
508
+
509
+ ```ts
510
+ const token = await Moonbase.getAccessToken()
511
+ const response = await fetch('https://api.example.com/presets', {
512
+ headers: token ? { Authorization: `Bearer ${token}` } : {},
513
+ })
514
+ ```
515
+
516
+ The token is a JWT signed with your account's key. Verify it on your server against the JWK Set at `https://<account-id>.moonbase.sh/api/key/jwks`, and check all of:
517
+
518
+ - the `typ` header is `at+jwt` and the algorithm is `RS256`
519
+ - the issuer (`iss`) is your Account ID
520
+ - the audience (`aud`) is `https://moonbase.sh`
521
+ - the expiry (`exp`) is present and hasn't passed
522
+
523
+ License tokens are signed with the same key and issuer, so a check that skips the audience or the expiry accepts a license file as a sign-in. The customer's ID is the `sub` claim. With [jose](https://github.com/panva/jose):
524
+
525
+ ```ts
526
+ import { createRemoteJWKSet, jwtVerify } from 'jose'
527
+
528
+ const jwks = createRemoteJWKSet(new URL('https://acme.moonbase.sh/api/key/jwks'))
529
+
530
+ const { payload } = await jwtVerify(token, jwks, {
531
+ typ: 'at+jwt',
532
+ algorithms: ['RS256'],
533
+ issuer: 'acme',
534
+ audience: 'https://moonbase.sh',
535
+ requiredClaims: ['exp'],
536
+ })
537
+ // payload.sub is the customer's ID
538
+ ```
539
+
540
+ Don't read the widget's `localStorage` entry yourself: it holds the refresh token as well, which must never leave the browser.
541
+
503
542
  ## Integrations
504
543
 
505
544
  The widget can forward its commerce and auth events to common marketing/analytics SDKs without any extra glue code. Enable a provider by passing its config in `integrations`:
@@ -202,6 +202,7 @@ declare class MoonbaseImpl implements MoonbaseInstance {
202
202
  setup(url: string, options?: DeepPartial<MoonbaseOptions>): Promise<void>;
203
203
  configure(options: DeepPartial<MoonbaseOptions>): void;
204
204
  on<TEvent extends MoonbaseEvent>(eventType: TEvent, callback: (event: MoonbaseEventArgs[TEvent]) => void): void;
205
+ getAccessToken(): Promise<string | null>;
205
206
  private handleLocationIntent;
206
207
  sign_in(parameters?: MoonbaseIntentArgs['sign_in']): void;
207
208
  sign_up(parameters?: MoonbaseIntentArgs['sign_up']): void;
@@ -236,6 +237,13 @@ export declare type MoonbaseInstance = MoonbaseInstanceIntents & {
236
237
  setup: (url: string, options: DeepPartial<MoonbaseOptions>) => Promise<void>;
237
238
  configure: (options: DeepPartial<MoonbaseOptions>) => void;
238
239
  on: <TEvent extends MoonbaseEvent>(eventType: TEvent, callback: (event: MoonbaseEventArgs[TEvent]) => void) => void;
240
+ /**
241
+ * The signed-in customer's access token, for calling your own API on their behalf, or
242
+ * null when nobody is signed in. Renewed first when it is about to run out, so it is
243
+ * always good for at least the next half minute. Verify it on your server with your
244
+ * account's public key, at `/api/key/jwks` on your Moonbase address.
245
+ */
246
+ getAccessToken: () => Promise<string | null>;
239
247
  };
240
248
 
241
249
  declare type MoonbaseInstanceIntents = {