@autonomous-ai/auth-sdk 1.0.7
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 +300 -0
- package/dist/client.d.ts +60 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +224 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/pkce.d.ts +34 -0
- package/dist/pkce.d.ts.map +1 -0
- package/dist/pkce.js +85 -0
- package/dist/pkce.js.map +1 -0
- package/dist/react/AuthProvider.d.ts +25 -0
- package/dist/react/AuthProvider.d.ts.map +1 -0
- package/dist/react/AuthProvider.js +111 -0
- package/dist/react/AuthProvider.js.map +1 -0
- package/dist/react/index.d.ts +6 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +5 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/useAuth.d.ts +21 -0
- package/dist/react/useAuth.d.ts.map +1 -0
- package/dist/react/useAuth.js +23 -0
- package/dist/react/useAuth.js.map +1 -0
- package/dist/react/useCallback.d.ts +31 -0
- package/dist/react/useCallback.d.ts.map +1 -0
- package/dist/react/useCallback.js +78 -0
- package/dist/react/useCallback.js.map +1 -0
- package/dist/react/useUser.d.ts +22 -0
- package/dist/react/useUser.d.ts.map +1 -0
- package/dist/react/useUser.js +25 -0
- package/dist/react/useUser.js.map +1 -0
- package/dist/storage.d.ts +49 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +139 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.d.ts +157 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# @autonomous-ai/auth-sdk
|
|
2
|
+
|
|
3
|
+
Client SDK for the auth-service SSO flow — OAuth2 Authorization Code + PKCE (S256), with first-class React bindings.
|
|
4
|
+
|
|
5
|
+
- **Zero runtime dependencies** — React is an optional peer dependency
|
|
6
|
+
- **ESM only**, ships TypeScript types
|
|
7
|
+
- Automatic token refresh before expiry
|
|
8
|
+
- Post-login redirect via `nextUrl`, no server-side changes needed
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @autonomous-ai/auth-sdk
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
React is optional — only needed if you import `@autonomous-ai/auth-sdk/react`:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install react # >= 18
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Local development
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install && npm run build
|
|
26
|
+
npm link # in this repo
|
|
27
|
+
npm link @autonomous-ai/auth-sdk # in the consuming app
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Entry points
|
|
31
|
+
|
|
32
|
+
| Import path | Contents |
|
|
33
|
+
| ------------------------------- | ---------------------------------------------------- |
|
|
34
|
+
| `@autonomous-ai/auth-sdk` | `AuthClient`, `TokenManager`, PKCE helpers, all types |
|
|
35
|
+
| `@autonomous-ai/auth-sdk/react` | `AuthProvider`, `useAuth`, `useUser`, `useAuthCallback` |
|
|
36
|
+
|
|
37
|
+
## Quick Start (React)
|
|
38
|
+
|
|
39
|
+
### 1. Wrap your app with AuthProvider
|
|
40
|
+
|
|
41
|
+
Define `authConfig` outside the component (or memoize it) — a new object identity on every render re-triggers the provider's effects.
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { AuthProvider } from "@autonomous-ai/auth-sdk/react";
|
|
45
|
+
|
|
46
|
+
const authConfig = {
|
|
47
|
+
ssoUrl: "https://sso.example.com",
|
|
48
|
+
clientId: "my-app",
|
|
49
|
+
redirectUri: "https://app.example.com/callback",
|
|
50
|
+
scope: "openid profile email",
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function App() {
|
|
54
|
+
return (
|
|
55
|
+
<AuthProvider config={authConfig}>
|
|
56
|
+
<YourApp />
|
|
57
|
+
</AuthProvider>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 2. Use the hooks
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { useAuth, useUser } from "@autonomous-ai/auth-sdk/react";
|
|
66
|
+
|
|
67
|
+
function LoginButton() {
|
|
68
|
+
const { isAuthenticated, login, logout, isLoading } = useAuth();
|
|
69
|
+
|
|
70
|
+
if (isLoading) return <div>Loading...</div>;
|
|
71
|
+
|
|
72
|
+
if (isAuthenticated) {
|
|
73
|
+
return <button onClick={() => logout()}>Logout</button>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return <button onClick={() => login()}>Login with SSO</button>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function UserProfile() {
|
|
80
|
+
const user = useUser();
|
|
81
|
+
|
|
82
|
+
if (!user) return null;
|
|
83
|
+
|
|
84
|
+
return <p>Welcome, {user.fullName || user.email}!</p>;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 3. Handle the OAuth2 callback
|
|
89
|
+
|
|
90
|
+
Mount this on the route you registered as `redirectUri`. The hook reads `code` / `state` from the URL, exchanges them for tokens, and is guarded against React StrictMode double-invocation.
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { useEffect } from "react";
|
|
94
|
+
import { useAuthCallback, useAuth } from "@autonomous-ai/auth-sdk/react";
|
|
95
|
+
import { useNavigate } from "react-router-dom";
|
|
96
|
+
|
|
97
|
+
function CallbackPage() {
|
|
98
|
+
const navigate = useNavigate();
|
|
99
|
+
const { refreshAuthState } = useAuth();
|
|
100
|
+
const { isLoading, error, success, nextUrl } = useAuthCallback(authConfig);
|
|
101
|
+
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (success) {
|
|
104
|
+
refreshAuthState(); // re-read tokens written by the callback
|
|
105
|
+
navigate(nextUrl || "/");
|
|
106
|
+
}
|
|
107
|
+
}, [success, nextUrl, navigate, refreshAuthState]);
|
|
108
|
+
|
|
109
|
+
if (isLoading) return <div>Processing login...</div>;
|
|
110
|
+
if (error) return <div>Login failed: {error}</div>;
|
|
111
|
+
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 4. Post-login redirect (`nextUrl`)
|
|
117
|
+
|
|
118
|
+
Pass `nextUrl` to `login()` to send the user back to the page they started from. It is stored in `sessionStorage` before the SSO redirect and returned by `useAuthCallback` after a successful exchange.
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
import { useEffect } from "react";
|
|
122
|
+
import { useAuth } from "@autonomous-ai/auth-sdk/react";
|
|
123
|
+
import { useLocation } from "react-router-dom";
|
|
124
|
+
|
|
125
|
+
function ProtectedPage() {
|
|
126
|
+
const location = useLocation();
|
|
127
|
+
const { isAuthenticated, isLoading, login } = useAuth();
|
|
128
|
+
|
|
129
|
+
useEffect(() => {
|
|
130
|
+
if (!isLoading && !isAuthenticated) {
|
|
131
|
+
login({
|
|
132
|
+
nextUrl: `${location.pathname}${location.search}${location.hash}`,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}, [isAuthenticated, isLoading, login, location]);
|
|
136
|
+
|
|
137
|
+
if (isLoading || !isAuthenticated) {
|
|
138
|
+
return <div>Redirecting to login...</div>;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return <div>Protected content</div>;
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Vanilla JavaScript / TypeScript
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import { AuthClient } from "@autonomous-ai/auth-sdk";
|
|
149
|
+
|
|
150
|
+
const client = new AuthClient({
|
|
151
|
+
ssoUrl: "https://sso.example.com",
|
|
152
|
+
clientId: "my-app",
|
|
153
|
+
redirectUri: "https://app.example.com/callback",
|
|
154
|
+
scope: "openid profile email",
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Start login (redirects the browser to SSO)
|
|
158
|
+
await client.authorize({ nextUrl: "/dashboard" });
|
|
159
|
+
|
|
160
|
+
// On the callback page
|
|
161
|
+
const params = new URLSearchParams(window.location.search);
|
|
162
|
+
const result = await client.handleCallback(
|
|
163
|
+
params.get("code")!,
|
|
164
|
+
params.get("state")!
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
if (result.success) {
|
|
168
|
+
if (result.nextUrl) window.location.href = result.nextUrl;
|
|
169
|
+
} else {
|
|
170
|
+
console.error(result.error);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Auth status
|
|
174
|
+
if (client.isAuthenticated()) {
|
|
175
|
+
console.log("User:", client.getUser());
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Access token for API calls — refreshes automatically if expired
|
|
179
|
+
const token = await client.getValidAccessToken();
|
|
180
|
+
await fetch("/api/me", { headers: { Authorization: `Bearer ${token}` } });
|
|
181
|
+
|
|
182
|
+
// Logout (clears tokens and redirects to SSO logout)
|
|
183
|
+
client.logout();
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## API Reference
|
|
187
|
+
|
|
188
|
+
### AuthClient
|
|
189
|
+
|
|
190
|
+
| Method | Returns | Description |
|
|
191
|
+
| ------------------------------- | -------------------------- | ---------------------------------------- |
|
|
192
|
+
| `authorize(options?)` | `Promise<void>` | Start OAuth2 login flow (redirects away) |
|
|
193
|
+
| `handleCallback(code, state)` | `Promise<CallbackResult>` | Exchange authorization code for tokens |
|
|
194
|
+
| `refreshToken()` | `Promise<TokenResponse>` | Refresh the access token |
|
|
195
|
+
| `logout(redirectUri?)` | `void` | Clear tokens and redirect to SSO logout |
|
|
196
|
+
| `isAuthenticated()` | `boolean` | Whether a valid session exists |
|
|
197
|
+
| `getAccessToken()` | `string \| null` | Current access token |
|
|
198
|
+
| `getRefreshToken()` | `string \| null` | Current refresh token |
|
|
199
|
+
| `getUser()` | `User \| null` | User decoded from the JWT |
|
|
200
|
+
| `isTokenExpired(buffer = 60)` | `boolean` | Expiry check with a seconds buffer |
|
|
201
|
+
| `getValidAccessToken()` | `Promise<string>` | Token, refreshed if expired |
|
|
202
|
+
| `clearTokens()` | `void` | Clear tokens without an SSO logout |
|
|
203
|
+
|
|
204
|
+
`createAuthClient(config)` is a factory shorthand for `new AuthClient(config)`.
|
|
205
|
+
|
|
206
|
+
### AuthConfig
|
|
207
|
+
|
|
208
|
+
| Option | Type | Default | Description |
|
|
209
|
+
| ------------- | -------------- | ---------------- | ------------------------------------ |
|
|
210
|
+
| `ssoUrl` | `string` | required | SSO server base URL |
|
|
211
|
+
| `clientId` | `string` | required | OAuth2 client ID |
|
|
212
|
+
| `redirectUri` | `string` | required | Callback URL registered with the SSO |
|
|
213
|
+
| `scope` | `string?` | - | Space-separated scopes |
|
|
214
|
+
| `storage` | `TokenStorage?` | `localStorage` | Custom token storage |
|
|
215
|
+
|
|
216
|
+
### AuthorizeOptions
|
|
217
|
+
|
|
218
|
+
| Option | Type | Description |
|
|
219
|
+
| ----------- | --------------------------------------- | ----------------------------------------- |
|
|
220
|
+
| `prompt` | `'select_account' \| 'none' \| 'login'` | Force account selection or silent auth |
|
|
221
|
+
| `loginHint` | `string` | Pre-fill email for login |
|
|
222
|
+
| `nextUrl` | `string` | URL to redirect to after successful login |
|
|
223
|
+
|
|
224
|
+
### User
|
|
225
|
+
|
|
226
|
+
Parsed from the JWT's `ext_info` claim.
|
|
227
|
+
|
|
228
|
+
| Field | Type | Description |
|
|
229
|
+
| -------------------- | ----------- | ------------------------- |
|
|
230
|
+
| `id` | `string` | User ID |
|
|
231
|
+
| `email` | `string` | User email |
|
|
232
|
+
| `fullName` | `string?` | Full name |
|
|
233
|
+
| `code` | `string?` | User code |
|
|
234
|
+
| `roles` | `string[]?` | User roles |
|
|
235
|
+
| `scope` | `string?` | Granted scope |
|
|
236
|
+
| `companyDomain` | `string?` | Company domain |
|
|
237
|
+
| `companyDomainType` | `string?` | Company domain type |
|
|
238
|
+
| `isEppUser` | `boolean?` | Employee Purchase Program |
|
|
239
|
+
| `vendorId` | `string?` | Vendor ID |
|
|
240
|
+
| `vendorCode` | `string?` | Vendor code |
|
|
241
|
+
| `vendorName` | `string?` | Vendor name |
|
|
242
|
+
| `referralCode` | `string?` | Referral code |
|
|
243
|
+
|
|
244
|
+
### CallbackResult
|
|
245
|
+
|
|
246
|
+
| Field | Type | Description |
|
|
247
|
+
| --------- | ----------------- | -------------------------------------- |
|
|
248
|
+
| `success` | `boolean` | Whether the code exchange succeeded |
|
|
249
|
+
| `tokens` | `TokenResponse?` | Tokens returned by auth-service |
|
|
250
|
+
| `error` | `string?` | Error message when `success` is false |
|
|
251
|
+
| `nextUrl` | `string?` | Post-login redirect target |
|
|
252
|
+
|
|
253
|
+
### React hooks
|
|
254
|
+
|
|
255
|
+
| Hook | Returns | Description |
|
|
256
|
+
| ------------------------- | ----------------------------------------------------------- | ---------------------- |
|
|
257
|
+
| `useAuth()` | `AuthContextValue` | Auth state and actions |
|
|
258
|
+
| `useUser()` | `User \| null` | Current user |
|
|
259
|
+
| `useAuthCallback(config)` | `{ isLoading, error, success, result, nextUrl }` | Handle OAuth2 callback |
|
|
260
|
+
|
|
261
|
+
`useAuth()` returns `isAuthenticated`, `isLoading`, `user`, `error`, plus `login()`, `logout()`, `getAccessToken()`, `refreshToken()` and `refreshAuthState()`.
|
|
262
|
+
|
|
263
|
+
`useAuthCallback` creates its own `AuthClient` and works outside `AuthProvider` — but call `refreshAuthState()` afterwards so the provider picks up the new tokens.
|
|
264
|
+
|
|
265
|
+
### AuthProvider props
|
|
266
|
+
|
|
267
|
+
| Prop | Type | Default | Description |
|
|
268
|
+
| --------------- | ------------ | -------- | -------------------------------- |
|
|
269
|
+
| `config` | `AuthConfig` | required | Auth configuration |
|
|
270
|
+
| `autoRefresh` | `boolean` | `true` | Auto-refresh tokens |
|
|
271
|
+
| `refreshBuffer` | `number` | `60` | Seconds before expiry to refresh |
|
|
272
|
+
| `onAuthChange` | `function` | - | Called on auth state change |
|
|
273
|
+
|
|
274
|
+
## Custom storage
|
|
275
|
+
|
|
276
|
+
Tokens go to `localStorage` by default. Supply any object implementing `TokenStorage` to change that — e.g. `sessionStorage` so the session dies with the tab:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
const client = new AuthClient({
|
|
280
|
+
...config,
|
|
281
|
+
storage: {
|
|
282
|
+
getItem: (key) => sessionStorage.getItem(key),
|
|
283
|
+
setItem: (key, value) => sessionStorage.setItem(key, value),
|
|
284
|
+
removeItem: (key) => sessionStorage.removeItem(key),
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
The PKCE verifier and `state` always use `sessionStorage`, regardless of this setting.
|
|
290
|
+
|
|
291
|
+
## Security
|
|
292
|
+
|
|
293
|
+
- PKCE (S256) prevents authorization code interception
|
|
294
|
+
- `state` parameter for CSRF protection, validated on callback
|
|
295
|
+
- PKCE verifier kept in `sessionStorage`, never in `localStorage`
|
|
296
|
+
- Tokens refreshed automatically before expiry (`refreshBuffer`)
|
|
297
|
+
|
|
298
|
+
## License
|
|
299
|
+
|
|
300
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { AuthConfig, AuthorizeOptions, CallbackResult, TokenResponse, User } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Auth Client for OAuth2 SSO flow with PKCE
|
|
4
|
+
*/
|
|
5
|
+
export declare class AuthClient {
|
|
6
|
+
private config;
|
|
7
|
+
private tokenManager;
|
|
8
|
+
constructor(config: AuthConfig);
|
|
9
|
+
/**
|
|
10
|
+
* Start OAuth2 authorization flow with PKCE
|
|
11
|
+
* Redirects the browser to SSO login page
|
|
12
|
+
*/
|
|
13
|
+
authorize(options?: AuthorizeOptions): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Handle OAuth2 callback - exchange code for tokens
|
|
16
|
+
* Call this from your callback page
|
|
17
|
+
*/
|
|
18
|
+
handleCallback(code: string, state: string): Promise<CallbackResult>;
|
|
19
|
+
/**
|
|
20
|
+
* Refresh access token using refresh token
|
|
21
|
+
*/
|
|
22
|
+
refreshToken(): Promise<TokenResponse>;
|
|
23
|
+
/**
|
|
24
|
+
* Logout - clears tokens and redirects to SSO logout
|
|
25
|
+
*/
|
|
26
|
+
logout(redirectUri?: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Check if user is authenticated
|
|
29
|
+
*/
|
|
30
|
+
isAuthenticated(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Get current access token
|
|
33
|
+
*/
|
|
34
|
+
getAccessToken(): string | null;
|
|
35
|
+
/**
|
|
36
|
+
* Get current refresh token
|
|
37
|
+
*/
|
|
38
|
+
getRefreshToken(): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Get user info from current token
|
|
41
|
+
*/
|
|
42
|
+
getUser(): User | null;
|
|
43
|
+
/**
|
|
44
|
+
* Check if token is expired or about to expire
|
|
45
|
+
*/
|
|
46
|
+
isTokenExpired(bufferSeconds?: number): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Get a valid access token, refreshing if needed
|
|
49
|
+
*/
|
|
50
|
+
getValidAccessToken(): Promise<string>;
|
|
51
|
+
/**
|
|
52
|
+
* Clear all stored tokens (local logout without SSO redirect)
|
|
53
|
+
*/
|
|
54
|
+
clearTokens(): void;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create a new AuthClient instance
|
|
58
|
+
*/
|
|
59
|
+
export declare function createAuthClient(config: AuthConfig): AuthClient;
|
|
60
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,IAAI,EACL,MAAM,SAAS,CAAC;AAGjB;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,YAAY,CAAe;gBAEvB,MAAM,EAAE,UAAU;IAS9B;;;OAGG;IACG,SAAS,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC1D;;;OAGG;IACG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAqE1E;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,aAAa,CAAC;IAiC5C;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAqBlC;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC;;OAEG;IACH,OAAO,IAAI,IAAI,GAAG,IAAI;IAItB;;OAEG;IACH,cAAc,CAAC,aAAa,GAAE,MAAW,GAAG,OAAO;IAInD;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC;IAa5C;;OAEG;IACH,WAAW,IAAI,IAAI;CAIpB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAE/D"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { generateCodeChallenge, generateCodeVerifier, generateState, pkceStorage } from './pkce';
|
|
2
|
+
import { TokenManager, defaultStorage } from './storage';
|
|
3
|
+
import { SDK_VERSION } from './version';
|
|
4
|
+
/**
|
|
5
|
+
* Auth Client for OAuth2 SSO flow with PKCE
|
|
6
|
+
*/
|
|
7
|
+
export class AuthClient {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.config = {
|
|
10
|
+
scope: 'openid profile email',
|
|
11
|
+
storage: defaultStorage,
|
|
12
|
+
...config,
|
|
13
|
+
};
|
|
14
|
+
this.tokenManager = new TokenManager(this.config.storage);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Start OAuth2 authorization flow with PKCE
|
|
18
|
+
* Redirects the browser to SSO login page
|
|
19
|
+
*/
|
|
20
|
+
async authorize(options) {
|
|
21
|
+
// Generate and store PKCE code verifier
|
|
22
|
+
const codeVerifier = generateCodeVerifier();
|
|
23
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
24
|
+
pkceStorage.setCodeVerifier(codeVerifier);
|
|
25
|
+
// Generate and store state for CSRF protection
|
|
26
|
+
const state = generateState();
|
|
27
|
+
pkceStorage.setState(state);
|
|
28
|
+
// Build authorization URL
|
|
29
|
+
const params = new URLSearchParams({
|
|
30
|
+
response_type: 'code',
|
|
31
|
+
client_id: this.config.clientId,
|
|
32
|
+
redirect_uri: this.config.redirectUri,
|
|
33
|
+
scope: this.config.scope,
|
|
34
|
+
state: state,
|
|
35
|
+
code_challenge: codeChallenge,
|
|
36
|
+
code_challenge_method: 'S256',
|
|
37
|
+
autonomous_sdk_version: SDK_VERSION,
|
|
38
|
+
});
|
|
39
|
+
// Store next URL for post-login redirect
|
|
40
|
+
if (options?.nextUrl) {
|
|
41
|
+
pkceStorage.setNextUrl(options.nextUrl);
|
|
42
|
+
}
|
|
43
|
+
// Add optional parameters
|
|
44
|
+
if (options?.prompt) {
|
|
45
|
+
params.set('prompt', options.prompt);
|
|
46
|
+
}
|
|
47
|
+
if (options?.loginHint) {
|
|
48
|
+
params.set('login_hint', options.loginHint);
|
|
49
|
+
}
|
|
50
|
+
// Redirect to SSO authorization endpoint
|
|
51
|
+
window.location.href = `${this.config.ssoUrl}/oauth2/authorize?${params.toString()}`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Handle OAuth2 callback - exchange code for tokens
|
|
55
|
+
* Call this from your callback page
|
|
56
|
+
*/
|
|
57
|
+
async handleCallback(code, state) {
|
|
58
|
+
try {
|
|
59
|
+
// Verify state to prevent CSRF
|
|
60
|
+
const storedState = pkceStorage.getState();
|
|
61
|
+
if (!storedState || storedState !== state) {
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
error: 'Invalid state parameter - possible CSRF attack',
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// Get PKCE code verifier
|
|
68
|
+
const codeVerifier = pkceStorage.getCodeVerifier();
|
|
69
|
+
if (!codeVerifier) {
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
error: 'Missing code verifier - PKCE flow incomplete',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// Exchange code for tokens
|
|
76
|
+
const response = await fetch(`${this.config.ssoUrl}/oauth2/token`, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
headers: {
|
|
79
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
80
|
+
},
|
|
81
|
+
body: new URLSearchParams({
|
|
82
|
+
grant_type: 'authorization_code',
|
|
83
|
+
code: code,
|
|
84
|
+
redirect_uri: this.config.redirectUri,
|
|
85
|
+
client_id: this.config.clientId,
|
|
86
|
+
code_verifier: codeVerifier,
|
|
87
|
+
autonomous_sdk_version: SDK_VERSION,
|
|
88
|
+
}),
|
|
89
|
+
});
|
|
90
|
+
// Get next URL before clearing PKCE storage
|
|
91
|
+
const nextUrl = pkceStorage.getNextUrl() || undefined;
|
|
92
|
+
// Clear PKCE storage after use
|
|
93
|
+
pkceStorage.clear();
|
|
94
|
+
const result = await response.json();
|
|
95
|
+
// Check for OAuth2 error response
|
|
96
|
+
if (!result.access_token) {
|
|
97
|
+
return {
|
|
98
|
+
success: false,
|
|
99
|
+
error: 'Token exchange failed',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// Store tokens
|
|
103
|
+
this.tokenManager.setTokens(result);
|
|
104
|
+
return {
|
|
105
|
+
success: true,
|
|
106
|
+
tokens: result,
|
|
107
|
+
nextUrl,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
pkceStorage.clear();
|
|
112
|
+
return {
|
|
113
|
+
success: false,
|
|
114
|
+
error: err instanceof Error ? err.message : 'Unknown error during callback',
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Refresh access token using refresh token
|
|
120
|
+
*/
|
|
121
|
+
async refreshToken() {
|
|
122
|
+
const refreshToken = this.tokenManager.getRefreshToken();
|
|
123
|
+
if (!refreshToken) {
|
|
124
|
+
throw new Error('No refresh token available');
|
|
125
|
+
}
|
|
126
|
+
const response = await fetch(`${this.config.ssoUrl}/oauth2/token`, {
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: {
|
|
129
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
130
|
+
},
|
|
131
|
+
body: new URLSearchParams({
|
|
132
|
+
grant_type: 'refresh_token',
|
|
133
|
+
refresh_token: refreshToken,
|
|
134
|
+
client_id: this.config.clientId,
|
|
135
|
+
autonomous_sdk_version: SDK_VERSION,
|
|
136
|
+
}),
|
|
137
|
+
});
|
|
138
|
+
const result = await response.json();
|
|
139
|
+
// Check for OAuth2 error response
|
|
140
|
+
if (!result.access_token) {
|
|
141
|
+
// Clear tokens on refresh failure
|
|
142
|
+
this.tokenManager.clearTokens();
|
|
143
|
+
throw new Error('Token refresh failed');
|
|
144
|
+
}
|
|
145
|
+
this.tokenManager.setTokens(result);
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Logout - clears tokens and redirects to SSO logout
|
|
150
|
+
*/
|
|
151
|
+
logout(redirectUri) {
|
|
152
|
+
const postLogoutRedirectUri = redirectUri || window.location.origin;
|
|
153
|
+
const idToken = this.tokenManager.getAccessToken();
|
|
154
|
+
// Clear local tokens
|
|
155
|
+
this.tokenManager.clearTokens();
|
|
156
|
+
pkceStorage.clear();
|
|
157
|
+
// Build logout URL
|
|
158
|
+
const params = new URLSearchParams({
|
|
159
|
+
post_logout_redirect_uri: postLogoutRedirectUri,
|
|
160
|
+
});
|
|
161
|
+
if (idToken) {
|
|
162
|
+
params.set('id_token_hint', idToken);
|
|
163
|
+
}
|
|
164
|
+
// Redirect to SSO logout endpoint
|
|
165
|
+
window.location.href = `${this.config.ssoUrl}/oauth2/logout?${params.toString()}`;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Check if user is authenticated
|
|
169
|
+
*/
|
|
170
|
+
isAuthenticated() {
|
|
171
|
+
return this.tokenManager.isAuthenticated();
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get current access token
|
|
175
|
+
*/
|
|
176
|
+
getAccessToken() {
|
|
177
|
+
return this.tokenManager.getAccessToken();
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get current refresh token
|
|
181
|
+
*/
|
|
182
|
+
getRefreshToken() {
|
|
183
|
+
return this.tokenManager.getRefreshToken();
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Get user info from current token
|
|
187
|
+
*/
|
|
188
|
+
getUser() {
|
|
189
|
+
return this.tokenManager.getUser();
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Check if token is expired or about to expire
|
|
193
|
+
*/
|
|
194
|
+
isTokenExpired(bufferSeconds = 60) {
|
|
195
|
+
return this.tokenManager.isTokenExpired(bufferSeconds);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Get a valid access token, refreshing if needed
|
|
199
|
+
*/
|
|
200
|
+
async getValidAccessToken() {
|
|
201
|
+
if (this.isTokenExpired()) {
|
|
202
|
+
await this.refreshToken();
|
|
203
|
+
}
|
|
204
|
+
const token = this.getAccessToken();
|
|
205
|
+
if (!token) {
|
|
206
|
+
throw new Error('No access token available');
|
|
207
|
+
}
|
|
208
|
+
return token;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Clear all stored tokens (local logout without SSO redirect)
|
|
212
|
+
*/
|
|
213
|
+
clearTokens() {
|
|
214
|
+
this.tokenManager.clearTokens();
|
|
215
|
+
pkceStorage.clear();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Create a new AuthClient instance
|
|
220
|
+
*/
|
|
221
|
+
export function createAuthClient(config) {
|
|
222
|
+
return new AuthClient(config);
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { AuthClient, createAuthClient } from './client';
|
|
2
|
+
export { TokenManager, defaultStorage } from './storage';
|
|
3
|
+
export { generateCodeVerifier, generateCodeChallenge, generateState, pkceStorage, } from './pkce';
|
|
4
|
+
export type { AuthConfig, TokenStorage, AuthorizeOptions, TokenResponse, OAuth2Error, ApiResponse, JwtPayload, JwtExtInfo, User, AuthState, AuthContextValue, CallbackResult, } from './types';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,EACb,WAAW,GACZ,MAAM,QAAQ,CAAC;AAGhB,YAAY,EACV,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,EACV,IAAI,EACJ,SAAS,EACT,gBAAgB,EAChB,cAAc,GACf,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,EACb,WAAW,GACZ,MAAM,QAAQ,CAAC"}
|
package/dist/pkce.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PKCE (Proof Key for Code Exchange) utilities
|
|
3
|
+
* Implements RFC 7636 for OAuth2 authorization code flow security
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generate a cryptographically random code verifier (43-128 chars)
|
|
7
|
+
*/
|
|
8
|
+
export declare function generateCodeVerifier(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Generate code challenge from verifier using SHA-256 (S256 method)
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateCodeChallenge(verifier: string): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Generate random state for CSRF protection
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateState(): string;
|
|
17
|
+
/**
|
|
18
|
+
* PKCE and state storage using sessionStorage
|
|
19
|
+
* (More secure than localStorage for PKCE verifier)
|
|
20
|
+
*/
|
|
21
|
+
export declare const pkceStorage: {
|
|
22
|
+
setCodeVerifier(verifier: string): void;
|
|
23
|
+
getCodeVerifier(): string | null;
|
|
24
|
+
clearCodeVerifier(): void;
|
|
25
|
+
setState(state: string): void;
|
|
26
|
+
getState(): string | null;
|
|
27
|
+
clearState(): void;
|
|
28
|
+
setNextUrl(url: string): void;
|
|
29
|
+
getNextUrl(): string | null;
|
|
30
|
+
clearNextUrl(): void;
|
|
31
|
+
/** Clear all PKCE-related data */
|
|
32
|
+
clear(): void;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=pkce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../src/pkce.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAI7C;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK7E;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAgBD;;;GAGG;AACH,eAAO,MAAM,WAAW;8BACI,MAAM,GAAG,IAAI;uBAIpB,MAAM,GAAG,IAAI;yBAIX,IAAI;oBAIT,MAAM,GAAG,IAAI;gBAIjB,MAAM,GAAG,IAAI;kBAIX,IAAI;oBAIF,MAAM,GAAG,IAAI;kBAIf,MAAM,GAAG,IAAI;oBAIX,IAAI;IAIpB,kCAAkC;aACzB,IAAI;CAKd,CAAC"}
|