@jamroast/jamauth-react 0.0.0-stage → 0.0.2
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 +92 -2
- package/dist/index.cjs +356 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +218 -0
- package/dist/index.d.ts +218 -0
- package/dist/index.js +332 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -4
package/README.md
CHANGED
|
@@ -1,3 +1,93 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @jamroast/jamauth-react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Framework-agnostic React bindings for [jamauth](https://jamauth.net) — embedded
|
|
4
|
+
OIDC authorization-code (PKCE) sign-in / sign-up via an iframe bridge.
|
|
5
|
+
|
|
6
|
+
The **entire credential surface** (email + password, MFA, forgot / reset /
|
|
7
|
+
verify) renders on the jamauth authority inside an embedded `<iframe>`. When the
|
|
8
|
+
authorization code is minted, jamauth relays `{ type: 'jamauth:authorize',
|
|
9
|
+
code, state }` to the parent window via `postMessage`; this library exchanges it
|
|
10
|
+
for tokens with a public PKCE request and stores them.
|
|
11
|
+
|
|
12
|
+
No credential inputs live in this package — only an iframe wrapper.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
pnpm add @jamroast/jamauth-react
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import {
|
|
24
|
+
JamauthProvider,
|
|
25
|
+
SignIn,
|
|
26
|
+
SignUp,
|
|
27
|
+
SignedIn,
|
|
28
|
+
SignedOut,
|
|
29
|
+
useAuth,
|
|
30
|
+
useSession,
|
|
31
|
+
UserButton,
|
|
32
|
+
} from '@jamroast/jamauth-react';
|
|
33
|
+
|
|
34
|
+
function App() {
|
|
35
|
+
return (
|
|
36
|
+
<JamauthProvider
|
|
37
|
+
config={{
|
|
38
|
+
authority: 'https://jamauth.net', // your configured issuer/authority
|
|
39
|
+
clientId: 'your-client-id',
|
|
40
|
+
redirectUri: 'https://yourapp.com/auth/callback',
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
<SignedOut>
|
|
44
|
+
<SignIn />
|
|
45
|
+
{/* or <SignUp /> for the registration surface */}
|
|
46
|
+
</SignedOut>
|
|
47
|
+
<SignedIn>
|
|
48
|
+
<UserButton />
|
|
49
|
+
</SignedIn>
|
|
50
|
+
</JamauthProvider>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Configuration
|
|
56
|
+
|
|
57
|
+
| key | required | description |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| `authority` | yes | jamauth issuer origin (`https://jamauth.net`). The `postMessage` handshake is validated against this origin — never hardcoded. |
|
|
60
|
+
| `clientId` | yes | OIDC client id. |
|
|
61
|
+
| `redirectUri` | yes | OIDC callback, registered on the client. |
|
|
62
|
+
| `resource` | no | RFC 8707 resource indicator (RS256 human tokens only). |
|
|
63
|
+
| `scope` | no | defaults to `openid profile email offline_access`. |
|
|
64
|
+
| `tokenEndpoint` | no | defaults to `${authority}/token`. |
|
|
65
|
+
| `loginHint` | no | prefills the invitee email on sign-in. |
|
|
66
|
+
| `handshakeTimeoutMs` | no | blocked-iframe fallback timeout (default `5000`). |
|
|
67
|
+
| `onToken` | no | callback after a successful code exchange. |
|
|
68
|
+
|
|
69
|
+
### Hooks
|
|
70
|
+
|
|
71
|
+
- `useAuth()` — `{ isAuthenticated, token, signOut }`
|
|
72
|
+
- `useSession()` — reactive `{ isAuthenticated, token }` backed by the stored access token
|
|
73
|
+
- `useOidc()` — low-level bridge (`buildEmbedUrl`, `buildAuthorizeUrl`, `exchangeCodeForToken`, `authorityOrigin`)
|
|
74
|
+
|
|
75
|
+
### Components
|
|
76
|
+
|
|
77
|
+
- `<SignIn />`, `<SignUp />` — embedded iframe surfaces (no credential inputs)
|
|
78
|
+
- `<SignedIn />` / `<SignedOut />` — render based on session state
|
|
79
|
+
- `<UserButton />` — minimal account button (sign in / sign out)
|
|
80
|
+
|
|
81
|
+
## Embedded iframe bridge
|
|
82
|
+
|
|
83
|
+
The bridge is not fooled by `iframe.onload` (a `frame-ancestors`-blocked frame
|
|
84
|
+
still fires `onload`). Instead it confirms the handshake by validating
|
|
85
|
+
`event.origin === authorityOrigin(authority)` **and**
|
|
86
|
+
`event.source === iframe.contentWindow`. If `jamauth:ready` never arrives within
|
|
87
|
+
`handshakeTimeoutMs`, it falls back to a top-level
|
|
88
|
+
`window.location.assign(freshPkceAuthorizeUrl)` — idempotent and correct, so a
|
|
89
|
+
false positive degrades to the normal redirect flow rather than a broken UX.
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
|
|
6
|
+
// src/provider.tsx
|
|
7
|
+
|
|
8
|
+
// src/bridge.ts
|
|
9
|
+
var STORAGE_KEYS = {
|
|
10
|
+
userToken: "jamauth.userToken",
|
|
11
|
+
refreshToken: "jamauth.refreshToken",
|
|
12
|
+
tokenExpiresIn: "jamauth.tokenExpiresIn",
|
|
13
|
+
pkceVerifier: "jamauth.pkceVerifier"
|
|
14
|
+
};
|
|
15
|
+
var SESSION_CHANGED_EVENT = "jamauth:session-changed";
|
|
16
|
+
function notifySessionChanged() {
|
|
17
|
+
if (typeof window === "undefined") return;
|
|
18
|
+
window.dispatchEvent(new Event(SESSION_CHANGED_EVENT));
|
|
19
|
+
}
|
|
20
|
+
var DEFAULT_SCOPE = "openid profile email offline_access";
|
|
21
|
+
function base64UrlEncode(bytes) {
|
|
22
|
+
let binary = "";
|
|
23
|
+
for (const b of bytes) binary += String.fromCharCode(b);
|
|
24
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
25
|
+
}
|
|
26
|
+
function generateCodeVerifier() {
|
|
27
|
+
const bytes = new Uint8Array(32);
|
|
28
|
+
crypto.getRandomValues(bytes);
|
|
29
|
+
return base64UrlEncode(bytes);
|
|
30
|
+
}
|
|
31
|
+
async function sha256(verifier) {
|
|
32
|
+
const data = new TextEncoder().encode(verifier);
|
|
33
|
+
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
34
|
+
return base64UrlEncode(new Uint8Array(digest));
|
|
35
|
+
}
|
|
36
|
+
function authorityOrigin(authority) {
|
|
37
|
+
return new URL(authority).origin;
|
|
38
|
+
}
|
|
39
|
+
function verifierStorage() {
|
|
40
|
+
return typeof window === "undefined" ? null : window.sessionStorage;
|
|
41
|
+
}
|
|
42
|
+
function tokenStorage() {
|
|
43
|
+
return typeof window === "undefined" ? null : window.localStorage;
|
|
44
|
+
}
|
|
45
|
+
async function buildAuthorizeUrlWithPath(params, path) {
|
|
46
|
+
const verifier = generateCodeVerifier();
|
|
47
|
+
const storage = verifierStorage();
|
|
48
|
+
if (storage) storage.setItem(STORAGE_KEYS.pkceVerifier, verifier);
|
|
49
|
+
const challenge = await sha256(verifier);
|
|
50
|
+
const url = new URL(path, authorityOrigin(params.authority));
|
|
51
|
+
url.searchParams.set("client_id", params.clientId);
|
|
52
|
+
url.searchParams.set("response_type", "code");
|
|
53
|
+
url.searchParams.set("redirect_uri", params.redirectUri);
|
|
54
|
+
url.searchParams.set("scope", params.scope ?? DEFAULT_SCOPE);
|
|
55
|
+
if (params.resource) url.searchParams.set("resource", params.resource);
|
|
56
|
+
if (params.loginHint) url.searchParams.set("login_hint", params.loginHint);
|
|
57
|
+
if (params.prompt) url.searchParams.set("prompt", params.prompt);
|
|
58
|
+
url.searchParams.set("code_challenge", challenge);
|
|
59
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
60
|
+
url.searchParams.set("state", crypto.randomUUID());
|
|
61
|
+
return url;
|
|
62
|
+
}
|
|
63
|
+
function buildAuthorizeUrl(params) {
|
|
64
|
+
return buildAuthorizeUrlWithPath(params, "/auth");
|
|
65
|
+
}
|
|
66
|
+
function buildEmbedUrl(params) {
|
|
67
|
+
return buildAuthorizeUrlWithPath(params, "/embed/authorize");
|
|
68
|
+
}
|
|
69
|
+
function isTrustedBridgeMessage(event, authority, iframe) {
|
|
70
|
+
return event.origin === authorityOrigin(authority) && event.source === iframe.contentWindow;
|
|
71
|
+
}
|
|
72
|
+
function parseAuthorizeMessage(data) {
|
|
73
|
+
if (!data || typeof data !== "object") return null;
|
|
74
|
+
const message = data;
|
|
75
|
+
if (message.type !== "jamauth:authorize") return null;
|
|
76
|
+
if (typeof message.code !== "string" || typeof message.state !== "string") return null;
|
|
77
|
+
return { code: message.code, state: message.state };
|
|
78
|
+
}
|
|
79
|
+
function isReadyMessage(data) {
|
|
80
|
+
return !!data && typeof data === "object" && data.type === "jamauth:ready";
|
|
81
|
+
}
|
|
82
|
+
function storeTokenResponse(response) {
|
|
83
|
+
const storage = tokenStorage();
|
|
84
|
+
if (!storage) return;
|
|
85
|
+
storage.setItem(STORAGE_KEYS.userToken, response.access_token);
|
|
86
|
+
if (response.refresh_token) {
|
|
87
|
+
storage.setItem(STORAGE_KEYS.refreshToken, response.refresh_token);
|
|
88
|
+
}
|
|
89
|
+
if (response.expires_in !== void 0) {
|
|
90
|
+
storage.setItem(STORAGE_KEYS.tokenExpiresIn, String(response.expires_in));
|
|
91
|
+
}
|
|
92
|
+
const verifier = verifierStorage();
|
|
93
|
+
if (verifier) verifier.removeItem(STORAGE_KEYS.pkceVerifier);
|
|
94
|
+
notifySessionChanged();
|
|
95
|
+
}
|
|
96
|
+
function clearStoredTokens() {
|
|
97
|
+
const storage = tokenStorage();
|
|
98
|
+
if (!storage) return;
|
|
99
|
+
storage.removeItem(STORAGE_KEYS.userToken);
|
|
100
|
+
storage.removeItem(STORAGE_KEYS.refreshToken);
|
|
101
|
+
storage.removeItem(STORAGE_KEYS.tokenExpiresIn);
|
|
102
|
+
notifySessionChanged();
|
|
103
|
+
}
|
|
104
|
+
async function exchangeCodeForToken(params, code) {
|
|
105
|
+
const storage = verifierStorage();
|
|
106
|
+
const verifier = storage ? storage.getItem(STORAGE_KEYS.pkceVerifier) ?? "" : "";
|
|
107
|
+
const form = new URLSearchParams();
|
|
108
|
+
form.set("grant_type", "authorization_code");
|
|
109
|
+
form.set("code", code);
|
|
110
|
+
form.set("redirect_uri", params.redirectUri);
|
|
111
|
+
form.set("client_id", params.clientId);
|
|
112
|
+
form.set("code_verifier", verifier);
|
|
113
|
+
if (params.resource) form.set("resource", params.resource);
|
|
114
|
+
const endpoint = params.tokenEndpoint ?? `${authorityOrigin(params.authority)}/token`;
|
|
115
|
+
const res = await fetch(endpoint, {
|
|
116
|
+
method: "POST",
|
|
117
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
118
|
+
body: form.toString()
|
|
119
|
+
});
|
|
120
|
+
if (!res.ok) {
|
|
121
|
+
const body = await res.text();
|
|
122
|
+
throw new Error(`token exchange failed (${res.status}): ${body}`);
|
|
123
|
+
}
|
|
124
|
+
const json = await res.json();
|
|
125
|
+
if (!json.access_token) {
|
|
126
|
+
throw new Error("token response missing access_token");
|
|
127
|
+
}
|
|
128
|
+
return json;
|
|
129
|
+
}
|
|
130
|
+
function fallbackToTopLevelRedirect(authorizeUrl) {
|
|
131
|
+
if (typeof window === "undefined") return;
|
|
132
|
+
window.location.assign(authorizeUrl.toString());
|
|
133
|
+
}
|
|
134
|
+
var JamauthContext = react.createContext(null);
|
|
135
|
+
function JamauthProvider({
|
|
136
|
+
config,
|
|
137
|
+
children
|
|
138
|
+
}) {
|
|
139
|
+
return /* @__PURE__ */ jsxRuntime.jsx(JamauthContext.Provider, { value: config, children });
|
|
140
|
+
}
|
|
141
|
+
function useJamauth() {
|
|
142
|
+
const config = react.useContext(JamauthContext);
|
|
143
|
+
if (!config) {
|
|
144
|
+
throw new Error("useJamauth must be used within a <JamauthProvider>.");
|
|
145
|
+
}
|
|
146
|
+
return config;
|
|
147
|
+
}
|
|
148
|
+
function toOidcParams(config) {
|
|
149
|
+
return {
|
|
150
|
+
authority: config.authority,
|
|
151
|
+
clientId: config.clientId,
|
|
152
|
+
redirectUri: config.redirectUri,
|
|
153
|
+
resource: config.resource,
|
|
154
|
+
scope: config.scope,
|
|
155
|
+
tokenEndpoint: config.tokenEndpoint,
|
|
156
|
+
loginHint: config.loginHint
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function subscribeSession(onStoreChange) {
|
|
160
|
+
if (typeof window === "undefined") return () => {
|
|
161
|
+
};
|
|
162
|
+
window.addEventListener(SESSION_CHANGED_EVENT, onStoreChange);
|
|
163
|
+
return () => window.removeEventListener(SESSION_CHANGED_EVENT, onStoreChange);
|
|
164
|
+
}
|
|
165
|
+
function getSessionSnapshot() {
|
|
166
|
+
if (typeof window === "undefined") {
|
|
167
|
+
return { isAuthenticated: false, token: null };
|
|
168
|
+
}
|
|
169
|
+
const token = window.localStorage.getItem(STORAGE_KEYS.userToken);
|
|
170
|
+
return { isAuthenticated: !!token, token };
|
|
171
|
+
}
|
|
172
|
+
function useSession() {
|
|
173
|
+
return react.useSyncExternalStore(subscribeSession, getSessionSnapshot, getSessionSnapshot);
|
|
174
|
+
}
|
|
175
|
+
function useAuth() {
|
|
176
|
+
const session = useSession();
|
|
177
|
+
const signOut = () => clearStoredTokens();
|
|
178
|
+
return { ...session, signOut };
|
|
179
|
+
}
|
|
180
|
+
function useOidc() {
|
|
181
|
+
const config = useJamauth();
|
|
182
|
+
const params = toOidcParams(config);
|
|
183
|
+
return {
|
|
184
|
+
authorityOrigin: () => authorityOrigin(config.authority),
|
|
185
|
+
buildAuthorizeUrl: () => buildAuthorizeUrl(params),
|
|
186
|
+
buildEmbedUrl: (prompt) => buildEmbedUrl({ ...params, prompt }),
|
|
187
|
+
exchangeCodeForToken: (code) => exchangeCodeForToken(params, code)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function SignedIn({ children }) {
|
|
191
|
+
const { isAuthenticated } = useSession();
|
|
192
|
+
return isAuthenticated ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }) : null;
|
|
193
|
+
}
|
|
194
|
+
function SignedOut({ children }) {
|
|
195
|
+
const { isAuthenticated } = useSession();
|
|
196
|
+
return isAuthenticated ? null : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
197
|
+
}
|
|
198
|
+
function useEmbeddedAuth(prompt) {
|
|
199
|
+
const config = useJamauth();
|
|
200
|
+
const iframeRef = react.useRef(null);
|
|
201
|
+
const [src, setSrc] = react.useState("");
|
|
202
|
+
const [status, setStatus] = react.useState("loading");
|
|
203
|
+
react.useEffect(() => {
|
|
204
|
+
if (typeof window === "undefined") return;
|
|
205
|
+
let cancelled = false;
|
|
206
|
+
let timer;
|
|
207
|
+
const timeoutMs = config.handshakeTimeoutMs ?? 5e3;
|
|
208
|
+
const params = {
|
|
209
|
+
authority: config.authority,
|
|
210
|
+
clientId: config.clientId,
|
|
211
|
+
redirectUri: config.redirectUri,
|
|
212
|
+
resource: config.resource,
|
|
213
|
+
scope: config.scope,
|
|
214
|
+
tokenEndpoint: config.tokenEndpoint,
|
|
215
|
+
loginHint: config.loginHint,
|
|
216
|
+
prompt
|
|
217
|
+
};
|
|
218
|
+
void buildEmbedUrl(params).then((embedUrl) => {
|
|
219
|
+
if (cancelled) return;
|
|
220
|
+
setSrc(embedUrl.toString());
|
|
221
|
+
});
|
|
222
|
+
timer = window.setTimeout(() => {
|
|
223
|
+
if (cancelled) return;
|
|
224
|
+
void buildAuthorizeUrl(params).then((authorizeUrl) => {
|
|
225
|
+
if (cancelled) return;
|
|
226
|
+
setStatus("fallback");
|
|
227
|
+
fallbackToTopLevelRedirect(authorizeUrl);
|
|
228
|
+
});
|
|
229
|
+
}, timeoutMs);
|
|
230
|
+
const onMessage = (event) => {
|
|
231
|
+
const iframe = iframeRef.current;
|
|
232
|
+
if (!iframe) return;
|
|
233
|
+
if (!isTrustedBridgeMessage(event, config.authority, iframe)) return;
|
|
234
|
+
if (isReadyMessage(event.data)) {
|
|
235
|
+
if (timer !== void 0) window.clearTimeout(timer);
|
|
236
|
+
setStatus("ready");
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const authorize = parseAuthorizeMessage(event.data);
|
|
240
|
+
if (!authorize) return;
|
|
241
|
+
if (timer !== void 0) window.clearTimeout(timer);
|
|
242
|
+
void exchangeCodeForToken(params, authorize.code).then((response) => {
|
|
243
|
+
storeTokenResponse(response);
|
|
244
|
+
config.onToken?.(response);
|
|
245
|
+
setStatus("authenticated");
|
|
246
|
+
}).catch(async () => {
|
|
247
|
+
const authorizeUrl = await buildAuthorizeUrl(params);
|
|
248
|
+
if (cancelled) return;
|
|
249
|
+
setStatus("fallback");
|
|
250
|
+
fallbackToTopLevelRedirect(authorizeUrl);
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
window.addEventListener("message", onMessage);
|
|
254
|
+
return () => {
|
|
255
|
+
cancelled = true;
|
|
256
|
+
if (timer !== void 0) window.clearTimeout(timer);
|
|
257
|
+
window.removeEventListener("message", onMessage);
|
|
258
|
+
};
|
|
259
|
+
}, [
|
|
260
|
+
config.authority,
|
|
261
|
+
config.clientId,
|
|
262
|
+
config.redirectUri,
|
|
263
|
+
config.resource,
|
|
264
|
+
config.scope,
|
|
265
|
+
config.tokenEndpoint,
|
|
266
|
+
config.loginHint,
|
|
267
|
+
config.handshakeTimeoutMs,
|
|
268
|
+
config.onToken,
|
|
269
|
+
prompt
|
|
270
|
+
]);
|
|
271
|
+
return { iframeRef, src, status };
|
|
272
|
+
}
|
|
273
|
+
function SignIn({ className, style }) {
|
|
274
|
+
const { iframeRef, src } = useEmbeddedAuth();
|
|
275
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
276
|
+
"iframe",
|
|
277
|
+
{
|
|
278
|
+
ref: iframeRef,
|
|
279
|
+
src,
|
|
280
|
+
title: "Sign in with jamauth",
|
|
281
|
+
className,
|
|
282
|
+
style: {
|
|
283
|
+
border: "none",
|
|
284
|
+
width: "100%",
|
|
285
|
+
minHeight: "32rem",
|
|
286
|
+
...style
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
function SignUp({ className, style }) {
|
|
292
|
+
const { iframeRef, src } = useEmbeddedAuth("register");
|
|
293
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
294
|
+
"iframe",
|
|
295
|
+
{
|
|
296
|
+
ref: iframeRef,
|
|
297
|
+
src,
|
|
298
|
+
title: "Sign up with jamauth",
|
|
299
|
+
className,
|
|
300
|
+
style: {
|
|
301
|
+
border: "none",
|
|
302
|
+
width: "100%",
|
|
303
|
+
minHeight: "32rem",
|
|
304
|
+
...style
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
function UserButton({
|
|
310
|
+
signInLabel = "Sign in",
|
|
311
|
+
signOutLabel = "Sign out",
|
|
312
|
+
onSignOut,
|
|
313
|
+
className,
|
|
314
|
+
style
|
|
315
|
+
}) {
|
|
316
|
+
const { isAuthenticated, signOut } = useAuth();
|
|
317
|
+
if (!isAuthenticated) {
|
|
318
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className, style, children: signInLabel });
|
|
319
|
+
}
|
|
320
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
321
|
+
"button",
|
|
322
|
+
{
|
|
323
|
+
type: "button",
|
|
324
|
+
className,
|
|
325
|
+
style,
|
|
326
|
+
onClick: onSignOut ?? signOut,
|
|
327
|
+
children: signOutLabel
|
|
328
|
+
}
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
exports.JamauthProvider = JamauthProvider;
|
|
333
|
+
exports.SESSION_CHANGED_EVENT = SESSION_CHANGED_EVENT;
|
|
334
|
+
exports.STORAGE_KEYS = STORAGE_KEYS;
|
|
335
|
+
exports.SignIn = SignIn;
|
|
336
|
+
exports.SignUp = SignUp;
|
|
337
|
+
exports.SignedIn = SignedIn;
|
|
338
|
+
exports.SignedOut = SignedOut;
|
|
339
|
+
exports.UserButton = UserButton;
|
|
340
|
+
exports.authorityOrigin = authorityOrigin;
|
|
341
|
+
exports.buildAuthorizeUrl = buildAuthorizeUrl;
|
|
342
|
+
exports.buildEmbedUrl = buildEmbedUrl;
|
|
343
|
+
exports.clearStoredTokens = clearStoredTokens;
|
|
344
|
+
exports.exchangeCodeForToken = exchangeCodeForToken;
|
|
345
|
+
exports.fallbackToTopLevelRedirect = fallbackToTopLevelRedirect;
|
|
346
|
+
exports.isReadyMessage = isReadyMessage;
|
|
347
|
+
exports.isTrustedBridgeMessage = isTrustedBridgeMessage;
|
|
348
|
+
exports.parseAuthorizeMessage = parseAuthorizeMessage;
|
|
349
|
+
exports.storeTokenResponse = storeTokenResponse;
|
|
350
|
+
exports.useAuth = useAuth;
|
|
351
|
+
exports.useEmbeddedAuth = useEmbeddedAuth;
|
|
352
|
+
exports.useJamauth = useJamauth;
|
|
353
|
+
exports.useOidc = useOidc;
|
|
354
|
+
exports.useSession = useSession;
|
|
355
|
+
//# sourceMappingURL=index.cjs.map
|
|
356
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bridge.ts","../src/provider.tsx","../src/use-embedded-auth.ts","../src/sign-in.tsx","../src/sign-up.tsx","../src/user-button.tsx"],"names":["createContext","useContext","useSyncExternalStore","jsx","Fragment","useRef","useState","useEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Framework-agnostic OIDC authorization-code (PKCE) + embedded-iframe\n * `postMessage` bridge for `@jamroast/jamauth-react`.\n *\n * Generalizes the PKCE S256 + `localStorage` token pattern from jamauth's own\n * SPA (`web/src/lib/oidc-capture.ts`) so any client app (Next/Vite/Remix/etc.)\n * can render a branded `SignIn`/`SignUp` on its own domain while every\n * credential form (email+password, MFA, forgot/reset/verify) stays on the\n * jamauth authority inside an embedded `<iframe>` that completes the OIDC\n * authorization-code flow and relays `{ code, state }` to the parent via\n * `postMessage`.\n *\n * Pure React + `window`/`postMessage`/`localStorage` with `typeof window`\n * guards so it is SSR-safe. No credential inputs live here — credentials are\n * typed only inside the jamauth frame (server-rendered interaction HTML).\n */\n\nexport const STORAGE_KEYS = {\n userToken: 'jamauth.userToken',\n refreshToken: 'jamauth.refreshToken',\n tokenExpiresIn: 'jamauth.tokenExpiresIn',\n pkceVerifier: 'jamauth.pkceVerifier',\n} as const;\n\n/** Custom event fired whenever the stored session changes (sign-in/sign-out). */\nexport const SESSION_CHANGED_EVENT = 'jamauth:session-changed';\n\nfunction notifySessionChanged(): void {\n if (typeof window === 'undefined') return;\n window.dispatchEvent(new Event(SESSION_CHANGED_EVENT));\n}\n\nconst DEFAULT_SCOPE = 'openid profile email offline_access';\n\n/** Caller-supplied OIDC client identity (never a hardcoded first-party default). */\nexport interface OidcClientParams {\n /** The jamauth issuer/authority origin, e.g. `https://jamauth.net`. */\n authority: string;\n clientId: string;\n redirectUri: string;\n /** RFC 8707 resource indicator; only needed for RS256 human-token minting. */\n resource?: string;\n /** OIDC `login_hint` — the invitee email, prefilled on sign-in. */\n loginHint?: string;\n /** OIDC scope; defaults to `openid profile email offline_access`. */\n scope?: string;\n /** Token endpoint override; defaults to `${authority}/token`. */\n tokenEndpoint?: string;\n /** OIDC `prompt` value (e.g. `'register'` for the sign-up surface). */\n prompt?: string;\n}\n\nexport interface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n}\n\nexport type AuthorizeMessage = { type: 'jamauth:authorize'; code: string; state: string };\nexport type ReadyMessage = { type: 'jamauth:ready' };\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let binary = '';\n for (const b of bytes) binary += String.fromCharCode(b);\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction generateCodeVerifier(): string {\n const bytes = new Uint8Array(32);\n crypto.getRandomValues(bytes);\n return base64UrlEncode(bytes);\n}\n\nasync function sha256(verifier: string): Promise<string> {\n const data = new TextEncoder().encode(verifier);\n const digest = await crypto.subtle.digest('SHA-256', data);\n return base64UrlEncode(new Uint8Array(digest));\n}\n\n/**\n * Derive the configured authority origin. The handshake validates incoming\n * `postMessage` events against this origin — never a hardcoded `jamauth.net`\n * literal.\n */\nexport function authorityOrigin(authority: string): string {\n return new URL(authority).origin;\n}\n\nfunction verifierStorage(): Storage | null {\n return typeof window === 'undefined' ? null : window.sessionStorage;\n}\n\nfunction tokenStorage(): Storage | null {\n return typeof window === 'undefined' ? null : window.localStorage;\n}\n\nasync function buildAuthorizeUrlWithPath(\n params: OidcClientParams,\n path: '/auth' | '/embed/authorize',\n): Promise<URL> {\n const verifier = generateCodeVerifier();\n const storage = verifierStorage();\n if (storage) storage.setItem(STORAGE_KEYS.pkceVerifier, verifier);\n const challenge = await sha256(verifier);\n\n const url = new URL(path, authorityOrigin(params.authority));\n url.searchParams.set('client_id', params.clientId);\n url.searchParams.set('response_type', 'code');\n url.searchParams.set('redirect_uri', params.redirectUri);\n url.searchParams.set('scope', params.scope ?? DEFAULT_SCOPE);\n if (params.resource) url.searchParams.set('resource', params.resource);\n if (params.loginHint) url.searchParams.set('login_hint', params.loginHint);\n if (params.prompt) url.searchParams.set('prompt', params.prompt);\n url.searchParams.set('code_challenge', challenge);\n url.searchParams.set('code_challenge_method', 'S256');\n url.searchParams.set('state', crypto.randomUUID());\n return url;\n}\n\n/** Build the top-level `/auth` authorization URL (PKCE S256, `response_type=code`). */\nexport function buildAuthorizeUrl(params: OidcClientParams): Promise<URL> {\n return buildAuthorizeUrlWithPath(params, '/auth');\n}\n\n/** Build the embedded `/embed/authorize` iframe URL (same PKCE S256 params). */\nexport function buildEmbedUrl(params: OidcClientParams): Promise<URL> {\n return buildAuthorizeUrlWithPath(params, '/embed/authorize');\n}\n\n/**\n * Validate an incoming `postMessage` event against the configured authority\n * origin (never hardcoded) AND the iframe's `contentWindow` (so a same-origin\n * event from an unexpected frame is ignored).\n */\nexport function isTrustedBridgeMessage(\n event: MessageEvent,\n authority: string,\n iframe: HTMLIFrameElement,\n): boolean {\n return (\n event.origin === authorityOrigin(authority) &&\n event.source === iframe.contentWindow\n );\n}\n\n/** Parse a `jamauth:authorize` relay payload; returns `null` for other types. */\nexport function parseAuthorizeMessage(data: unknown): { code: string; state: string } | null {\n if (!data || typeof data !== 'object') return null;\n const message = data as Partial<AuthorizeMessage>;\n if (message.type !== 'jamauth:authorize') return null;\n if (typeof message.code !== 'string' || typeof message.state !== 'string') return null;\n return { code: message.code, state: message.state };\n}\n\n/** Parse a `jamauth:ready` handshake payload; returns `true` for the handshake. */\nexport function isReadyMessage(data: unknown): data is ReadyMessage {\n return !!data && typeof data === 'object' && (data as ReadyMessage).type === 'jamauth:ready';\n}\n\n/** Store a minted token response (mirrors `oidc-capture.ts`). */\nexport function storeTokenResponse(response: TokenResponse): void {\n const storage = tokenStorage();\n if (!storage) return;\n storage.setItem(STORAGE_KEYS.userToken, response.access_token);\n if (response.refresh_token) {\n storage.setItem(STORAGE_KEYS.refreshToken, response.refresh_token);\n }\n if (response.expires_in !== undefined) {\n storage.setItem(STORAGE_KEYS.tokenExpiresIn, String(response.expires_in));\n }\n const verifier = verifierStorage();\n if (verifier) verifier.removeItem(STORAGE_KEYS.pkceVerifier);\n notifySessionChanged();\n}\n\n/** Clear the stored session tokens (sign-out). */\nexport function clearStoredTokens(): void {\n const storage = tokenStorage();\n if (!storage) return;\n storage.removeItem(STORAGE_KEYS.userToken);\n storage.removeItem(STORAGE_KEYS.refreshToken);\n storage.removeItem(STORAGE_KEYS.tokenExpiresIn);\n notifySessionChanged();\n}\n\n/**\n * Exchange an authorization `code` for tokens via a PUBLIC PKCE request\n * (`grant_type=authorization_code`, no client_secret, no Authorization header).\n * The token endpoint defaults to `${authority}/token` (CORS-allowed for the\n * registered client origin via `clientBasedCORS`).\n */\nexport async function exchangeCodeForToken(\n params: OidcClientParams,\n code: string,\n): Promise<TokenResponse> {\n const storage = verifierStorage();\n const verifier = storage ? storage.getItem(STORAGE_KEYS.pkceVerifier) ?? '' : '';\n\n const form = new URLSearchParams();\n form.set('grant_type', 'authorization_code');\n form.set('code', code);\n form.set('redirect_uri', params.redirectUri);\n form.set('client_id', params.clientId);\n form.set('code_verifier', verifier);\n if (params.resource) form.set('resource', params.resource);\n\n const endpoint = params.tokenEndpoint ?? `${authorityOrigin(params.authority)}/token`;\n const res = await fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: form.toString(),\n });\n\n if (!res.ok) {\n const body = await res.text();\n throw new Error(`token exchange failed (${res.status}): ${body}`);\n }\n\n const json = (await res.json()) as TokenResponse;\n if (!json.access_token) {\n throw new Error('token response missing access_token');\n }\n return json;\n}\n\n/**\n * Fallback to a top-level redirect with a fresh PKCE `authorizeUrl`. Used when\n * the embedded iframe is blocked (or fails to handshake) — idempotent and\n * correct, so a false positive degrades to the top-level flow rather than a\n * broken UX.\n */\nexport function fallbackToTopLevelRedirect(authorizeUrl: URL): void {\n if (typeof window === 'undefined') return;\n window.location.assign(authorizeUrl.toString());\n}\n","import {\n createContext,\n useContext,\n useSyncExternalStore,\n type ReactNode,\n} from 'react';\nimport {\n STORAGE_KEYS,\n SESSION_CHANGED_EVENT,\n authorityOrigin,\n buildAuthorizeUrl,\n buildEmbedUrl,\n clearStoredTokens,\n exchangeCodeForToken,\n type OidcClientParams,\n type TokenResponse,\n} from './bridge.js';\n\n/** Configuration carried by `JamauthProvider`. */\nexport interface JamauthConfig {\n /** The jamauth issuer/authority origin, e.g. `https://jamauth.net`. */\n authority: string;\n clientId: string;\n redirectUri: string;\n resource?: string;\n scope?: string;\n tokenEndpoint?: string;\n loginHint?: string;\n /** Blocked-iframe handshake timeout in ms (default 5000). */\n handshakeTimeoutMs?: number;\n /** Called once the authorization code is exchanged for tokens. */\n onToken?: (response: TokenResponse) => void;\n}\n\nconst JamauthContext = createContext<JamauthConfig | null>(null);\n\n/** Provide the jamauth authority + client identity to the embedded auth surface. */\nexport function JamauthProvider({\n config,\n children,\n}: {\n config: JamauthConfig;\n children: ReactNode;\n}) {\n return (\n <JamauthContext.Provider value={config}>{children}</JamauthContext.Provider>\n );\n}\n\n/** Read the configured jamauth client identity (throws outside a provider). */\nexport function useJamauth(): JamauthConfig {\n const config = useContext(JamauthContext);\n if (!config) {\n throw new Error('useJamauth must be used within a <JamauthProvider>.');\n }\n return config;\n}\n\nfunction toOidcParams(config: JamauthConfig): OidcClientParams {\n return {\n authority: config.authority,\n clientId: config.clientId,\n redirectUri: config.redirectUri,\n resource: config.resource,\n scope: config.scope,\n tokenEndpoint: config.tokenEndpoint,\n loginHint: config.loginHint,\n };\n}\n\nfunction subscribeSession(onStoreChange: () => void): () => void {\n if (typeof window === 'undefined') return () => {};\n window.addEventListener(SESSION_CHANGED_EVENT, onStoreChange);\n return () => window.removeEventListener(SESSION_CHANGED_EVENT, onStoreChange);\n}\n\nexport interface SessionState {\n isAuthenticated: boolean;\n token: string | null;\n}\n\nfunction getSessionSnapshot(): SessionState {\n if (typeof window === 'undefined') {\n return { isAuthenticated: false, token: null };\n }\n const token = window.localStorage.getItem(STORAGE_KEYS.userToken);\n return { isAuthenticated: !!token, token };\n}\n\n/** Reactive session state sourced from the stored access token. */\nexport function useSession(): SessionState {\n return useSyncExternalStore(subscribeSession, getSessionSnapshot, getSessionSnapshot);\n}\n\n/** High-level auth surface: session state plus sign-out. */\nexport function useAuth(): SessionState & { signOut: () => void } {\n const session = useSession();\n const signOut = () => clearStoredTokens();\n return { ...session, signOut };\n}\n\n/** Low-level OIDC bridge bound to the configured authority/client identity. */\nexport function useOidc() {\n const config = useJamauth();\n const params = toOidcParams(config);\n return {\n authorityOrigin: () => authorityOrigin(config.authority),\n buildAuthorizeUrl: () => buildAuthorizeUrl(params),\n buildEmbedUrl: (prompt?: string) => buildEmbedUrl({ ...params, prompt }),\n exchangeCodeForToken: (code: string) => exchangeCodeForToken(params, code),\n };\n}\n\n/** Renders `children` only while authenticated (access token present). */\nexport function SignedIn({ children }: { children: ReactNode }) {\n const { isAuthenticated } = useSession();\n return isAuthenticated ? <>{children}</> : null;\n}\n\n/** Renders `children` only while signed out (no access token present). */\nexport function SignedOut({ children }: { children: ReactNode }) {\n const { isAuthenticated } = useSession();\n return isAuthenticated ? null : <>{children}</>;\n}\n","import { useEffect, useRef, useState } from 'react';\nimport {\n buildAuthorizeUrl,\n buildEmbedUrl,\n exchangeCodeForToken,\n fallbackToTopLevelRedirect,\n isReadyMessage,\n isTrustedBridgeMessage,\n parseAuthorizeMessage,\n storeTokenResponse,\n type OidcClientParams,\n} from './bridge.js';\nimport { useJamauth } from './provider.js';\n\nexport type EmbeddedStatus = 'loading' | 'ready' | 'authenticated' | 'fallback';\n\nexport interface EmbeddedAuthState {\n iframeRef: React.RefObject<HTMLIFrameElement | null>;\n src: string;\n status: EmbeddedStatus;\n}\n\n/**\n * Mount the embedded `/embed/authorize` iframe and drive the confirmation\n * handshake + timeout fallback:\n *\n * - `iframe.onload` is NOT authoritative (a `frame-ancestors`-blocked frame\n * still fires `onload`). Instead the parent validates\n * `event.origin === authorityOrigin` (derived from the configured authority,\n * never hardcoded) **and** `event.source === iframe.contentWindow`.\n * - A `handshakeTimeoutMs` timer (default ~5s) falls back to a top-level\n * `window.location.assign(freshPkceAuthorizeUrl)` when no `jamauth:ready`\n * arrives — idempotent and correct, so a false positive degrades to the\n * top-level flow rather than a broken UX.\n * - On `jamauth:authorize`, the code is exchanged via public PKCE and the\n * tokens are stored.\n */\nexport function useEmbeddedAuth(prompt?: string): EmbeddedAuthState {\n const config = useJamauth();\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const [src, setSrc] = useState('');\n const [status, setStatus] = useState<EmbeddedStatus>('loading');\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n let cancelled = false;\n let timer: number | undefined;\n const timeoutMs = config.handshakeTimeoutMs ?? 5000;\n\n const params: OidcClientParams = {\n authority: config.authority,\n clientId: config.clientId,\n redirectUri: config.redirectUri,\n resource: config.resource,\n scope: config.scope,\n tokenEndpoint: config.tokenEndpoint,\n loginHint: config.loginHint,\n prompt,\n };\n\n void buildEmbedUrl(params).then((embedUrl) => {\n if (cancelled) return;\n setSrc(embedUrl.toString());\n });\n\n timer = window.setTimeout(() => {\n if (cancelled) return;\n void buildAuthorizeUrl(params).then((authorizeUrl) => {\n if (cancelled) return;\n setStatus('fallback');\n fallbackToTopLevelRedirect(authorizeUrl);\n });\n }, timeoutMs);\n\n const onMessage = (event: MessageEvent) => {\n const iframe = iframeRef.current;\n if (!iframe) return;\n if (!isTrustedBridgeMessage(event, config.authority, iframe)) return;\n\n if (isReadyMessage(event.data)) {\n if (timer !== undefined) window.clearTimeout(timer);\n setStatus('ready');\n return;\n }\n\n const authorize = parseAuthorizeMessage(event.data);\n if (!authorize) return;\n if (timer !== undefined) window.clearTimeout(timer);\n\n void exchangeCodeForToken(params, authorize.code)\n .then((response) => {\n storeTokenResponse(response);\n config.onToken?.(response);\n setStatus('authenticated');\n })\n .catch(async () => {\n const authorizeUrl = await buildAuthorizeUrl(params);\n if (cancelled) return;\n setStatus('fallback');\n fallbackToTopLevelRedirect(authorizeUrl);\n });\n };\n\n window.addEventListener('message', onMessage);\n\n return () => {\n cancelled = true;\n if (timer !== undefined) window.clearTimeout(timer);\n window.removeEventListener('message', onMessage);\n };\n }, [\n config.authority,\n config.clientId,\n config.redirectUri,\n config.resource,\n config.scope,\n config.tokenEndpoint,\n config.loginHint,\n config.handshakeTimeoutMs,\n config.onToken,\n prompt,\n ]);\n\n return { iframeRef, src, status };\n}\n","import type { CSSProperties } from 'react';\nimport { useEmbeddedAuth } from './use-embedded-auth.js';\n\nexport interface SignInProps {\n /** Override the handshake timeout (ms) for this surface. */\n handshakeTimeoutMs?: number;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * Embedded sign-in surface — an iframe wrapper around the jamauth\n * `/embed/authorize` flow. This component renders **no credential inputs**:\n * the email+password form (and MFA / forgot / reset / verify) lives on the\n * jamauth authority inside the frame, and the completed authorization code is\n * relayed back to the parent via `postMessage`.\n */\nexport function SignIn({ className, style }: SignInProps) {\n const { iframeRef, src } = useEmbeddedAuth();\n return (\n <iframe\n ref={iframeRef}\n src={src}\n title=\"Sign in with jamauth\"\n className={className}\n style={{\n border: 'none',\n width: '100%',\n minHeight: '32rem',\n ...style,\n }}\n />\n );\n}\n","import type { CSSProperties } from 'react';\nimport { useEmbeddedAuth } from './use-embedded-auth.js';\n\nexport interface SignUpProps {\n /** Override the handshake timeout (ms) for this surface. */\n handshakeTimeoutMs?: number;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * Embedded sign-up surface — an iframe wrapper around the jamauth\n * `/embed/authorize` flow with `prompt=register`. Like `SignIn`, this renders\n * **no credential inputs**; the sign-up form lives on the jamauth authority\n * inside the frame and the completed authorization code is relayed back via\n * `postMessage`.\n */\nexport function SignUp({ className, style }: SignUpProps) {\n const { iframeRef, src } = useEmbeddedAuth('register');\n return (\n <iframe\n ref={iframeRef}\n src={src}\n title=\"Sign up with jamauth\"\n className={className}\n style={{\n border: 'none',\n width: '100%',\n minHeight: '32rem',\n ...style,\n }}\n />\n );\n}\n","import type { CSSProperties, ReactNode } from 'react';\nimport { useAuth } from './provider.js';\n\nexport interface UserButtonProps {\n /** Label shown when signed out (default \"Sign in\"). */\n signInLabel?: ReactNode;\n /** Label shown when signed in (default \"Sign out\"). */\n signOutLabel?: ReactNode;\n /** Called instead of the default sign-out when the user is signed in. */\n onSignOut?: () => void;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * A minimal, framework-agnostic account button. It reflects the stored session\n * state and, when signed in, signs the user out (or delegates to `onSignOut`).\n * It renders no credential inputs.\n */\nexport function UserButton({\n signInLabel = 'Sign in',\n signOutLabel = 'Sign out',\n onSignOut,\n className,\n style,\n}: UserButtonProps) {\n const { isAuthenticated, signOut } = useAuth();\n\n if (!isAuthenticated) {\n return (\n <span className={className} style={style}>\n {signInLabel}\n </span>\n );\n }\n\n return (\n <button\n type=\"button\"\n className={className}\n style={style}\n onClick={onSignOut ?? signOut}\n >\n {signOutLabel}\n </button>\n );\n}\n"]}
|