@douvery/auth 0.1.0
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 +231 -0
- package/dist/index.d.ts +352 -0
- package/dist/index.js +722 -0
- package/dist/index.js.map +1 -0
- package/package.json +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# @douvery/auth
|
|
2
|
+
|
|
3
|
+
OAuth 2.0/OIDC client library for Douvery authentication.
|
|
4
|
+
|
|
5
|
+
## Packages
|
|
6
|
+
|
|
7
|
+
| Package | Description |
|
|
8
|
+
|---------|-------------|
|
|
9
|
+
| [@douvery/auth](./packages/core) | Core client library (vanilla TypeScript) |
|
|
10
|
+
| [@douvery/auth-react](./packages/react) | React hooks and components |
|
|
11
|
+
| [@douvery/auth-qwik](./packages/qwik) | Qwik hooks and components |
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
### React
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @douvery/auth-react
|
|
19
|
+
# or
|
|
20
|
+
pnpm add @douvery/auth-react
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Qwik
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @douvery/auth-qwik
|
|
27
|
+
# or
|
|
28
|
+
pnpm add @douvery/auth-qwik
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Vanilla TypeScript
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install @douvery/auth
|
|
35
|
+
# or
|
|
36
|
+
pnpm add @douvery/auth
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
### React
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { DouveryAuthProvider, useDouveryAuth } from '@douvery/auth-react';
|
|
45
|
+
|
|
46
|
+
// Wrap your app with the provider
|
|
47
|
+
function App() {
|
|
48
|
+
return (
|
|
49
|
+
<DouveryAuthProvider
|
|
50
|
+
config={{
|
|
51
|
+
clientId: 'your-client-id',
|
|
52
|
+
redirectUri: 'http://localhost:3000/callback',
|
|
53
|
+
issuer: 'https://auth.douvery.com',
|
|
54
|
+
scopes: ['openid', 'profile', 'email'],
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
<YourApp />
|
|
58
|
+
</DouveryAuthProvider>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Use the hook in your components
|
|
63
|
+
function LoginButton() {
|
|
64
|
+
const { login, logout, isAuthenticated, user } = useDouveryAuth();
|
|
65
|
+
|
|
66
|
+
if (isAuthenticated) {
|
|
67
|
+
return (
|
|
68
|
+
<div>
|
|
69
|
+
<p>Welcome, {user?.name}!</p>
|
|
70
|
+
<button onClick={() => logout()}>Logout</button>
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return <button onClick={() => login()}>Login</button>;
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Qwik
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { DouveryAuthProvider, useDouveryAuth } from '@douvery/auth-qwik';
|
|
83
|
+
import { component$ } from '@builder.io/qwik';
|
|
84
|
+
|
|
85
|
+
// Wrap your app with the provider
|
|
86
|
+
export default component$(() => {
|
|
87
|
+
return (
|
|
88
|
+
<DouveryAuthProvider
|
|
89
|
+
config={{
|
|
90
|
+
clientId: 'your-client-id',
|
|
91
|
+
redirectUri: 'http://localhost:5173/callback',
|
|
92
|
+
issuer: 'https://auth.douvery.com',
|
|
93
|
+
scopes: ['openid', 'profile', 'email'],
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
<Slot />
|
|
97
|
+
</DouveryAuthProvider>
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Use the hook in your components
|
|
102
|
+
export const LoginButton = component$(() => {
|
|
103
|
+
const { login, logout, isAuthenticated, user } = useDouveryAuth();
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<>
|
|
107
|
+
{isAuthenticated.value ? (
|
|
108
|
+
<div>
|
|
109
|
+
<p>Welcome, {user.value?.name}!</p>
|
|
110
|
+
<button onClick$={() => logout()}>Logout</button>
|
|
111
|
+
</div>
|
|
112
|
+
) : (
|
|
113
|
+
<button onClick$={() => login()}>Login</button>
|
|
114
|
+
)}
|
|
115
|
+
</>
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Vanilla TypeScript
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { createDouveryAuth } from '@douvery/auth';
|
|
124
|
+
|
|
125
|
+
const auth = createDouveryAuth({
|
|
126
|
+
clientId: 'your-client-id',
|
|
127
|
+
redirectUri: 'http://localhost:3000/callback',
|
|
128
|
+
issuer: 'https://auth.douvery.com',
|
|
129
|
+
scopes: ['openid', 'profile', 'email'],
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Initialize (checks for existing session or handles callback)
|
|
133
|
+
await auth.initialize();
|
|
134
|
+
|
|
135
|
+
// Login
|
|
136
|
+
await auth.login();
|
|
137
|
+
|
|
138
|
+
// After callback, get user
|
|
139
|
+
const user = auth.getUser();
|
|
140
|
+
console.log(user);
|
|
141
|
+
|
|
142
|
+
// Get access token (auto-refreshes if needed)
|
|
143
|
+
const token = await auth.getAccessToken();
|
|
144
|
+
|
|
145
|
+
// Logout
|
|
146
|
+
await auth.logout();
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Configuration Options
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
interface DouveryAuthConfig {
|
|
153
|
+
/** OAuth Client ID */
|
|
154
|
+
clientId: string;
|
|
155
|
+
|
|
156
|
+
/** Authorization server base URL (default: "https://auth.douvery.com") */
|
|
157
|
+
issuer?: string;
|
|
158
|
+
|
|
159
|
+
/** Redirect URI after authentication */
|
|
160
|
+
redirectUri: string;
|
|
161
|
+
|
|
162
|
+
/** Post-logout redirect URI */
|
|
163
|
+
postLogoutRedirectUri?: string;
|
|
164
|
+
|
|
165
|
+
/** OAuth scopes to request (default: ["openid", "profile", "email"]) */
|
|
166
|
+
scopes?: string[];
|
|
167
|
+
|
|
168
|
+
/** Token storage strategy (default: "localStorage") */
|
|
169
|
+
storage?: "localStorage" | "sessionStorage" | "memory" | "cookie";
|
|
170
|
+
|
|
171
|
+
/** Auto-refresh tokens before expiry (default: true) */
|
|
172
|
+
autoRefresh?: boolean;
|
|
173
|
+
|
|
174
|
+
/** Seconds before expiry to trigger refresh (default: 60) */
|
|
175
|
+
refreshThreshold?: number;
|
|
176
|
+
|
|
177
|
+
/** Enable debug logging (default: false) */
|
|
178
|
+
debug?: boolean;
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Login Options
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
await auth.login({
|
|
186
|
+
// URL to return to after login
|
|
187
|
+
returnTo: '/dashboard',
|
|
188
|
+
|
|
189
|
+
// Force re-authentication
|
|
190
|
+
prompt: 'login',
|
|
191
|
+
|
|
192
|
+
// Pre-fill email
|
|
193
|
+
loginHint: 'user@example.com',
|
|
194
|
+
|
|
195
|
+
// UI locale
|
|
196
|
+
uiLocales: 'es',
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Features
|
|
201
|
+
|
|
202
|
+
- ✅ **PKCE Support** - Secure authorization code flow with PKCE
|
|
203
|
+
- ✅ **Auto Token Refresh** - Automatic token refresh before expiry
|
|
204
|
+
- ✅ **Multiple Storage Options** - localStorage, sessionStorage, memory, or cookies
|
|
205
|
+
- ✅ **TypeScript First** - Full TypeScript support with comprehensive types
|
|
206
|
+
- ✅ **Framework Adapters** - React and Qwik adapters with hooks
|
|
207
|
+
- ✅ **Event System** - Subscribe to auth events (login, logout, token refresh, etc.)
|
|
208
|
+
- ✅ **SSR Compatible** - Works with server-side rendering
|
|
209
|
+
|
|
210
|
+
## Development
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Install dependencies
|
|
214
|
+
pnpm install
|
|
215
|
+
|
|
216
|
+
# Build all packages
|
|
217
|
+
pnpm build
|
|
218
|
+
|
|
219
|
+
# Run in development mode
|
|
220
|
+
pnpm dev
|
|
221
|
+
|
|
222
|
+
# Type check
|
|
223
|
+
pnpm typecheck
|
|
224
|
+
|
|
225
|
+
# Clean build outputs
|
|
226
|
+
pnpm clean
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @douvery/auth - Core Types
|
|
3
|
+
* OAuth 2.0/OIDC type definitions
|
|
4
|
+
*/
|
|
5
|
+
interface DouveryAuthConfig {
|
|
6
|
+
/** OAuth Client ID */
|
|
7
|
+
clientId: string;
|
|
8
|
+
/** Authorization server base URL @default "https://auth.douvery.com" */
|
|
9
|
+
issuer?: string;
|
|
10
|
+
/** Redirect URI after authentication */
|
|
11
|
+
redirectUri: string;
|
|
12
|
+
/** Post-logout redirect URI */
|
|
13
|
+
postLogoutRedirectUri?: string;
|
|
14
|
+
/** OAuth scopes to request @default ["openid", "profile", "email"] */
|
|
15
|
+
scopes?: string[];
|
|
16
|
+
/** Token storage strategy @default "localStorage" */
|
|
17
|
+
storage?: "localStorage" | "sessionStorage" | "memory" | "cookie";
|
|
18
|
+
/** Custom storage implementation */
|
|
19
|
+
customStorage?: TokenStorage;
|
|
20
|
+
/** Auto-refresh tokens before expiry @default true */
|
|
21
|
+
autoRefresh?: boolean;
|
|
22
|
+
/** Seconds before expiry to trigger refresh @default 60 */
|
|
23
|
+
refreshThreshold?: number;
|
|
24
|
+
/** Enable debug logging @default false */
|
|
25
|
+
debug?: boolean;
|
|
26
|
+
}
|
|
27
|
+
interface TokenSet {
|
|
28
|
+
access_token: string;
|
|
29
|
+
token_type: string;
|
|
30
|
+
expires_in: number;
|
|
31
|
+
refresh_token?: string;
|
|
32
|
+
id_token?: string;
|
|
33
|
+
scope?: string;
|
|
34
|
+
}
|
|
35
|
+
interface TokenInfo {
|
|
36
|
+
accessToken: string;
|
|
37
|
+
refreshToken?: string;
|
|
38
|
+
idToken?: string;
|
|
39
|
+
expiresAt: number;
|
|
40
|
+
tokenType: string;
|
|
41
|
+
scope: string[];
|
|
42
|
+
}
|
|
43
|
+
interface DecodedIdToken {
|
|
44
|
+
iss: string;
|
|
45
|
+
sub: string;
|
|
46
|
+
aud: string;
|
|
47
|
+
exp: number;
|
|
48
|
+
iat: number;
|
|
49
|
+
auth_time?: number;
|
|
50
|
+
nonce?: string;
|
|
51
|
+
acr?: string;
|
|
52
|
+
amr?: string[];
|
|
53
|
+
azp?: string;
|
|
54
|
+
at_hash?: string;
|
|
55
|
+
c_hash?: string;
|
|
56
|
+
name?: string;
|
|
57
|
+
given_name?: string;
|
|
58
|
+
family_name?: string;
|
|
59
|
+
middle_name?: string;
|
|
60
|
+
nickname?: string;
|
|
61
|
+
preferred_username?: string;
|
|
62
|
+
profile?: string;
|
|
63
|
+
picture?: string;
|
|
64
|
+
website?: string;
|
|
65
|
+
email?: string;
|
|
66
|
+
email_verified?: boolean;
|
|
67
|
+
gender?: string;
|
|
68
|
+
birthdate?: string;
|
|
69
|
+
zoneinfo?: string;
|
|
70
|
+
locale?: string;
|
|
71
|
+
phone_number?: string;
|
|
72
|
+
phone_number_verified?: boolean;
|
|
73
|
+
address?: {
|
|
74
|
+
formatted?: string;
|
|
75
|
+
street_address?: string;
|
|
76
|
+
locality?: string;
|
|
77
|
+
region?: string;
|
|
78
|
+
postal_code?: string;
|
|
79
|
+
country?: string;
|
|
80
|
+
};
|
|
81
|
+
updated_at?: number;
|
|
82
|
+
[key: string]: unknown;
|
|
83
|
+
}
|
|
84
|
+
interface User {
|
|
85
|
+
id: string;
|
|
86
|
+
email?: string;
|
|
87
|
+
emailVerified?: boolean;
|
|
88
|
+
name?: string;
|
|
89
|
+
firstName?: string;
|
|
90
|
+
lastName?: string;
|
|
91
|
+
picture?: string;
|
|
92
|
+
phoneNumber?: string;
|
|
93
|
+
phoneNumberVerified?: boolean;
|
|
94
|
+
locale?: string;
|
|
95
|
+
[key: string]: unknown;
|
|
96
|
+
}
|
|
97
|
+
type AuthStatus = "loading" | "authenticated" | "unauthenticated";
|
|
98
|
+
interface AuthState {
|
|
99
|
+
status: AuthStatus;
|
|
100
|
+
user: User | null;
|
|
101
|
+
tokens: TokenInfo | null;
|
|
102
|
+
error: AuthError | null;
|
|
103
|
+
}
|
|
104
|
+
interface PKCEPair {
|
|
105
|
+
codeVerifier: string;
|
|
106
|
+
codeChallenge: string;
|
|
107
|
+
codeChallengeMethod: "S256";
|
|
108
|
+
}
|
|
109
|
+
interface TokenStorage {
|
|
110
|
+
get(key: string): string | null | Promise<string | null>;
|
|
111
|
+
set(key: string, value: string): void | Promise<void>;
|
|
112
|
+
remove(key: string): void | Promise<void>;
|
|
113
|
+
clear(): void | Promise<void>;
|
|
114
|
+
}
|
|
115
|
+
interface StorageKeys {
|
|
116
|
+
accessToken: string;
|
|
117
|
+
refreshToken: string;
|
|
118
|
+
idToken: string;
|
|
119
|
+
expiresAt: string;
|
|
120
|
+
state: string;
|
|
121
|
+
nonce: string;
|
|
122
|
+
codeVerifier: string;
|
|
123
|
+
returnTo: string;
|
|
124
|
+
}
|
|
125
|
+
type AuthEvent = {
|
|
126
|
+
type: "INITIALIZED";
|
|
127
|
+
} | {
|
|
128
|
+
type: "LOGIN_STARTED";
|
|
129
|
+
} | {
|
|
130
|
+
type: "LOGIN_SUCCESS";
|
|
131
|
+
user: User;
|
|
132
|
+
tokens: TokenInfo;
|
|
133
|
+
} | {
|
|
134
|
+
type: "LOGIN_ERROR";
|
|
135
|
+
error: AuthError;
|
|
136
|
+
} | {
|
|
137
|
+
type: "LOGOUT_STARTED";
|
|
138
|
+
} | {
|
|
139
|
+
type: "LOGOUT_SUCCESS";
|
|
140
|
+
} | {
|
|
141
|
+
type: "LOGOUT_ERROR";
|
|
142
|
+
error: AuthError;
|
|
143
|
+
} | {
|
|
144
|
+
type: "TOKEN_REFRESHED";
|
|
145
|
+
tokens: TokenInfo;
|
|
146
|
+
} | {
|
|
147
|
+
type: "TOKEN_REFRESH_ERROR";
|
|
148
|
+
error: AuthError;
|
|
149
|
+
} | {
|
|
150
|
+
type: "SESSION_EXPIRED";
|
|
151
|
+
};
|
|
152
|
+
type AuthEventHandler = (event: AuthEvent) => void;
|
|
153
|
+
declare class AuthError extends Error {
|
|
154
|
+
code: AuthErrorCode;
|
|
155
|
+
cause?: Error | undefined;
|
|
156
|
+
constructor(code: AuthErrorCode, message: string, cause?: Error | undefined);
|
|
157
|
+
}
|
|
158
|
+
type AuthErrorCode = "invalid_request" | "invalid_client" | "invalid_grant" | "unauthorized_client" | "unsupported_grant_type" | "invalid_scope" | "access_denied" | "server_error" | "temporarily_unavailable" | "login_required" | "consent_required" | "interaction_required" | "invalid_token" | "insufficient_scope" | "token_expired" | "token_refresh_failed" | "pkce_error" | "state_mismatch" | "nonce_mismatch" | "network_error" | "configuration_error" | "unknown_error";
|
|
159
|
+
interface OIDCDiscovery {
|
|
160
|
+
issuer: string;
|
|
161
|
+
authorization_endpoint: string;
|
|
162
|
+
token_endpoint: string;
|
|
163
|
+
userinfo_endpoint: string;
|
|
164
|
+
jwks_uri: string;
|
|
165
|
+
revocation_endpoint?: string;
|
|
166
|
+
introspection_endpoint?: string;
|
|
167
|
+
end_session_endpoint?: string;
|
|
168
|
+
registration_endpoint?: string;
|
|
169
|
+
scopes_supported: string[];
|
|
170
|
+
response_types_supported: string[];
|
|
171
|
+
response_modes_supported?: string[];
|
|
172
|
+
grant_types_supported: string[];
|
|
173
|
+
token_endpoint_auth_methods_supported?: string[];
|
|
174
|
+
subject_types_supported: string[];
|
|
175
|
+
id_token_signing_alg_values_supported: string[];
|
|
176
|
+
claims_supported?: string[];
|
|
177
|
+
code_challenge_methods_supported?: string[];
|
|
178
|
+
}
|
|
179
|
+
interface CallbackResult {
|
|
180
|
+
success: boolean;
|
|
181
|
+
user?: User;
|
|
182
|
+
tokens?: TokenInfo;
|
|
183
|
+
error?: AuthError;
|
|
184
|
+
returnTo?: string;
|
|
185
|
+
}
|
|
186
|
+
interface LoginOptions {
|
|
187
|
+
/** URL to return to after login */
|
|
188
|
+
returnTo?: string;
|
|
189
|
+
/** Additional authorization parameters */
|
|
190
|
+
authorizationParams?: Record<string, string>;
|
|
191
|
+
/** Prompt parameter (none, login, consent, select_account) */
|
|
192
|
+
prompt?: "none" | "login" | "consent" | "select_account";
|
|
193
|
+
/** Login hint (email or identifier) */
|
|
194
|
+
loginHint?: string;
|
|
195
|
+
/** UI locales preference */
|
|
196
|
+
uiLocales?: string;
|
|
197
|
+
/** Maximum authentication age in seconds */
|
|
198
|
+
maxAge?: number;
|
|
199
|
+
/** ACR values requested */
|
|
200
|
+
acrValues?: string;
|
|
201
|
+
}
|
|
202
|
+
interface LogoutOptions {
|
|
203
|
+
/** URL to return to after logout */
|
|
204
|
+
returnTo?: string;
|
|
205
|
+
/** Whether to federate logout (end session at IdP) @default true */
|
|
206
|
+
federated?: boolean;
|
|
207
|
+
/** Only clear local session, don't redirect @default false */
|
|
208
|
+
localOnly?: boolean;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @douvery/auth - Auth Client
|
|
213
|
+
* Main OAuth 2.0/OIDC client implementation
|
|
214
|
+
*/
|
|
215
|
+
|
|
216
|
+
declare class DouveryAuthClient {
|
|
217
|
+
private config;
|
|
218
|
+
private tokenManager;
|
|
219
|
+
private discovery;
|
|
220
|
+
private eventHandlers;
|
|
221
|
+
private refreshTimer;
|
|
222
|
+
private state;
|
|
223
|
+
constructor(config: DouveryAuthConfig);
|
|
224
|
+
/** Initialize the auth client */
|
|
225
|
+
initialize(): Promise<AuthState>;
|
|
226
|
+
/** Start the login flow */
|
|
227
|
+
login(options?: LoginOptions): Promise<void>;
|
|
228
|
+
/** Logout the user */
|
|
229
|
+
logout(options?: LogoutOptions): Promise<void>;
|
|
230
|
+
/** Check if current URL is an OAuth callback */
|
|
231
|
+
isCallback(): boolean;
|
|
232
|
+
/** Handle the OAuth callback */
|
|
233
|
+
handleCallback(): Promise<CallbackResult>;
|
|
234
|
+
private exchangeCode;
|
|
235
|
+
/** Refresh the access token */
|
|
236
|
+
refreshTokens(): Promise<TokenInfo>;
|
|
237
|
+
/** Get current access token (auto-refreshes if needed) */
|
|
238
|
+
getAccessToken(): Promise<string | null>;
|
|
239
|
+
private tokenSetToInfo;
|
|
240
|
+
private fetchUser;
|
|
241
|
+
private extractUserFromIdToken;
|
|
242
|
+
private normalizeUser;
|
|
243
|
+
private getDiscovery;
|
|
244
|
+
private setupAutoRefresh;
|
|
245
|
+
private clearAutoRefresh;
|
|
246
|
+
getState(): AuthState;
|
|
247
|
+
isAuthenticated(): boolean;
|
|
248
|
+
getUser(): User | null;
|
|
249
|
+
subscribe(handler: AuthEventHandler): () => void;
|
|
250
|
+
private updateState;
|
|
251
|
+
private emit;
|
|
252
|
+
private log;
|
|
253
|
+
}
|
|
254
|
+
/** Create a new DouveryAuthClient instance */
|
|
255
|
+
declare function createDouveryAuth(config: DouveryAuthConfig): DouveryAuthClient;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* @douvery/auth - PKCE Utilities
|
|
259
|
+
* RFC 7636 - Proof Key for Code Exchange
|
|
260
|
+
*/
|
|
261
|
+
|
|
262
|
+
/** Generate a cryptographically random string for use as code_verifier */
|
|
263
|
+
declare function generateCodeVerifier(length?: number): string;
|
|
264
|
+
/** Generate a random state parameter for CSRF protection */
|
|
265
|
+
declare function generateState(): string;
|
|
266
|
+
/** Generate a random nonce for replay attack protection */
|
|
267
|
+
declare function generateNonce(): string;
|
|
268
|
+
/** Create SHA-256 hash and encode as base64url */
|
|
269
|
+
declare function generateCodeChallenge(verifier: string): Promise<string>;
|
|
270
|
+
/** Encode ArrayBuffer as base64url (RFC 4648 Section 5) */
|
|
271
|
+
declare function base64UrlEncode(buffer: ArrayBuffer): string;
|
|
272
|
+
/** Decode base64url string to ArrayBuffer */
|
|
273
|
+
declare function base64UrlDecode(input: string): ArrayBuffer;
|
|
274
|
+
/** Generate a complete PKCE pair (verifier + challenge) */
|
|
275
|
+
declare function generatePKCEPair(): Promise<PKCEPair>;
|
|
276
|
+
/** Verify a code_verifier against a code_challenge */
|
|
277
|
+
declare function verifyCodeChallenge(verifier: string, challenge: string, method?: "S256" | "plain"): Promise<boolean>;
|
|
278
|
+
/** Parse and decode a JWT token (without verification) */
|
|
279
|
+
declare function decodeJWT<T = Record<string, unknown>>(token: string): T;
|
|
280
|
+
/** Check if a JWT token is expired */
|
|
281
|
+
declare function isTokenExpired(token: string, clockSkew?: number): boolean;
|
|
282
|
+
/** Get token expiration timestamp */
|
|
283
|
+
declare function getTokenExpiration(token: string): number | null;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @douvery/auth - Token Storage
|
|
287
|
+
* Abstraction for token persistence
|
|
288
|
+
*/
|
|
289
|
+
|
|
290
|
+
declare const STORAGE_KEYS: StorageKeys;
|
|
291
|
+
/** In-memory storage implementation */
|
|
292
|
+
declare class MemoryStorage implements TokenStorage {
|
|
293
|
+
private store;
|
|
294
|
+
get(key: string): string | null;
|
|
295
|
+
set(key: string, value: string): void;
|
|
296
|
+
remove(key: string): void;
|
|
297
|
+
clear(): void;
|
|
298
|
+
}
|
|
299
|
+
/** LocalStorage implementation */
|
|
300
|
+
declare class LocalStorage implements TokenStorage {
|
|
301
|
+
get(key: string): string | null;
|
|
302
|
+
set(key: string, value: string): void;
|
|
303
|
+
remove(key: string): void;
|
|
304
|
+
clear(): void;
|
|
305
|
+
}
|
|
306
|
+
/** SessionStorage implementation */
|
|
307
|
+
declare class SessionStorage implements TokenStorage {
|
|
308
|
+
get(key: string): string | null;
|
|
309
|
+
set(key: string, value: string): void;
|
|
310
|
+
remove(key: string): void;
|
|
311
|
+
clear(): void;
|
|
312
|
+
}
|
|
313
|
+
/** Cookie storage implementation (for SSR compatibility) */
|
|
314
|
+
declare class CookieStorage implements TokenStorage {
|
|
315
|
+
private options;
|
|
316
|
+
constructor(options?: {
|
|
317
|
+
path?: string;
|
|
318
|
+
domain?: string;
|
|
319
|
+
secure?: boolean;
|
|
320
|
+
sameSite?: "Strict" | "Lax" | "None";
|
|
321
|
+
maxAge?: number;
|
|
322
|
+
});
|
|
323
|
+
get(key: string): string | null;
|
|
324
|
+
set(key: string, value: string): void;
|
|
325
|
+
remove(key: string): void;
|
|
326
|
+
clear(): void;
|
|
327
|
+
}
|
|
328
|
+
/** Create storage instance based on type */
|
|
329
|
+
declare function createStorage(type: "localStorage" | "sessionStorage" | "memory" | "cookie"): TokenStorage;
|
|
330
|
+
/** Token manager for handling token persistence */
|
|
331
|
+
declare class TokenManager {
|
|
332
|
+
private storage;
|
|
333
|
+
constructor(storage: TokenStorage);
|
|
334
|
+
getTokens(): Promise<TokenInfo | null>;
|
|
335
|
+
setTokens(tokens: TokenInfo): Promise<void>;
|
|
336
|
+
clearTokens(): Promise<void>;
|
|
337
|
+
saveState(state: string): Promise<void>;
|
|
338
|
+
getState(): Promise<string | null>;
|
|
339
|
+
clearState(): Promise<void>;
|
|
340
|
+
saveNonce(nonce: string): Promise<void>;
|
|
341
|
+
getNonce(): Promise<string | null>;
|
|
342
|
+
clearNonce(): Promise<void>;
|
|
343
|
+
saveCodeVerifier(verifier: string): Promise<void>;
|
|
344
|
+
getCodeVerifier(): Promise<string | null>;
|
|
345
|
+
clearCodeVerifier(): Promise<void>;
|
|
346
|
+
saveReturnTo(url: string): Promise<void>;
|
|
347
|
+
getReturnTo(): Promise<string | null>;
|
|
348
|
+
clearReturnTo(): Promise<void>;
|
|
349
|
+
clearAll(): Promise<void>;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export { AuthError, type AuthErrorCode, type AuthEvent, type AuthEventHandler, type AuthState, type AuthStatus, type CallbackResult, CookieStorage, type DecodedIdToken, DouveryAuthClient, type DouveryAuthConfig, LocalStorage, type LoginOptions, type LogoutOptions, MemoryStorage, type OIDCDiscovery, type PKCEPair, STORAGE_KEYS, SessionStorage, type StorageKeys, type TokenInfo, TokenManager, type TokenSet, type TokenStorage, type User, base64UrlDecode, base64UrlEncode, createDouveryAuth, createStorage, decodeJWT, generateCodeChallenge, generateCodeVerifier, generateNonce, generatePKCEPair, generateState, getTokenExpiration, isTokenExpired, verifyCodeChallenge };
|