@go-mondo/nextjs-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 +462 -0
- package/dist/access-token-UIlXwi3X.d.cts +27 -0
- package/dist/access-token-UIlXwi3X.d.ts +27 -0
- package/dist/client.cjs +1324 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +201 -0
- package/dist/client.d.ts +201 -0
- package/dist/client.js +1301 -0
- package/dist/client.js.map +1 -0
- package/dist/config.cjs +4 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +90 -0
- package/dist/config.d.ts +90 -0
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.cjs +189 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +178 -0
- package/dist/errors.d.ts +178 -0
- package/dist/errors.js +178 -0
- package/dist/errors.js.map +1 -0
- package/dist/hooks.cjs +236 -0
- package/dist/hooks.cjs.map +1 -0
- package/dist/hooks.d.cts +146 -0
- package/dist/hooks.d.ts +146 -0
- package/dist/hooks.js +230 -0
- package/dist/hooks.js.map +1 -0
- package/dist/oauth.cjs +10 -0
- package/dist/oauth.cjs.map +1 -0
- package/dist/oauth.d.cts +55 -0
- package/dist/oauth.d.ts +55 -0
- package/dist/oauth.js +8 -0
- package/dist/oauth.js.map +1 -0
- package/dist/session.cjs +45 -0
- package/dist/session.cjs.map +1 -0
- package/dist/session.d.cts +71 -0
- package/dist/session.d.ts +71 -0
- package/dist/session.js +43 -0
- package/dist/session.js.map +1 -0
- package/dist/types-CbrOw4QQ.d.cts +108 -0
- package/dist/types-CbrOw4QQ.d.ts +108 -0
- package/package.json +146 -0
package/README.md
ADDED
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
# @go-mondo/nextjs-auth
|
|
2
|
+
|
|
3
|
+
Next.js authentication helpers for Mondo Identity.
|
|
4
|
+
|
|
5
|
+
This package provides a small OAuth/OIDC auth layer for modern Next.js apps. It
|
|
6
|
+
is centered around a single auth client that can mount auth routes, protect
|
|
7
|
+
routes from `proxy.ts`, read the current session, and return or refresh access
|
|
8
|
+
tokens.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
pnpm add @go-mondo/nextjs-auth
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Public Entry Points
|
|
17
|
+
|
|
18
|
+
This package uses explicit subpath exports for supporting types. Import the
|
|
19
|
+
auth client from `@go-mondo/nextjs-auth` or `@go-mondo/nextjs-auth/client`, and
|
|
20
|
+
import supporting public types from `@go-mondo/nextjs-auth/config`,
|
|
21
|
+
`@go-mondo/nextjs-auth/session`, `@go-mondo/nextjs-auth/oauth`, or
|
|
22
|
+
`@go-mondo/nextjs-auth/errors`. Hooks are exported from
|
|
23
|
+
`@go-mondo/nextjs-auth/hooks`.
|
|
24
|
+
|
|
25
|
+
## Environment
|
|
26
|
+
|
|
27
|
+
At minimum, configure:
|
|
28
|
+
|
|
29
|
+
```env
|
|
30
|
+
MONDO_SECRET="replace-with-at-least-32-characters"
|
|
31
|
+
MONDO_ISSUER_BASE_URL="https://identity.example.com"
|
|
32
|
+
APP_BASE_URL="http://localhost:3000"
|
|
33
|
+
MONDO_CLIENT_ID="your-client-id"
|
|
34
|
+
MONDO_CLIENT_SECRET="your-client-secret"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Common optional values:
|
|
38
|
+
|
|
39
|
+
```env
|
|
40
|
+
MONDO_AUDIENCE="https://api.example.com"
|
|
41
|
+
MONDO_SCOPE="openid profile email offline_access"
|
|
42
|
+
|
|
43
|
+
NEXT_PUBLIC_LOGIN_ROUTE="/auth/login"
|
|
44
|
+
NEXT_PUBLIC_SESSION_ROUTE="/auth/session"
|
|
45
|
+
NEXT_PUBLIC_ACCESS_TOKEN_ROUTE="/auth/access-token"
|
|
46
|
+
CALLBACK_ROUTE="/auth/callback"
|
|
47
|
+
LOGOUT_ROUTE="/auth/logout"
|
|
48
|
+
SESSION_ROUTE="/auth/session"
|
|
49
|
+
ACCESS_TOKEN_ROUTE="/auth/access-token"
|
|
50
|
+
POST_LOGOUT_REDIRECT_ROUTE="/"
|
|
51
|
+
|
|
52
|
+
MONDO_SESSION_IDLE_DURATION="86400"
|
|
53
|
+
MONDO_SESSION_ABSOLUTE_DURATION="604800"
|
|
54
|
+
MONDO_COOKIE_SECURE="true"
|
|
55
|
+
MONDO_COOKIE_SAME_SITE="lax"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`MONDO_SECRET` is used by `iron-session` to seal session and transaction
|
|
59
|
+
cookies. Use at least 32 characters. For secret rotation, pass an array of
|
|
60
|
+
secrets when creating the auth client.
|
|
61
|
+
|
|
62
|
+
## Quick Start
|
|
63
|
+
|
|
64
|
+
Create one auth client and reuse it everywhere.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
// src/lib/auth.ts
|
|
68
|
+
import { createAuth } from '@go-mondo/nextjs-auth';
|
|
69
|
+
|
|
70
|
+
export const auth = createAuth();
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Mount the auth routes.
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
// src/app/auth/[...auth]/route.ts
|
|
77
|
+
import { auth } from '@/lib/auth';
|
|
78
|
+
|
|
79
|
+
export const GET = auth.handleAuth();
|
|
80
|
+
export const POST = auth.handleAuth();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Protect routes with `proxy.ts`.
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
// src/proxy.ts
|
|
87
|
+
import { auth } from '@/lib/auth';
|
|
88
|
+
|
|
89
|
+
export const proxy = auth.proxy;
|
|
90
|
+
|
|
91
|
+
export const config = {
|
|
92
|
+
matcher: [
|
|
93
|
+
'/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)',
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Link users to login and logout with normal anchors.
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
export function AuthLinks() {
|
|
102
|
+
return (
|
|
103
|
+
<nav>
|
|
104
|
+
<a href="/auth/login">Log in</a>
|
|
105
|
+
<a href="/auth/logout">Log out</a>
|
|
106
|
+
</nav>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Public Routes
|
|
112
|
+
|
|
113
|
+
If your matcher covers the whole app, pass public paths to `auth.proxy`.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
// src/proxy.ts
|
|
117
|
+
import { auth } from '@/lib/auth';
|
|
118
|
+
|
|
119
|
+
export function proxy(request: Request) {
|
|
120
|
+
return auth.proxy(request, {
|
|
121
|
+
publicPaths: ['/', '/pricing', /^\/blog(\/.*)?$/],
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Unauthenticated users are redirected to the configured login route with a
|
|
127
|
+
`returnTo` query parameter.
|
|
128
|
+
|
|
129
|
+
You can also compose `auth.proxy()` with other proxy checks. This is useful
|
|
130
|
+
when one route family needs different behavior than the rest of the protected
|
|
131
|
+
app.
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// src/proxy.ts
|
|
135
|
+
import { NextResponse, type NextRequest } from 'next/server';
|
|
136
|
+
import { auth } from '@/lib/auth';
|
|
137
|
+
|
|
138
|
+
const publicPaths = ['/', '/pricing', /^\/blog(\/.*)?$/];
|
|
139
|
+
|
|
140
|
+
export async function proxy(request: NextRequest) {
|
|
141
|
+
const { pathname, search } = request.nextUrl;
|
|
142
|
+
|
|
143
|
+
if (pathname === '/healthz') {
|
|
144
|
+
return Response.json({ ok: true });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (pathname.startsWith('/api/webhooks/')) {
|
|
148
|
+
const signature = request.headers.get('x-webhook-signature');
|
|
149
|
+
|
|
150
|
+
if (signature !== process.env.WEBHOOK_SHARED_SECRET) {
|
|
151
|
+
return new Response(null, { status: 401 });
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return NextResponse.next();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (pathname.startsWith('/admin')) {
|
|
158
|
+
const response = await auth.proxy(request, {
|
|
159
|
+
returnTo: `${pathname}${search}`,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
response?.headers.set('x-route-scope', 'admin');
|
|
163
|
+
return response;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return auth.proxy(request, {
|
|
167
|
+
publicPaths,
|
|
168
|
+
returnTo: `${pathname}${search}`,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export const config = {
|
|
173
|
+
matcher: [
|
|
174
|
+
'/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)',
|
|
175
|
+
],
|
|
176
|
+
};
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Reading the Session
|
|
180
|
+
|
|
181
|
+
Use the auth client from server components, route handlers, and server actions.
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
// src/app/account/page.tsx
|
|
185
|
+
import { auth } from '@/lib/auth';
|
|
186
|
+
|
|
187
|
+
export default async function AccountPage() {
|
|
188
|
+
const session = await auth.getSession();
|
|
189
|
+
|
|
190
|
+
if (!session) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return <h1>{session.user.email}</h1>;
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The default session JSON endpoint is mounted at `/auth/session`.
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
const response = await fetch('/auth/session');
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Reading the User in Client Components
|
|
205
|
+
|
|
206
|
+
Client components can read the current user with the TanStack Query hook from
|
|
207
|
+
the focused user hook entry point. Your app must provide a
|
|
208
|
+
`QueryClientProvider`.
|
|
209
|
+
|
|
210
|
+
```sh
|
|
211
|
+
pnpm add @tanstack/react-query
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
// src/app/providers.tsx
|
|
216
|
+
'use client';
|
|
217
|
+
|
|
218
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
219
|
+
import { type ReactNode, useState } from 'react';
|
|
220
|
+
|
|
221
|
+
export function Providers({ children }: { children: ReactNode }) {
|
|
222
|
+
const [queryClient] = useState(() => new QueryClient());
|
|
223
|
+
|
|
224
|
+
return (
|
|
225
|
+
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
'use client';
|
|
232
|
+
|
|
233
|
+
import { useUserProfile } from '@go-mondo/nextjs-auth/hooks';
|
|
234
|
+
|
|
235
|
+
type MondoClaims = {
|
|
236
|
+
roles?: string[];
|
|
237
|
+
org_id?: string;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
export function ProfileButton() {
|
|
241
|
+
const { data: user, isLoading } = useUserProfile<MondoClaims>();
|
|
242
|
+
|
|
243
|
+
if (isLoading) {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return <span>{user?.email ?? 'Signed out'}</span>;
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
The hook calls `/auth/session` by default and returns `undefined` for 401/403
|
|
252
|
+
responses. It can read either the default session JSON shape or a transformed
|
|
253
|
+
route that returns `session.user` directly.
|
|
254
|
+
|
|
255
|
+
## Getting an Access Token
|
|
256
|
+
|
|
257
|
+
On the server, call `getAccessToken`. If the stored access token is expired and
|
|
258
|
+
a refresh token is available, the package refreshes the access token and writes
|
|
259
|
+
the updated authorization data back to the sealed session cookies.
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
// src/app/api/reports/route.ts
|
|
263
|
+
import { auth } from '@/lib/auth';
|
|
264
|
+
|
|
265
|
+
export async function GET() {
|
|
266
|
+
const { accessToken } = await auth.getAccessToken({
|
|
267
|
+
scopes: ['reports:read'],
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
const upstream = await fetch('https://api.example.com/reports', {
|
|
271
|
+
headers: {
|
|
272
|
+
authorization: `Bearer ${accessToken}`,
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
return Response.json(await upstream.json(), { status: upstream.status });
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The default access-token JSON endpoint is mounted at `/auth/access-token`.
|
|
281
|
+
Prefer server-side access-token usage when possible; expose this endpoint only
|
|
282
|
+
when browser code truly needs the token.
|
|
283
|
+
|
|
284
|
+
Client components can request a current or refreshed access token with
|
|
285
|
+
`useAccessToken`. The server still owns the refresh token; browser code only
|
|
286
|
+
receives the short-lived access token returned by the mounted access-token
|
|
287
|
+
route.
|
|
288
|
+
|
|
289
|
+
```tsx
|
|
290
|
+
'use client';
|
|
291
|
+
|
|
292
|
+
import { useAccessToken } from '@go-mondo/nextjs-auth/hooks';
|
|
293
|
+
|
|
294
|
+
export function ReportsClient() {
|
|
295
|
+
const { data: token } = useAccessToken({
|
|
296
|
+
scopes: ['reports:read'],
|
|
297
|
+
refresh: true,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
return <button disabled={!token}>Load reports</button>;
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
When `scopes`, `refresh`, or `refreshBeforeExpiresIn` are provided, the hook
|
|
305
|
+
POSTs those options to `/auth/access-token`. The authorization server validates
|
|
306
|
+
whether requested scopes are allowed for the stored refresh token.
|
|
307
|
+
|
|
308
|
+
For imperative browser API clients, use `createAccessTokenProvider` so repeated
|
|
309
|
+
API calls do not hit `/auth/access-token` before every request. The cache is
|
|
310
|
+
memory-only, expires entries from the returned `expiresAt` value, and shares one
|
|
311
|
+
in-flight token request across concurrent callers.
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
// src/lib/api.ts
|
|
315
|
+
import { createAccessTokenProvider } from '@go-mondo/nextjs-auth/hooks';
|
|
316
|
+
|
|
317
|
+
const tokens = createAccessTokenProvider({
|
|
318
|
+
scopes: ['reports:read'],
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
export async function apiFetch(input: RequestInfo | URL, init?: RequestInit) {
|
|
322
|
+
const { accessToken } = await tokens.getAccessToken();
|
|
323
|
+
const headers = new Headers(init?.headers);
|
|
324
|
+
|
|
325
|
+
headers.set('authorization', `Bearer ${accessToken}`);
|
|
326
|
+
|
|
327
|
+
return fetch(input, {
|
|
328
|
+
...init,
|
|
329
|
+
headers,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Custom Configuration
|
|
335
|
+
|
|
336
|
+
You can configure the client in code instead of relying only on environment
|
|
337
|
+
variables.
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
// src/lib/auth.ts
|
|
341
|
+
import { createAuth } from '@go-mondo/nextjs-auth';
|
|
342
|
+
|
|
343
|
+
export const auth = createAuth({
|
|
344
|
+
baseURL: 'https://app.example.com',
|
|
345
|
+
issuerBaseURL: 'https://identity.example.com',
|
|
346
|
+
clientId: 'client-id',
|
|
347
|
+
clientSecret: 'client-secret',
|
|
348
|
+
secret: [
|
|
349
|
+
'new-32-character-or-longer-secret',
|
|
350
|
+
'old-32-character-or-longer-secret',
|
|
351
|
+
],
|
|
352
|
+
authorization: {
|
|
353
|
+
audience: 'https://api.example.com',
|
|
354
|
+
scope: 'openid profile email offline_access reports:read',
|
|
355
|
+
},
|
|
356
|
+
session: {
|
|
357
|
+
idleDuration: 60 * 60 * 24,
|
|
358
|
+
absoluteDuration: 60 * 60 * 24 * 7,
|
|
359
|
+
cookie: {
|
|
360
|
+
secure: true,
|
|
361
|
+
sameSite: 'lax',
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
Configuration is validated with Zod at client initialization. The schema is
|
|
368
|
+
described in code so validation errors, generated docs, and future examples can
|
|
369
|
+
all draw from the same source of truth.
|
|
370
|
+
|
|
371
|
+
## Typed Claims
|
|
372
|
+
|
|
373
|
+
Pass your app-specific claims to `createAuth` to type `session.user`.
|
|
374
|
+
|
|
375
|
+
```ts
|
|
376
|
+
import { createAuth } from '@go-mondo/nextjs-auth';
|
|
377
|
+
|
|
378
|
+
type MondoClaims = {
|
|
379
|
+
roles?: string[];
|
|
380
|
+
org_id?: string;
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
export const auth = createAuth<MondoClaims>();
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
```ts
|
|
387
|
+
const session = await auth.getSession();
|
|
388
|
+
session?.user.roles;
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## Mounted Routes
|
|
392
|
+
|
|
393
|
+
By default, `auth.handleAuth()` handles:
|
|
394
|
+
|
|
395
|
+
- `/auth/login`: starts the authorization-code login flow.
|
|
396
|
+
- `/auth/callback`: verifies the callback and stores the session.
|
|
397
|
+
- `/auth/logout`: clears the local application session.
|
|
398
|
+
- `/auth/session`: returns the current session as JSON.
|
|
399
|
+
- `/auth/access-token`: returns or refreshes the current access token.
|
|
400
|
+
|
|
401
|
+
## Session Cookies
|
|
402
|
+
|
|
403
|
+
The session is split into sealed `iron-session` cookies:
|
|
404
|
+
|
|
405
|
+
- `Mondo.Session`: user claims and session timestamps.
|
|
406
|
+
- `Mondo.Authorization`: access token, expiry, scopes, and refresh token.
|
|
407
|
+
- `Mondo.Authentication`: raw ID token.
|
|
408
|
+
|
|
409
|
+
This keeps the session stateless and tamper-proof while avoiding a server-side
|
|
410
|
+
session database. Cookies are HTTP-only by default.
|
|
411
|
+
|
|
412
|
+
## Session Expiration
|
|
413
|
+
|
|
414
|
+
Sessions support both idle and absolute expiration. `idleDuration` extends the
|
|
415
|
+
session when authenticated activity touches it, such as protected requests
|
|
416
|
+
handled by `auth.proxy()` or the session JSON route. `absoluteDuration` caps the
|
|
417
|
+
session lifetime from the original login time, regardless of activity.
|
|
418
|
+
|
|
419
|
+
The stored `expiresAt` timestamp is the earlier of the idle and absolute
|
|
420
|
+
expiration times. Set `idleDuration: false` to disable activity-based extension;
|
|
421
|
+
set `absoluteDuration: false` to disable the hard maximum lifetime. At least one
|
|
422
|
+
expiration mode must be enabled.
|
|
423
|
+
|
|
424
|
+
## Development
|
|
425
|
+
|
|
426
|
+
```sh
|
|
427
|
+
pnpm install
|
|
428
|
+
pnpm run check
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
`pnpm run check` runs library type-checking, example type-checking, linting,
|
|
432
|
+
formatting checks, tests, and the package build.
|
|
433
|
+
|
|
434
|
+
## Examples
|
|
435
|
+
|
|
436
|
+
This repository includes two runnable Next.js examples. Both require your own
|
|
437
|
+
Mondo Identity OIDC application credentials.
|
|
438
|
+
|
|
439
|
+
```sh
|
|
440
|
+
pnpm install
|
|
441
|
+
pnpm run build
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Server-rendered profile:
|
|
445
|
+
|
|
446
|
+
```sh
|
|
447
|
+
cd examples/server-profile
|
|
448
|
+
cp .env.example .env.local
|
|
449
|
+
pnpm dev
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
Client-rendered profile:
|
|
453
|
+
|
|
454
|
+
```sh
|
|
455
|
+
cd examples/client-profile
|
|
456
|
+
cp .env.example .env.local
|
|
457
|
+
pnpm dev
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
The server example runs on port `3001`; the client example runs on port `3002`.
|
|
461
|
+
Register the matching `/auth/callback` URL with your identity provider before
|
|
462
|
+
logging in.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
type AccessTokenResult = {
|
|
2
|
+
/** Bearer token value returned by the identity provider. */
|
|
3
|
+
accessToken: string;
|
|
4
|
+
/** Epoch seconds when the access token expires. */
|
|
5
|
+
expiresAt: number;
|
|
6
|
+
/** Space-delimited scopes granted to the access token. */
|
|
7
|
+
scope?: string;
|
|
8
|
+
/** Token type returned by the identity provider, usually `Bearer`. */
|
|
9
|
+
type?: string;
|
|
10
|
+
};
|
|
11
|
+
type GetAccessTokenOptions = {
|
|
12
|
+
/**
|
|
13
|
+
* Refresh even when the current access token is still valid.
|
|
14
|
+
*/
|
|
15
|
+
refresh?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Required scopes for the returned access token.
|
|
18
|
+
*/
|
|
19
|
+
scopes?: string | Array<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Number of seconds before expiry that should be treated as already expired.
|
|
22
|
+
*/
|
|
23
|
+
refreshBeforeExpiresIn?: number;
|
|
24
|
+
};
|
|
25
|
+
type GetAccessToken = (options?: GetAccessTokenOptions) => Promise<AccessTokenResult>;
|
|
26
|
+
|
|
27
|
+
export type { AccessTokenResult as A, GetAccessTokenOptions as G, GetAccessToken as a };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
type AccessTokenResult = {
|
|
2
|
+
/** Bearer token value returned by the identity provider. */
|
|
3
|
+
accessToken: string;
|
|
4
|
+
/** Epoch seconds when the access token expires. */
|
|
5
|
+
expiresAt: number;
|
|
6
|
+
/** Space-delimited scopes granted to the access token. */
|
|
7
|
+
scope?: string;
|
|
8
|
+
/** Token type returned by the identity provider, usually `Bearer`. */
|
|
9
|
+
type?: string;
|
|
10
|
+
};
|
|
11
|
+
type GetAccessTokenOptions = {
|
|
12
|
+
/**
|
|
13
|
+
* Refresh even when the current access token is still valid.
|
|
14
|
+
*/
|
|
15
|
+
refresh?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Required scopes for the returned access token.
|
|
18
|
+
*/
|
|
19
|
+
scopes?: string | Array<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Number of seconds before expiry that should be treated as already expired.
|
|
22
|
+
*/
|
|
23
|
+
refreshBeforeExpiresIn?: number;
|
|
24
|
+
};
|
|
25
|
+
type GetAccessToken = (options?: GetAccessTokenOptions) => Promise<AccessTokenResult>;
|
|
26
|
+
|
|
27
|
+
export type { AccessTokenResult as A, GetAccessTokenOptions as G, GetAccessToken as a };
|