@luminaryworks/auth-react 0.3.1 → 0.4.1
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 +97 -64
- package/dist/index.d.ts +72 -30
- package/dist/index.js +266 -172
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,64 +1,97 @@
|
|
|
1
|
-
# `@luminaryworks/auth-react`
|
|
2
|
-
|
|
3
|
-
LuminaryWorks unified OIDC SPA client + **AuthGate** (401 pause / single-flight reauth).
|
|
4
|
-
|
|
5
|
-
## AuthGate
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
import { authGate, withAuthGateRetry, AuthGateProvider, ReauthOverlay } from "@luminaryworks/auth-react";
|
|
9
|
-
|
|
10
|
-
authGate.configure({
|
|
11
|
-
tryRefresh: async () => {
|
|
12
|
-
/* refresh product JWT; return true if ok */
|
|
13
|
-
return false;
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
// In API client:
|
|
18
|
-
await withAuthGateRetry(() => fetch(...), {
|
|
19
|
-
isUnauthorized: (e) => e.status === 401,
|
|
20
|
-
});
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
On first 401: try refresh → else open reauth UI (overlay + OIDC **popup**, not IdP iframe) → retry queued callers.
|
|
24
|
-
|
|
25
|
-
## Headless login panel
|
|
26
|
-
|
|
27
|
-
Branded panel with **social buttons** (auto-loaded from IdP `
|
|
28
|
-
|
|
29
|
-
Styles ship as **CSS Modules (SCSS)**. The built bundle auto-injects panel CSS in the browser. Optional explicit import (SSR / style control):
|
|
30
|
-
|
|
31
|
-
```ts
|
|
32
|
-
import "@luminaryworks/auth-react/style.css";
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Override layout via `className` / `style` on the root.
|
|
36
|
-
|
|
37
|
-
```tsx
|
|
38
|
-
// End-user product login (social on by default)
|
|
39
|
-
<HeadlessLoginPanel
|
|
40
|
-
config={idpConfig}
|
|
41
|
-
productName="DataLuminary"
|
|
42
|
-
mode="redirect"
|
|
43
|
-
// socialProviders: "auto" | ["google","github"] | []
|
|
44
|
-
/>
|
|
45
|
-
|
|
46
|
-
// Admin / internal console — hide Experience social connectors
|
|
47
|
-
<HeadlessLoginPanel
|
|
48
|
-
config={idpConfig}
|
|
49
|
-
productName="DataLuminary Admin"
|
|
50
|
-
mode="redirect"
|
|
51
|
-
showSocialConnectors={false}
|
|
52
|
-
/>
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
| Prop | Default | Notes |
|
|
56
|
-
|------|---------|--------|
|
|
57
|
-
| `showSocialConnectors` | `true` | `false` skips fetch and hides divider + social buttons |
|
|
58
|
-
| `socialProviders` | `"auto"` | allowlist, or `[]` (same effect as `showSocialConnectors={false}`) |
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
1
|
+
# `@luminaryworks/auth-react`
|
|
2
|
+
|
|
3
|
+
LuminaryWorks unified OIDC SPA client + **AuthGate** (401 pause / single-flight reauth).
|
|
4
|
+
|
|
5
|
+
## AuthGate
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { authGate, withAuthGateRetry, AuthGateProvider, ReauthOverlay } from "@luminaryworks/auth-react";
|
|
9
|
+
|
|
10
|
+
authGate.configure({
|
|
11
|
+
tryRefresh: async () => {
|
|
12
|
+
/* refresh product JWT; return true if ok */
|
|
13
|
+
return false;
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// In API client:
|
|
18
|
+
await withAuthGateRetry(() => fetch(...), {
|
|
19
|
+
isUnauthorized: (e) => e.status === 401,
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
On first 401: try refresh → else open reauth UI (overlay + OIDC **popup**, not IdP iframe) → retry queued callers.
|
|
24
|
+
|
|
25
|
+
## Headless login panel
|
|
26
|
+
|
|
27
|
+
Branded panel with **social buttons** (auto-loaded from IdP Experience `socialConnectors` — google / github / x / …) plus **unified account** password. The default `LogtoExperienceAdapter` keeps Logto's `direct_sign_in=social:<target>` parameter inside provider-specific code. Buttons are hidden when the IdP has no social connectors (do not invent Google/GitHub — that dumped users on Logto `/sign-in`).
|
|
28
|
+
|
|
29
|
+
Styles ship as **CSS Modules (SCSS)**. The built bundle auto-injects panel CSS in the browser. Optional explicit import (SSR / style control):
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import "@luminaryworks/auth-react/style.css";
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Override layout via `className` / `style` on the root.
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
// End-user product login (social on by default)
|
|
39
|
+
<HeadlessLoginPanel
|
|
40
|
+
config={idpConfig}
|
|
41
|
+
productName="DataLuminary"
|
|
42
|
+
mode="redirect"
|
|
43
|
+
// socialProviders: "auto" | ["google","github"] | []
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
// Admin / internal console — hide Experience social connectors
|
|
47
|
+
<HeadlessLoginPanel
|
|
48
|
+
config={idpConfig}
|
|
49
|
+
productName="DataLuminary Admin"
|
|
50
|
+
mode="redirect"
|
|
51
|
+
showSocialConnectors={false}
|
|
52
|
+
/>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
| Prop | Default | Notes |
|
|
56
|
+
|------|---------|--------|
|
|
57
|
+
| `showSocialConnectors` | `true` | `false` skips fetch and hides divider + social buttons |
|
|
58
|
+
| `socialProviders` | `"auto"` | allowlist, or `[]` (same effect as `showSocialConnectors={false}`) |
|
|
59
|
+
| `experienceAdapter` | `LogtoExperienceAdapter` | optional custom `LoginExperienceAdapter` |
|
|
60
|
+
|
|
61
|
+
IdP hosted `/sign-in` social row layout: `node scripts/apply-branding.mjs` (customCss wrap). Enable connectors: `ensure-sign-in-experience.mjs` + `verify-social-direct-signin.mjs`.
|
|
62
|
+
|
|
63
|
+
### Login experience adapters
|
|
64
|
+
|
|
65
|
+
`HeadlessLoginPanel` delegates non-standard password and social-connector flows
|
|
66
|
+
to `LoginExperienceAdapter`; standard OIDC authorization code + PKCE remains in
|
|
67
|
+
the OIDC client. Adapter methods are optional and are used only when both the
|
|
68
|
+
matching capability and method are present. Without password support, the panel
|
|
69
|
+
renders `labels.submitSso` and starts a standard hosted OIDC flow. Logto is the
|
|
70
|
+
only built-in provider:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import {
|
|
74
|
+
createLoginExperienceAdapter,
|
|
75
|
+
LogtoExperienceAdapter,
|
|
76
|
+
resolveLoginExperienceAdapter,
|
|
77
|
+
type LoginExperienceAdapter,
|
|
78
|
+
type LoginExperienceCapability,
|
|
79
|
+
} from "@luminaryworks/auth-react";
|
|
80
|
+
|
|
81
|
+
const logto = new LogtoExperienceAdapter();
|
|
82
|
+
const sameDefault = createLoginExperienceAdapter("logto");
|
|
83
|
+
const resolved = resolveLoginExperienceAdapter(logto);
|
|
84
|
+
|
|
85
|
+
// Hosted-only enterprise IdP: no Experience API methods are required.
|
|
86
|
+
const hostedOnly = {
|
|
87
|
+
provider: "enterprise",
|
|
88
|
+
capabilities: [],
|
|
89
|
+
} satisfies LoginExperienceAdapter;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Existing `experiencePasswordSignIn` and `fetchSocialConnectors` imports remain
|
|
93
|
+
available as compatibility functions backed by the default Logto adapter.
|
|
94
|
+
|
|
95
|
+
## Popup callback
|
|
96
|
+
|
|
97
|
+
Callback route must detect popup windows and call `handleSignInPopupCallback` (do not SSO-exchange inside the popup).
|
package/dist/index.d.ts
CHANGED
|
@@ -45,9 +45,12 @@ declare function createUserManager(config: LuminaryIdpConfig): UserManager;
|
|
|
45
45
|
declare function resetUserManager(): void;
|
|
46
46
|
interface SignInOptions {
|
|
47
47
|
returnUrl?: string;
|
|
48
|
+
/** Provider-specific authorize parameters supplied by an experience adapter. */
|
|
49
|
+
extraQueryParams?: Record<string, string>;
|
|
48
50
|
/**
|
|
49
51
|
* Logto direct sign-in, e.g. `social:google` / `social:github` / `sso:<connectorId>`.
|
|
50
52
|
* Skips the hosted password page and opens the provider immediately.
|
|
53
|
+
* @deprecated Prefer a LoginExperienceAdapter, which supplies extraQueryParams.
|
|
51
54
|
*/
|
|
52
55
|
directSignIn?: string;
|
|
53
56
|
}
|
|
@@ -83,10 +86,17 @@ declare function clearStoredSession(config: LuminaryIdpConfig): void;
|
|
|
83
86
|
declare function getCurrentUser(config: LuminaryIdpConfig): Promise<LuminaryAuthSession | null>;
|
|
84
87
|
|
|
85
88
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
+
* Capabilities exposed by a headless login-experience provider.
|
|
90
|
+
*
|
|
91
|
+
* Consumers can use these flags to avoid assuming that every provider supports
|
|
92
|
+
* Logto's password, connector-discovery, or direct social-login flows.
|
|
89
93
|
*/
|
|
94
|
+
declare const LOGIN_EXPERIENCE_CAPABILITIES: {
|
|
95
|
+
readonly passwordSignIn: "password-sign-in";
|
|
96
|
+
readonly socialConnectors: "social-connectors";
|
|
97
|
+
readonly socialDirectSignIn: "social-direct-sign-in";
|
|
98
|
+
};
|
|
99
|
+
type LoginExperienceCapability = (typeof LOGIN_EXPERIENCE_CAPABILITIES)[keyof typeof LOGIN_EXPERIENCE_CAPABILITIES];
|
|
90
100
|
type ExperienceIdentifierType = "email" | "username" | "phone";
|
|
91
101
|
interface ExperiencePasswordSignInInput {
|
|
92
102
|
/** Experience API origin (no trailing slash). Prefer SPA origin when proxied. */
|
|
@@ -108,39 +118,69 @@ interface ExperiencePasswordSignInResult {
|
|
|
108
118
|
redirectTo?: string;
|
|
109
119
|
raw?: unknown;
|
|
110
120
|
}
|
|
111
|
-
/**
|
|
112
|
-
* Force authorize onto the Experience/SPA origin so Set-Cookie lands on the same
|
|
113
|
-
* host as subsequent `/api/experience` calls (dev proxy strips Domain).
|
|
114
|
-
*/
|
|
115
|
-
declare function sameOriginAuthorizeUrl(authorizeUrl: string, apiBase: string): string;
|
|
116
|
-
/**
|
|
117
|
-
* Headless password sign-in via Logto Experience API.
|
|
118
|
-
* Requires an OIDC interaction cookie (see {@link bootstrapOidcInteraction}) and
|
|
119
|
-
* same-site Experience calls (SPA proxy or Auth Gateway on the SPA origin).
|
|
120
|
-
*
|
|
121
|
-
* On success, follow {@link ExperiencePasswordSignInResult.redirectTo} in the same
|
|
122
|
-
* window — that URL completes the PKCE round-trip started by createSigninRequest.
|
|
123
|
-
* Do not start a second authorize (that shows Logto `/sign-in` again).
|
|
124
|
-
*
|
|
125
|
-
* Tries the guessed identifier type first, then the alternate email/username so
|
|
126
|
-
* users can sign in with either when both methods are enabled on the IdP.
|
|
127
|
-
*/
|
|
128
|
-
declare function experiencePasswordSignIn(input: ExperiencePasswordSignInInput): Promise<ExperiencePasswordSignInResult>;
|
|
129
121
|
interface ExperienceSocialConnector {
|
|
130
122
|
id: string;
|
|
131
123
|
target: string;
|
|
132
124
|
name: string;
|
|
133
125
|
logo?: string;
|
|
134
126
|
}
|
|
135
|
-
|
|
136
|
-
* Public Logto sign-in experience (no auth). Returns enabled social connectors
|
|
137
|
-
* in SIE order — use for Headless social buttons (google / github / x / …).
|
|
138
|
-
*/
|
|
139
|
-
declare function fetchSocialConnectors(input: {
|
|
127
|
+
interface FetchSocialConnectorsInput {
|
|
140
128
|
/** Same origin as Experience / IdP (e.g. SPA proxy or http://localhost:3001). */
|
|
141
129
|
apiBase: string;
|
|
142
130
|
appId?: string;
|
|
143
|
-
}
|
|
131
|
+
}
|
|
132
|
+
interface SocialSignInRequest {
|
|
133
|
+
/** Provider-specific authorize parameters, passed through by the OIDC client. */
|
|
134
|
+
extraQueryParams?: Record<string, string>;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Provider boundary for non-standard login-experience APIs.
|
|
138
|
+
*
|
|
139
|
+
* Standard OIDC redirect/popup and PKCE handling intentionally remain in the
|
|
140
|
+
* OIDC client. Only provider-specific Experience operations belong here.
|
|
141
|
+
*/
|
|
142
|
+
interface LoginExperienceAdapter {
|
|
143
|
+
readonly provider: string;
|
|
144
|
+
readonly capabilities: readonly LoginExperienceCapability[];
|
|
145
|
+
experiencePasswordSignIn?(input: ExperiencePasswordSignInInput): Promise<ExperiencePasswordSignInResult>;
|
|
146
|
+
fetchSocialConnectors?(input: FetchSocialConnectorsInput): Promise<ExperienceSocialConnector[]>;
|
|
147
|
+
createSocialSignInRequest?(target: string): SocialSignInRequest;
|
|
148
|
+
}
|
|
149
|
+
type LoginExperienceProvider = "logto";
|
|
150
|
+
/**
|
|
151
|
+
* Factory for built-in providers. Logto is intentionally the only built-in
|
|
152
|
+
* adapter; products can supply their own adapter without shipping fake stubs.
|
|
153
|
+
*/
|
|
154
|
+
declare function createLoginExperienceAdapter(provider?: LoginExperienceProvider): LoginExperienceAdapter;
|
|
155
|
+
/** Resolve an explicit product adapter, or the backward-compatible Logto default. */
|
|
156
|
+
declare function resolveLoginExperienceAdapter(adapter?: LoginExperienceAdapter | null): LoginExperienceAdapter;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Logto Experience API (Headless) adapter.
|
|
160
|
+
* Prefer same-origin Experience base (SPA proxies /api/experience) so cookies
|
|
161
|
+
* work on HTTP localhost.
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Force authorize onto the Experience/SPA origin so Set-Cookie lands on the
|
|
166
|
+
* same host as subsequent `/api/experience` calls (dev proxy strips Domain).
|
|
167
|
+
*/
|
|
168
|
+
declare function sameOriginAuthorizeUrl(authorizeUrl: string, apiBase: string): string;
|
|
169
|
+
/** Build Logto's provider-specific direct sign-in authorize parameter. */
|
|
170
|
+
declare function createLogtoDirectSignInRequest(directSignIn: string): SocialSignInRequest;
|
|
171
|
+
/** Built-in adapter for Logto's non-standard Experience API. */
|
|
172
|
+
declare class LogtoExperienceAdapter implements LoginExperienceAdapter {
|
|
173
|
+
readonly provider = "logto";
|
|
174
|
+
readonly capabilities: readonly LoginExperienceCapability[];
|
|
175
|
+
experiencePasswordSignIn(input: ExperiencePasswordSignInInput): Promise<ExperiencePasswordSignInResult>;
|
|
176
|
+
fetchSocialConnectors(input: FetchSocialConnectorsInput): Promise<ExperienceSocialConnector[]>;
|
|
177
|
+
createSocialSignInRequest(target: string): SocialSignInRequest;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** @deprecated Use a LoginExperienceAdapter instance. */
|
|
181
|
+
declare function experiencePasswordSignIn(input: ExperiencePasswordSignInInput): Promise<ExperiencePasswordSignInResult>;
|
|
182
|
+
/** @deprecated Use a LoginExperienceAdapter instance. */
|
|
183
|
+
declare function fetchSocialConnectors(input: FetchSocialConnectorsInput): Promise<ExperienceSocialConnector[]>;
|
|
144
184
|
|
|
145
185
|
/**
|
|
146
186
|
* AuthGate — single-flight 401 recovery with optional token refresh + reauth UI.
|
|
@@ -235,7 +275,7 @@ interface HeadlessLoginLabels {
|
|
|
235
275
|
identifierPlaceholder?: string;
|
|
236
276
|
passwordPlaceholder?: string;
|
|
237
277
|
submitPassword?: string;
|
|
238
|
-
/**
|
|
278
|
+
/** Hosted OIDC button shown when the adapter has no password capability. */
|
|
239
279
|
submitSso?: string;
|
|
240
280
|
submitGoogle?: string;
|
|
241
281
|
submitGithub?: string;
|
|
@@ -248,6 +288,8 @@ interface HeadlessLoginLabels {
|
|
|
248
288
|
}
|
|
249
289
|
interface HeadlessLoginPanelProps {
|
|
250
290
|
config: Partial<LuminaryIdpConfig>;
|
|
291
|
+
/** Login-experience provider. Defaults to the built-in Logto adapter. */
|
|
292
|
+
experienceAdapter?: LoginExperienceAdapter;
|
|
251
293
|
/** Product display name shown as brand signal */
|
|
252
294
|
productName: string;
|
|
253
295
|
logoSrc?: string;
|
|
@@ -290,7 +332,7 @@ interface HeadlessLoginPanelProps {
|
|
|
290
332
|
}
|
|
291
333
|
/** Shared default accent for product login panels. */
|
|
292
334
|
declare const DEFAULT_LOGIN_THEME_COLOR = "#3a84ff";
|
|
293
|
-
declare function HeadlessLoginPanel({ config, productName, logoSrc, labels: labelsProp, returnUrl, mode, showSocialConnectors, socialProviders, showCancel, onCancel, onOidcSession, onExperienceRedirect, footer, className, style, themeColor, }: HeadlessLoginPanelProps): react.JSX.Element;
|
|
335
|
+
declare function HeadlessLoginPanel({ config, experienceAdapter: experienceAdapterProp, productName, logoSrc, labels: labelsProp, returnUrl, mode, showSocialConnectors, socialProviders, showCancel, onCancel, onOidcSession, onExperienceRedirect, footer, className, style, themeColor, }: HeadlessLoginPanelProps): react.JSX.Element;
|
|
294
336
|
|
|
295
337
|
interface ReauthOverlayProps {
|
|
296
338
|
config: Partial<LuminaryIdpConfig>;
|
|
@@ -353,4 +395,4 @@ declare function createPostLoginPathHelpers(options: PostLoginPathOptions): {
|
|
|
353
395
|
isUnsafeReturnPath: (path: string) => boolean;
|
|
354
396
|
};
|
|
355
397
|
|
|
356
|
-
export { type AuthGateConfig, type AuthGatePhase, AuthGateProvider, type AuthGateProviderProps, type AuthGateSnapshot, DEFAULT_LOGIN_THEME_COLOR, type ExperienceIdentifierType, type ExperiencePasswordSignInInput, type ExperiencePasswordSignInResult, type ExperienceSocialConnector, type HeadlessLoginLabels, HeadlessLoginPanel, type HeadlessLoginPanelProps, LuminaryAuthProvider, type LuminaryAuthProviderProps, type LuminaryAuthSession, type LuminaryIdpConfig, type PostLoginPathOptions, ReauthOverlay, type ReauthOverlayProps, type SignInOptions, type SocialProviderTarget, type UnauthorizedDisposition, authGate, clearStoredSession, createPostLoginPathHelpers, createUserManager, experiencePasswordSignIn, fetchSocialConnectors, getCurrentUser, getStoredAccessToken, handleSignInCallback, handleSignInPopupCallback, isIdpConfigured, isOidcPopupWindow, prepareSignInRequestUrl, readIdpConfigFromEnv, resetUserManager, resolveExperienceApiBase, resolveIssuer, sameOriginAuthorizeUrl, signInPopup, signInRedirect, signOutRedirect, useAuthGate, useAuthGateOptional, useLuminaryAuth, withAuthGateRetry };
|
|
398
|
+
export { type AuthGateConfig, type AuthGatePhase, AuthGateProvider, type AuthGateProviderProps, type AuthGateSnapshot, DEFAULT_LOGIN_THEME_COLOR, type ExperienceIdentifierType, type ExperiencePasswordSignInInput, type ExperiencePasswordSignInResult, type ExperienceSocialConnector, type FetchSocialConnectorsInput, type HeadlessLoginLabels, HeadlessLoginPanel, type HeadlessLoginPanelProps, LOGIN_EXPERIENCE_CAPABILITIES, type LoginExperienceAdapter, type LoginExperienceCapability, type LoginExperienceProvider, LogtoExperienceAdapter, LuminaryAuthProvider, type LuminaryAuthProviderProps, type LuminaryAuthSession, type LuminaryIdpConfig, type PostLoginPathOptions, ReauthOverlay, type ReauthOverlayProps, type SignInOptions, type SocialProviderTarget, type SocialSignInRequest, type UnauthorizedDisposition, authGate, clearStoredSession, createLoginExperienceAdapter, createLogtoDirectSignInRequest, createPostLoginPathHelpers, createUserManager, experiencePasswordSignIn, fetchSocialConnectors, getCurrentUser, getStoredAccessToken, handleSignInCallback, handleSignInPopupCallback, isIdpConfigured, isOidcPopupWindow, prepareSignInRequestUrl, readIdpConfigFromEnv, resetUserManager, resolveExperienceApiBase, resolveIssuer, resolveLoginExperienceAdapter, sameOriginAuthorizeUrl, signInPopup, signInRedirect, signOutRedirect, useAuthGate, useAuthGateOptional, useLuminaryAuth, withAuthGateRetry };
|