@versini/auth-provider 8.0.3 → 8.0.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/README.md +147 -1
- package/dist/auth.js +16 -16
- package/dist/auth0.js +333 -313
- package/dist/hooks.js +3 -3
- package/dist/index.js +6 -6
- package/package.json +9 -8
- package/dist/index-DxGUVOpC.js +0 -985
package/README.md
CHANGED
|
@@ -1,3 +1,149 @@
|
|
|
1
1
|
# @versini/auth-provider
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
High-level React authentication components & hooks supporting password (PKCE Code) and Passkey (WebAuthn) flows, with optional Auth0 integration. Built on the primitives from `@versini/auth-common`.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @versini/auth-provider @versini/auth-common react react-dom
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Peer deps: `react` (>= 19) & `react-dom`.
|
|
12
|
+
|
|
13
|
+
## Packages Relationship
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
@versini/auth-provider -> @versini/auth-common (utilities, constants)
|
|
17
|
+
-> @versini/ui-hooks (local storage abstraction)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
- PKCE Code + Refresh token flow
|
|
23
|
+
- Passkey (WebAuthn) registration & authentication
|
|
24
|
+
- Silent access token refresh with refresh token rotation
|
|
25
|
+
- Role / permission helpers (re-export of `isGranted` & `AUTH_TYPES`)
|
|
26
|
+
- Opt-in Auth0 provider wrapper
|
|
27
|
+
- Local storage isolation per `clientId`
|
|
28
|
+
- Timezone & build metadata banner injection (in distributed bundles)
|
|
29
|
+
|
|
30
|
+
## Quick Start (Custom Auth Backend)
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { AuthProvider } from "@versini/auth-provider";
|
|
34
|
+
|
|
35
|
+
function App() {
|
|
36
|
+
return (
|
|
37
|
+
<AuthProvider clientId="my-web-app" sessionExpiration="3600" debug>
|
|
38
|
+
<MainRoutes />
|
|
39
|
+
</AuthProvider>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Inside your components:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { useAuth } from "@versini/auth-provider/hooks";
|
|
48
|
+
|
|
49
|
+
export function Profile() {
|
|
50
|
+
const { user, isAuthenticated, login, logout, getAccessToken } = useAuth();
|
|
51
|
+
|
|
52
|
+
if (!isAuthenticated) {
|
|
53
|
+
return <button onClick={() => login("alice", "p@ssw0rd")}>Login</button>;
|
|
54
|
+
}
|
|
55
|
+
return (
|
|
56
|
+
<div>
|
|
57
|
+
<p>User: {user?.username}</p>
|
|
58
|
+
<button onClick={logout}>Logout</button>
|
|
59
|
+
<button
|
|
60
|
+
onClick={async () => {
|
|
61
|
+
const token = await getAccessToken();
|
|
62
|
+
console.log("access", token.slice(0, 20) + "...");
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
Get Access Token
|
|
66
|
+
</button>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Passkey (WebAuthn) Flow
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
const { registeringForPasskey, loginWithPasskey } = useAuth();
|
|
76
|
+
|
|
77
|
+
// After user authenticates with password you can offer passkey registration:
|
|
78
|
+
await registeringForPasskey();
|
|
79
|
+
|
|
80
|
+
// Later, user can login directly with passkey:
|
|
81
|
+
await loginWithPasskey();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Auth0 Integration
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { Auth0Provider } from "@versini/auth-provider/auth0";
|
|
88
|
+
|
|
89
|
+
<Auth0Provider
|
|
90
|
+
domain="YOUR_DOMAIN"
|
|
91
|
+
clientId="YOUR_CLIENT_ID"
|
|
92
|
+
authorizationParams={{ redirect_uri: window.location.origin }}
|
|
93
|
+
>
|
|
94
|
+
<App />
|
|
95
|
+
</Auth0Provider>;
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
All Auth hooks still come from `@versini/auth-provider/hooks`.
|
|
99
|
+
|
|
100
|
+
## Public API Summary
|
|
101
|
+
|
|
102
|
+
- `<AuthProvider />` – Core provider. Props:
|
|
103
|
+
- `clientId: string` (required)
|
|
104
|
+
- `sessionExpiration?: string` (TTL hint sent to backend)
|
|
105
|
+
- `domain?: string` (multi-tenant / custom domain support)
|
|
106
|
+
- `debug?: boolean` (enables internal logging via `useLogger`)
|
|
107
|
+
- `endpoint?: string` (override default auth service URL)
|
|
108
|
+
- Hooks (from `hooks` entry):
|
|
109
|
+
- `useAuth()` – Returns `AuthContextProps`:
|
|
110
|
+
- state: `isLoading`, `isAuthenticated`, `user`, `logoutReason`, `authenticationType`
|
|
111
|
+
- methods: `login(username, password)`, `logout()`, `getAccessToken()`, `getIdToken()`, `registeringForPasskey()`, `loginWithPasskey()`
|
|
112
|
+
- Auth0:
|
|
113
|
+
- `<Auth0Provider />` – Wraps children and injects Auth0 context + shared `useAuth` hook wiring.
|
|
114
|
+
- Re-exports from `@versini/auth-common`:
|
|
115
|
+
- `AUTH_TYPES`, `isGranted`
|
|
116
|
+
|
|
117
|
+
## Storage Strategy
|
|
118
|
+
|
|
119
|
+
Local storage keys are namespaced: `@@auth@@::<clientId>::@@<token-type>@@`.
|
|
120
|
+
On logout or token invalidation all related keys are purged atomically (`removeStateAndLocalStorage`).
|
|
121
|
+
|
|
122
|
+
## Token Refresh
|
|
123
|
+
|
|
124
|
+
`getAccessToken()` validates the existing access token; if expired/invalid it attempts a silent refresh via `TokenManager.refreshtoken()`. Failure triggers a forced logout (security-first principle).
|
|
125
|
+
|
|
126
|
+
## Error & Security Principles
|
|
127
|
+
|
|
128
|
+
- Deny-by-default: unauthorized or invalid token state leads to logout.
|
|
129
|
+
- All network operations funnel through typed helpers; unexpected responses cause cleanup.
|
|
130
|
+
- No sensitive values are logged unless `debug` is enabled (still avoid including raw tokens in production logs).
|
|
131
|
+
- PKCE flow ensures authorization code interception resistance.
|
|
132
|
+
|
|
133
|
+
## Bundling Notes
|
|
134
|
+
|
|
135
|
+
Entry files are emitted without hashes (`index.js`, `auth.js`, `auth0.js`, `hooks.js`) for stable package exports; internal split chunks are hashed (`chunks/[name].[hash].js`). This is intentional for library consumption stability.
|
|
136
|
+
|
|
137
|
+
## TypeScript
|
|
138
|
+
|
|
139
|
+
Distributed ESM with full `.d.ts` declarations; strict types encourage safe usage. Avoid `any`; leverage `AuthContextProps` for context consumers.
|
|
140
|
+
|
|
141
|
+
## Roadmap / Ideas
|
|
142
|
+
|
|
143
|
+
- SSR helpers for preloading user session
|
|
144
|
+
- Optional cookie-based storage abstraction
|
|
145
|
+
- Enhanced role/permission model (attribute-based access)
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
MIT © gizmette.com
|
package/dist/auth.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
var Pe = Object.defineProperty;
|
|
2
2
|
var Ce = (e, t, n) => t in e ? Pe(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
|
|
3
3
|
var K = (e, t, n) => Ce(e, typeof t != "symbol" ? t + "" : t, n);
|
|
4
|
-
import { jsx as
|
|
5
|
-
import {
|
|
4
|
+
import { jsx as V } from "react/jsx-runtime";
|
|
5
|
+
import { HEADERS as ie, decodeToken as ve, JWT as T, API_TYPE as M, AUTH_TYPES as C, verifyAndExtractToken as D, pkceChallengePair as Ue } from "@versini/auth-common";
|
|
6
6
|
import De, { useSyncExternalStore as Le, useCallback as S, useEffect as ce, createContext as $e, useContext as Ke, useReducer as Ye, useRef as Ge } from "react";
|
|
7
|
-
import { AuthHookContext as
|
|
7
|
+
import { AuthHookContext as He } from "./AuthHookContext-C9a2AwWZ.js";
|
|
8
8
|
/*!
|
|
9
|
-
@versini/auth-provider v8.0.
|
|
9
|
+
@versini/auth-provider v8.0.5
|
|
10
10
|
© 2025 gizmette.com
|
|
11
11
|
*/
|
|
12
12
|
try {
|
|
13
13
|
window.__VERSINI_AUTH_CLIENT__ || (window.__VERSINI_AUTH_CLIENT__ = {
|
|
14
|
-
version: "8.0.
|
|
15
|
-
buildTime: "
|
|
14
|
+
version: "8.0.5",
|
|
15
|
+
buildTime: "09/01/2025 07:37 PM EDT",
|
|
16
16
|
homepage: "https://github.com/aversini/auth-client",
|
|
17
17
|
license: "MIT"
|
|
18
18
|
});
|
|
@@ -32,9 +32,9 @@ function F(e) {
|
|
|
32
32
|
return o;
|
|
33
33
|
}
|
|
34
34
|
function X() {
|
|
35
|
-
return
|
|
35
|
+
return Ve.stubThis(globalThis?.PublicKeyCredential !== void 0 && typeof globalThis.PublicKeyCredential == "function");
|
|
36
36
|
}
|
|
37
|
-
const
|
|
37
|
+
const Ve = {
|
|
38
38
|
stubThis: (e) => e
|
|
39
39
|
};
|
|
40
40
|
function ue(e) {
|
|
@@ -407,7 +407,7 @@ function z(e, t, n) {
|
|
|
407
407
|
throw new Error("Random bytes length must be >= 16");
|
|
408
408
|
return a[6] = a[6] & 15 | 64, a[8] = a[8] & 63 | 128, Qe(a);
|
|
409
409
|
}
|
|
410
|
-
const b = "Your session has expired. For your security, please log in again to continue.", tt = "Your session has been successfully terminated.", Q = "Login failed. Please try again.", nt = "Error getting access token, please re-authenticate.", at = "You forgot to wrap your component in <AuthProvider>.", G = "@@auth@@", U = "LOADING", x = "LOGIN", pe = "LOGOUT", L = "success", A = "failure", fe = "include", Te = "POST", ye = "application/json",
|
|
410
|
+
const b = "Your session has expired. For your security, please log in again to continue.", tt = "Your session has been successfully terminated.", Q = "Login failed. Please try again.", nt = "Error getting access token, please re-authenticate.", at = "You forgot to wrap your component in <AuthProvider>.", G = "@@auth@@", U = "LOADING", x = "LOGIN", pe = "LOGOUT", L = "success", A = "failure", fe = "include", Te = "POST", ye = "application/json", H = {
|
|
411
411
|
GET_REGISTRATION_OPTIONS: `mutation GetPasskeyRegistrationOptions(
|
|
412
412
|
$clientId: String!,
|
|
413
413
|
$username: String!,
|
|
@@ -490,19 +490,19 @@ const b = "Your session has expired. For your security, please log in again to c
|
|
|
490
490
|
}`
|
|
491
491
|
}, N = {
|
|
492
492
|
GET_REGISTRATION_OPTIONS: {
|
|
493
|
-
schema:
|
|
493
|
+
schema: H.GET_REGISTRATION_OPTIONS,
|
|
494
494
|
method: "getPasskeyRegistrationOptions"
|
|
495
495
|
},
|
|
496
496
|
VERIFY_REGISTRATION: {
|
|
497
|
-
schema:
|
|
497
|
+
schema: H.VERIFY_REGISTRATION,
|
|
498
498
|
method: "verifyPasskeyRegistration"
|
|
499
499
|
},
|
|
500
500
|
GET_AUTHENTICATION_OPTIONS: {
|
|
501
|
-
schema:
|
|
501
|
+
schema: H.GET_AUTHENTICATION_OPTIONS,
|
|
502
502
|
method: "getPasskeyAuthenticationOptions"
|
|
503
503
|
},
|
|
504
504
|
VERIFY_AUTHENTICATION: {
|
|
505
|
-
schema:
|
|
505
|
+
schema: H.VERIFY_AUTHENTICATION,
|
|
506
506
|
method: "verifyPasskeyAuthentication"
|
|
507
507
|
}
|
|
508
508
|
}, k = async ({
|
|
@@ -814,7 +814,7 @@ const P = () => {
|
|
|
814
814
|
logoutReason: t.payload.logoutReason
|
|
815
815
|
} : e, Tt = ({ children: e }) => {
|
|
816
816
|
const t = ht();
|
|
817
|
-
return /* @__PURE__ */
|
|
817
|
+
return /* @__PURE__ */ V(He.Provider, { value: t, children: e });
|
|
818
818
|
}, wt = ({
|
|
819
819
|
children: e,
|
|
820
820
|
sessionExpiration: t,
|
|
@@ -1083,7 +1083,7 @@ const P = () => {
|
|
|
1083
1083
|
}
|
|
1084
1084
|
return !1;
|
|
1085
1085
|
};
|
|
1086
|
-
return /* @__PURE__ */
|
|
1086
|
+
return /* @__PURE__ */ V(pt.Provider, { value: { state: c, dispatch: r }, children: /* @__PURE__ */ V(
|
|
1087
1087
|
me.Provider,
|
|
1088
1088
|
{
|
|
1089
1089
|
value: {
|
|
@@ -1095,7 +1095,7 @@ const P = () => {
|
|
|
1095
1095
|
registeringForPasskey: be,
|
|
1096
1096
|
loginWithPasskey: Ne
|
|
1097
1097
|
},
|
|
1098
|
-
children: /* @__PURE__ */
|
|
1098
|
+
children: /* @__PURE__ */ V(Tt, { children: e })
|
|
1099
1099
|
}
|
|
1100
1100
|
) });
|
|
1101
1101
|
};
|