tokenidp-react 0.3.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 +170 -0
- package/dist/index.css +50 -0
- package/dist/index.css.map +1 -0
- package/dist/index.js +724 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +691 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# TokenIDP React SDK
|
|
2
|
+
|
|
3
|
+
Official React SDK for integrating TokenIDP OAuth and OpenID Connect authentication into React applications.
|
|
4
|
+
|
|
5
|
+
The SDK handles Authorization Code + PKCE, OAuth callback processing, token persistence, refresh-token rotation, logout and revocation, hosted-login redirects, auth state, and tenant propagation.
|
|
6
|
+
|
|
7
|
+
## Package
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install tokenidp-react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
For local development from this repository:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd sdks/react-idp-sdk
|
|
17
|
+
npm install
|
|
18
|
+
npm run build
|
|
19
|
+
npm run pack
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Then install the generated `.tgz` in a React app.
|
|
23
|
+
|
|
24
|
+
## Exports
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import {
|
|
28
|
+
AuthCallback,
|
|
29
|
+
IdpAuthProvider,
|
|
30
|
+
LoginPage,
|
|
31
|
+
defaultAuthConfig,
|
|
32
|
+
useAuth,
|
|
33
|
+
} from "tokenidp-react";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Configure Auth
|
|
37
|
+
|
|
38
|
+
Wrap the app with `IdpAuthProvider`.
|
|
39
|
+
|
|
40
|
+
```jsx
|
|
41
|
+
import { IdpAuthProvider } from "tokenidp-react";
|
|
42
|
+
|
|
43
|
+
export function Root() {
|
|
44
|
+
return (
|
|
45
|
+
<IdpAuthProvider
|
|
46
|
+
config={{
|
|
47
|
+
authority: "https://idp.example.com",
|
|
48
|
+
clientId: "react-client",
|
|
49
|
+
redirectUri: `${window.location.origin}/auth/callback`,
|
|
50
|
+
postLoginRedirectUri: "/dashboard",
|
|
51
|
+
postLogoutRedirectUri: "/login?logged_out=1",
|
|
52
|
+
scope: "openid profile offline_access",
|
|
53
|
+
storage: "sessionStorage",
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
<App />
|
|
57
|
+
</IdpAuthProvider>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Required values:
|
|
63
|
+
|
|
64
|
+
- `authority`
|
|
65
|
+
- `clientId`
|
|
66
|
+
- `redirectUri`
|
|
67
|
+
|
|
68
|
+
Common optional values:
|
|
69
|
+
|
|
70
|
+
- `scope`, default `openid profile offline_access`
|
|
71
|
+
- `audience`
|
|
72
|
+
- `postLoginRedirectUri`, default `/`
|
|
73
|
+
- `postLogoutRedirectUri`, default `/login`
|
|
74
|
+
- `storage`, one of `memory`, `sessionStorage`, or `localStorage`
|
|
75
|
+
- `autoRefresh`, default `true`
|
|
76
|
+
- `refreshSkewSeconds`, default `180`
|
|
77
|
+
|
|
78
|
+
## Routes
|
|
79
|
+
|
|
80
|
+
Add a login route and callback route with React Router.
|
|
81
|
+
|
|
82
|
+
```jsx
|
|
83
|
+
import { AuthCallback, LoginPage } from "tokenidp-react";
|
|
84
|
+
|
|
85
|
+
<Routes>
|
|
86
|
+
<Route path="/login" element={<LoginPage />} />
|
|
87
|
+
<Route path="/auth/callback" element={<AuthCallback />} />
|
|
88
|
+
</Routes>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`LoginPage` automatically redirects to TokenIDP unless the URL contains `logged_out=1`, in which case it shows a signed-out state and a sign-in button.
|
|
92
|
+
|
|
93
|
+
`AuthCallback` reads `code` and `state`, validates OAuth state, exchanges the code for tokens, stores the session, and navigates to `postLoginRedirectUri` unless `redirectTo` is supplied.
|
|
94
|
+
|
|
95
|
+
## Use Auth State
|
|
96
|
+
|
|
97
|
+
```jsx
|
|
98
|
+
import { useAuth } from "tokenidp-react";
|
|
99
|
+
|
|
100
|
+
export function LoginButton() {
|
|
101
|
+
const auth = useAuth();
|
|
102
|
+
|
|
103
|
+
if (auth.isAuthenticated) {
|
|
104
|
+
return <button onClick={auth.logout}>Logout</button>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return <button onClick={() => auth.login()}>Login</button>;
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The `useAuth()` value includes:
|
|
112
|
+
|
|
113
|
+
- `isAuthenticated`
|
|
114
|
+
- `tenantKey`
|
|
115
|
+
- `landingPage`
|
|
116
|
+
- `accessToken`
|
|
117
|
+
- `refreshToken`
|
|
118
|
+
- `idToken`
|
|
119
|
+
- `expiresAt`
|
|
120
|
+
- `error`
|
|
121
|
+
- `login(options)`
|
|
122
|
+
- `logout()`
|
|
123
|
+
- `handleCallback({ code, state })`
|
|
124
|
+
- `refresh()`
|
|
125
|
+
- `setError(message)`
|
|
126
|
+
|
|
127
|
+
## Login Options
|
|
128
|
+
|
|
129
|
+
`login(options)` supports:
|
|
130
|
+
|
|
131
|
+
- `prompt`
|
|
132
|
+
- `loginHint`
|
|
133
|
+
- `audience`
|
|
134
|
+
- `tenantKey`
|
|
135
|
+
|
|
136
|
+
```jsx
|
|
137
|
+
auth.login({
|
|
138
|
+
loginHint: "user@example.com",
|
|
139
|
+
tenantKey: "tenant-a",
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Tenant Propagation
|
|
144
|
+
|
|
145
|
+
Tenant propagation is controlled by:
|
|
146
|
+
|
|
147
|
+
- `tenantKey`
|
|
148
|
+
- `tenantPropagationMode`: `all`, `api`, or `none`
|
|
149
|
+
- `tenantQueryParameter`, default `tenant`
|
|
150
|
+
- `tenantHeaderName`, default `X-Tenant-Key`
|
|
151
|
+
- `tenantKeyStorageKey`, default `idp_tenant_key`
|
|
152
|
+
|
|
153
|
+
Modes:
|
|
154
|
+
|
|
155
|
+
- `all`: add tenant query parameter to hosted authorization and built-in auth endpoint calls
|
|
156
|
+
- `api`: resolve and persist tenant for application API usage without adding tenant to hosted auth endpoint calls
|
|
157
|
+
- `none`: do not resolve or propagate tenant automatically
|
|
158
|
+
|
|
159
|
+
The SDK resolves tenant key from explicit login options, provider config, the current URL query parameter, or session storage.
|
|
160
|
+
|
|
161
|
+
## Logout
|
|
162
|
+
|
|
163
|
+
`logout()` attempts to revoke the refresh token, clears the local session, and redirects to the TokenIDP logout endpoint with `client_id` and `post_logout_redirect_uri`.
|
|
164
|
+
|
|
165
|
+
## Notes
|
|
166
|
+
|
|
167
|
+
- PKCE uses `S256`.
|
|
168
|
+
- OAuth state is stored in `sessionStorage` and validated during callback handling.
|
|
169
|
+
- Refresh uses the configured refresh token and keeps the previous refresh token if the server does not return a rotated value.
|
|
170
|
+
- The SDK stores tokens according to the configured storage mode. Use `sessionStorage` or `memory` for browser clients unless the application explicitly accepts the persistence tradeoff of `localStorage`.
|
package/dist/index.css
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* src/styles/idp-default.css */
|
|
2
|
+
.login-page {
|
|
3
|
+
min-height: 100vh;
|
|
4
|
+
width: 100%;
|
|
5
|
+
display: flex;
|
|
6
|
+
align-items: center;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
background:
|
|
9
|
+
radial-gradient(
|
|
10
|
+
circle at top,
|
|
11
|
+
#eef3fb 0%,
|
|
12
|
+
#f7f9fc 45%,
|
|
13
|
+
#f1f4f9 100%);
|
|
14
|
+
}
|
|
15
|
+
.redirect-card {
|
|
16
|
+
max-width: 440px;
|
|
17
|
+
width: 100%;
|
|
18
|
+
background: #ffffff;
|
|
19
|
+
border-radius: 16px;
|
|
20
|
+
padding: 28px 24px;
|
|
21
|
+
box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08);
|
|
22
|
+
border: 1px solid #e5e7eb;
|
|
23
|
+
text-align: center;
|
|
24
|
+
}
|
|
25
|
+
.redirect-card h1 {
|
|
26
|
+
font-size: 1.6rem;
|
|
27
|
+
font-weight: 700;
|
|
28
|
+
color: #0f172a;
|
|
29
|
+
margin-bottom: 6px;
|
|
30
|
+
}
|
|
31
|
+
.redirect-card p {
|
|
32
|
+
font-size: 0.95rem;
|
|
33
|
+
color: #6b7280;
|
|
34
|
+
margin-bottom: 12px;
|
|
35
|
+
}
|
|
36
|
+
.logo {
|
|
37
|
+
width: 56px;
|
|
38
|
+
height: 56px;
|
|
39
|
+
margin: -24px auto 14px auto;
|
|
40
|
+
border-radius: 50%;
|
|
41
|
+
background: #1e3a8a;
|
|
42
|
+
color: #ffffff;
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
font-size: 26px;
|
|
47
|
+
box-shadow: 0 10px 24px rgba(30, 58, 138, 0.25);
|
|
48
|
+
border: 4px solid #ffffff;
|
|
49
|
+
}
|
|
50
|
+
/*# sourceMappingURL=index.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/styles/idp-default.css"],"sourcesContent":["/* Page background (same as /authorize) */\r\n.login-page {\r\n min-height: 100vh;\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: radial-gradient(\r\n circle at top,\r\n #eef3fb 0%,\r\n #f7f9fc 45%,\r\n #f1f4f9 100%\r\n );\r\n}\r\n\r\n/* Card container */\r\n.redirect-card {\r\n max-width: 440px;\r\n width: 100%;\r\n background: #ffffff;\r\n border-radius: 16px;\r\n padding: 28px 24px;\r\n box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08);\r\n border: 1px solid #e5e7eb;\r\n text-align: center;\r\n}\r\n\r\n/* Title */\r\n.redirect-card h1 {\r\n font-size: 1.6rem;\r\n font-weight: 700;\r\n color: #0f172a;\r\n margin-bottom: 6px;\r\n}\r\n\r\n/* Subtext */\r\n.redirect-card p {\r\n font-size: 0.95rem;\r\n color: #6b7280;\r\n margin-bottom: 12px;\r\n}\r\n\r\n/* Logo badge */\r\n.logo {\r\n width: 56px;\r\n height: 56px;\r\n margin: -24px auto 14px auto; /* slightly floating but not too much */\r\n border-radius: 50%;\r\n background: #1e3a8a;\r\n color: #ffffff;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 26px;\r\n box-shadow: 0 10px 24px rgba(30, 58, 138, 0.25);\r\n border: 4px solid #ffffff; /* nice layered effect */\r\n}\r\n"],"mappings":";AACA,CAAC;AACC,cAAY;AACZ,SAAO;AACP,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB;AAAA,IAAY;AAAA,MACV,OAAO,GAAG,GADA;AAAA,MAEV,QAAQ,EAFE;AAAA,MAGV,QAAQ,GAHE;AAAA,MAIV,QAAQ;AAEZ;AAGA,CAAC;AACC,aAAW;AACX,SAAO;AACP,cAAY;AACZ,iBAAe;AACf,WAAS,KAAK;AACd,cAAY,EAAE,KAAK,KAAK,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;AACzC,UAAQ,IAAI,MAAM;AAClB,cAAY;AACd;AAGA,CAZC,cAYc;AACb,aAAW;AACX,eAAa;AACb,SAAO;AACP,iBAAe;AACjB;AAGA,CApBC,cAoBc;AACb,aAAW;AACX,SAAO;AACP,iBAAe;AACjB;AAGA,CAAC;AACC,SAAO;AACP,UAAQ;AACR,UAAQ,MAAM,KAAK,KAAK;AACxB,iBAAe;AACf,cAAY;AACZ,SAAO;AACP,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,aAAW;AACX,cAAY,EAAE,KAAK,KAAK,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE;AAC1C,UAAQ,IAAI,MAAM;AACpB;","names":[]}
|