@okta/spa-platform 0.6.0 → 0.9.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.
Files changed (58) hide show
  1. package/README.md +204 -0
  2. package/claude.md +562 -0
  3. package/dist/esm/Credential/Credential.js.map +1 -1
  4. package/dist/esm/Credential/CredentialCoordinator.js +25 -22
  5. package/dist/esm/Credential/CredentialCoordinator.js.map +1 -1
  6. package/dist/esm/Credential/TokenStorage.js +19 -3
  7. package/dist/esm/Credential/TokenStorage.js.map +1 -1
  8. package/dist/esm/FetchClient/index.js.map +1 -1
  9. package/dist/esm/core.js +25 -0
  10. package/dist/esm/core.js.map +1 -0
  11. package/dist/esm/flows/AuthorizationCodeFlow.js.map +1 -1
  12. package/dist/esm/flows/SessionLogoutFlow.js.map +1 -1
  13. package/dist/esm/flows/TransactionStorage.js.map +1 -1
  14. package/dist/esm/flows.js +30 -0
  15. package/dist/esm/flows.js.map +1 -0
  16. package/dist/esm/index.js +4 -13
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/orchestrators/AuthorizationCodeFlowOrchestrator.js +4 -0
  19. package/dist/esm/orchestrators/AuthorizationCodeFlowOrchestrator.js.map +1 -1
  20. package/dist/esm/orchestrators/HostOrchestrator/Host.js +9 -1
  21. package/dist/esm/orchestrators/HostOrchestrator/Host.js.map +1 -1
  22. package/dist/esm/orchestrators/HostOrchestrator/OrchestrationBridge.js.map +1 -1
  23. package/dist/esm/orchestrators/HostOrchestrator/SubApp.js +8 -2
  24. package/dist/esm/orchestrators/HostOrchestrator/SubApp.js.map +1 -1
  25. package/dist/esm/orchestrators/HostOrchestrator/index.js +11 -6
  26. package/dist/esm/orchestrators/HostOrchestrator/index.js.map +1 -1
  27. package/dist/esm/platform/OAuth2Client.js +4 -7
  28. package/dist/esm/platform/OAuth2Client.js.map +1 -1
  29. package/dist/esm/platform/defaults.js.map +1 -1
  30. package/dist/esm/platform/index.js.map +1 -1
  31. package/dist/esm/utils/IndexedDBStore.js +27 -18
  32. package/dist/esm/utils/IndexedDBStore.js.map +1 -1
  33. package/dist/esm/utils/SynchronizedResult.js +53 -60
  34. package/dist/esm/utils/SynchronizedResult.js.map +1 -1
  35. package/dist/esm/utils/isModernBrowser.js.map +1 -1
  36. package/dist/types/Credential/Credential.d.ts +8 -2
  37. package/dist/types/Credential/TokenStorage.d.ts +25 -1
  38. package/dist/types/FetchClient/index.d.ts +6 -0
  39. package/dist/types/core.d.ts +19 -0
  40. package/dist/types/flows/AuthorizationCodeFlow.d.ts +63 -13
  41. package/dist/types/flows/SessionLogoutFlow.d.ts +24 -0
  42. package/dist/types/flows/TransactionStorage.d.ts +7 -0
  43. package/dist/types/flows/index.d.ts +15 -2
  44. package/dist/types/flows.d.ts +9 -0
  45. package/dist/types/index.d.ts +1 -14
  46. package/dist/types/orchestrators/AuthorizationCodeFlowOrchestrator.d.ts +40 -6
  47. package/dist/types/orchestrators/HostOrchestrator/Host.d.ts +15 -0
  48. package/dist/types/orchestrators/HostOrchestrator/OrchestrationBridge.d.ts +4 -0
  49. package/dist/types/orchestrators/HostOrchestrator/SubApp.d.ts +13 -2
  50. package/dist/types/orchestrators/HostOrchestrator/index.d.ts +50 -16
  51. package/dist/types/orchestrators/index.d.ts +4 -1
  52. package/dist/types/platform/OAuth2Client.d.ts +9 -3
  53. package/dist/types/platform/defaults.d.ts +8 -0
  54. package/dist/types/platform/index.d.ts +6 -0
  55. package/dist/types/utils/IndexedDBStore.d.ts +1 -0
  56. package/dist/types/utils/SynchronizedResult.d.ts +1 -8
  57. package/dist/types/utils/isModernBrowser.d.ts +2 -1
  58. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,204 @@
1
+ ---
2
+ outline: [2, 3]
3
+ ---
4
+
5
+ # @okta/spa-platform
6
+
7
+ Platform library for browser environments for the Okta Client JavaScript ecosystem
8
+
9
+ ## Requirements
10
+
11
+ This library is written for modern JavaScript environments, targeting MDN's [Baseline 2022](https://developer.mozilla.org/en-US/docs/Glossary/Baseline/Compatibility) feature sets. Most notably utilizing the following APIs:
12
+
13
+ * [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
14
+ * [WebCrypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
15
+ * [Web Locks API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API)
16
+ * [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)
17
+ * [Broadcast Channel API](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API)
18
+
19
+ > [!NOTE]
20
+ > This library does not support Internet Explorer out-of-the-box. Polyfills will be required.
21
+
22
+ ## Installation
23
+
24
+ ```sh
25
+ yarn add @okta/auth-foundation @okta/spa-platform
26
+ # optionally include @okta/oauth2-flows
27
+ ```
28
+
29
+ ## Entry Points
30
+
31
+ (Recommended) Importing `@okta/spa-platform` has the following side effects:
32
+
33
+ - Registers the `@okta/spa-platform` Platform defaults
34
+ - Replaces `CredentialCoordinator.tokenStorage` with `BrowserTokenStorage`
35
+
36
+ All core exports are available via `@okta/spa-platform/core` to avoid the side effects, if required. Although, the `core` export is unlikely to result in desired functionality out-of-the-box.
37
+
38
+ To perform OAuth2 flows (like Authorization Code flow) a peer dependency of `@okta/oauth2-flows` is required. All features dependent on `@okta/oauth2-flows` are exported from `@okta/spa-platform/flows`, so `@okta/oauth2-flows` can be listed as a optional peer dependency
39
+
40
+ > All exports from `@okta/auth-foundation` and `@okta/oauth2-flows` are re-exported from `@okta/spa-platform`. Always import from `@okta/spa-platform` or a subpath
41
+
42
+ ## Usage
43
+
44
+ ### `isModernBrowser`
45
+
46
+ This library requires modern JavaScript APIs (see [requirements](#requirements)). This utility method returns `true` when the required APIs are available.
47
+
48
+ ## Platform
49
+
50
+ ### `BrowserTokenStorage`
51
+
52
+ Default implementation of `TokenStorage` backend by [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)
53
+
54
+ By default, all tokens will be encrypted (via `AES-GCM`) before being written to storage. `Token.Metadata` is stored separately an unencrypted.
55
+ This enables storage queries (via `Credential.find`) to search on claims without decrypting tokens
56
+
57
+ #### Configurations
58
+
59
+ | Property | Description | Default |
60
+ | ------ | ------ | ------ |
61
+ | `tokenPrefix` | A storage key prefix to identify entries by. | `'oauth-token'` |
62
+ | `encryptAtRest` | When `true`, tokens will be encrypted (via `AES-GCM`) before being written to storage. | `true` |
63
+ | `includeClaims` | When `true`, includes `idToken` claims in stored `Token.Metadata`. This includes `claims` within `Credential.find` queries | `true` |
64
+ | `encryptionKeyStore` | A [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)-backed store for managing storage encryption key(s) | `new IndexedDBStore<CryptoKey>('StorageKeys')` |
65
+ | `encryptionKeyName` | Key name of the storage encryption key with the `encryptionKeyStore` | `'EncryptionKey'` |
66
+
67
+ #### Customizing
68
+
69
+ > [!Tip]
70
+ > Updating storage configurations (or instances altogether) should happen at application bootstrap time. Making dynamic changes within an application's lifecycle may have unpredicatable results
71
+
72
+ Configuration properties can be updated directly
73
+
74
+ ```ts
75
+ import { Credential } from '@okta/spa-platform';
76
+
77
+ // Reference to default `BrowserTokenStorage` instance
78
+ Credential.coordinator.tokenStorage;
79
+
80
+ // Updates configuration property
81
+ Credential.coordinator.tokenStorage.includeClaims = false;
82
+ ```
83
+
84
+ Or the storage class can be extended
85
+
86
+ ```ts
87
+ import { Credential, BrowserTokenStorage } from '@okta/spa-platform';
88
+
89
+ class MyTokenStorage extends BrowserTokenStorage {
90
+ includeClaims = false;
91
+
92
+ protected async handleReadError (error: unknown, id: string) {
93
+ throw new TypeError('Something went wrong');
94
+ }
95
+ }
96
+
97
+ Credential.coordinator.tokenStorage = new MyTokenStorage();
98
+ ```
99
+
100
+ ## Authorization Code Flow
101
+
102
+ Browser-specific ultilies methods for performing [Authorization Code Flow](/docs/references/authorization_code_flow) in a browser environment.
103
+
104
+ ### `PerformRedirect` [:book:](/api/spa-platform/flows/AuthorizationCodeFlow/#performredirect)
105
+
106
+ > **Recommended Appoarch**
107
+
108
+ Performs a browser full-page redirect to the Authorization Server `/authorize` endpoint.
109
+ Once authentication is successful, the user will be redirected back to the provided `redirectUri`
110
+
111
+ > [!Tip]
112
+ > This requires the SPA handles the redirect at the provided `redirectUri` path via `.resume()`
113
+
114
+ ```ts
115
+ import { OAuth2Client, Credential } from '@okta/spa-platform';
116
+ import { AuthorizationCodeFlow } from '@okta/spa-platform/flows';
117
+
118
+ const client = new OAuth2Client({ ... });
119
+
120
+ const flow = new AuthorizationCodeFlow(client, {
121
+ redirectUri: REDIRECT_URI
122
+ });
123
+
124
+ export async function performSignIn () {
125
+ // NOTE: the resulting `Promise` from `PerformRedirect` never fulfills,
126
+ // so execution is blocking until the full-page direct occurs
127
+ return AuthorizationCodeFlow.PerformRedirect(flow);
128
+ }
129
+
130
+ // **MUST** be invoked at the `redirectUri` path to handle the redirect
131
+ // from the authorization server
132
+ export async function handleAuthorizationCodeFlowResponse () {
133
+ const { token } = await flow.resume(window.location.href);
134
+ await Credential.store(token);
135
+ }
136
+ ```
137
+
138
+ ### `PerformSilently` [:book:](/api/spa-platform/flows/AuthorizationCodeFlow/#performsilently)
139
+
140
+ Fulfills the `/authorize` request within a hidden iframe and therefore does *not* require a redirect. Does not prompt the user for credentials, however requires an existing IDP session; persumably the user was already prompted to establish this session. IDP sessions are (usually) cookie-based and therefore are susceptible to third-party cookie restrictions as well.
141
+
142
+ This approach is not recommended for most cases.
143
+
144
+ ```ts
145
+ import { OAuth2Client, Credential } from '@okta/spa-platform';
146
+ import { AuthorizationCodeFlow } from '@okta/spa-platform/flows';
147
+
148
+ const client = new OAuth2Client({ ... });
149
+
150
+ const flow = new AuthorizationCodeFlow(client, {
151
+ redirectUri: REDIRECT_URI
152
+ });
153
+
154
+ export async function performSignIn () {
155
+ const { token } = await AuthorizationCodeFlow.PerformSilently(flow);
156
+ await Credential.store(token);
157
+ }
158
+ ```
159
+
160
+ ### `PerformInPopup` [:book:](/api/spa-platform/flows/AuthorizationCodeFlow/#performinpopup)
161
+
162
+ > [!IMPORTANT]
163
+ > Read carefully before use. This method (and popup pattern at large) has quite a few "gotchas"
164
+
165
+ Fulfills `/authorize` requests in a popup window. Not necessarily recommended for primary authentication flows, but can be useful for step up authentication flows against known IDPs.
166
+
167
+ > [!NOTE]
168
+ > The phrase "external IDP" refers to an IDP other than the configured `issuer` for a given flow. See
169
+ > [Concepts: External Identity Providers](https://developer.okta.com/docs/concepts/identity-providers/) for a more detailed explanation
170
+
171
+ Utilizing external IDPs in a popup window will be susceptible to the IDP's [`Cross-Origin-Opener-Policy`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cross-Origin-Opener-Policy). Depending on their policy value, loading the IDP in a popup window may cause the popup window to create a new browsing context group ([BCG](https://developer.mozilla.org/en-US/docs/Glossary/Browsing_context)), seperate from the main browser window. The authentication flow will be unable to complete if this occurs. It's recommended to avoid using this method (and a popup in general) when utilizing external IDPs.
172
+
173
+ ```ts
174
+ import { OAuth2Client, Credential } from '@okta/spa-platform';
175
+ import { AuthorizationCodeFlow } from '@okta/spa-platform/flows';
176
+
177
+ const client = new OAuth2Client({ ... });
178
+
179
+ const flow = new AuthorizationCodeFlow(client, {
180
+ redirectUri: REDIRECT_URI
181
+ });
182
+
183
+ export async function performSignIn () {
184
+ const result = await AuthorizationCodeFlow.PerformInPopup(flow);
185
+
186
+ if (result.completed) {
187
+ await Credential.store(result.token);
188
+ }
189
+ else {
190
+ // handle unsuccessful auth
191
+ // `result.reason` - `'closed'` or `'blocked'`
192
+ }
193
+ }
194
+ ```
195
+
196
+ ## Session Logout Flow
197
+
198
+ Browser-specific ultilies methods for performing [OIDC RP-Initiated Logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) in a browser environment.
199
+
200
+ ### `PerformPostRedirect` [:book:](/api/spa-platform/flows/SessionLogoutFlow/#performpostredirect)
201
+
202
+ Performs a full-page redirect to IDP OIDC `end_session_endpoint` via generated hidden `<form method="POST">`.
203
+
204
+ Performing a `POST` request (instead of `GET` which supported by most IDPs) avoids leaking the `id_token` within the URL query params.