nuxt-auther 1.0.2 → 1.0.3

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.
Files changed (92) hide show
  1. package/dist/module.cjs +5 -0
  2. package/dist/module.d.mts +3 -0
  3. package/dist/module.d.ts +3 -0
  4. package/dist/module.json +8 -0
  5. package/dist/module.mjs +1007 -0
  6. package/dist/runtime/composables.d.ts +2 -0
  7. package/dist/runtime/composables.mjs +2 -0
  8. package/dist/runtime/core/auth.d.ts +53 -0
  9. package/dist/runtime/core/auth.mjs +387 -0
  10. package/dist/runtime/core/index.d.ts +3 -0
  11. package/dist/runtime/core/index.mjs +3 -0
  12. package/dist/runtime/core/middleware.d.ts +2 -0
  13. package/dist/runtime/core/middleware.mjs +41 -0
  14. package/dist/runtime/core/storage.d.ts +41 -0
  15. package/dist/runtime/core/storage.mjs +277 -0
  16. package/dist/runtime/inc/configuration-document-request-error.d.ts +3 -0
  17. package/dist/runtime/inc/configuration-document-request-error.mjs +6 -0
  18. package/dist/runtime/inc/configuration-document.d.ts +26 -0
  19. package/dist/runtime/inc/configuration-document.mjs +94 -0
  20. package/dist/runtime/inc/default-properties.d.ts +123 -0
  21. package/dist/runtime/inc/default-properties.mjs +132 -0
  22. package/dist/runtime/inc/expired-auth-session-error.d.ts +3 -0
  23. package/dist/runtime/inc/expired-auth-session-error.mjs +6 -0
  24. package/dist/runtime/inc/id-token.d.ts +15 -0
  25. package/dist/runtime/inc/id-token.mjs +81 -0
  26. package/dist/runtime/inc/index.d.ts +10 -0
  27. package/dist/runtime/inc/index.mjs +10 -0
  28. package/dist/runtime/inc/refresh-controller.d.ts +9 -0
  29. package/dist/runtime/inc/refresh-controller.mjs +29 -0
  30. package/dist/runtime/inc/refresh-token.d.ts +14 -0
  31. package/dist/runtime/inc/refresh-token.mjs +75 -0
  32. package/dist/runtime/inc/request-handler.d.ts +17 -0
  33. package/dist/runtime/inc/request-handler.mjs +93 -0
  34. package/dist/runtime/inc/token-status.d.ts +12 -0
  35. package/dist/runtime/inc/token-status.mjs +39 -0
  36. package/dist/runtime/inc/token.d.ts +14 -0
  37. package/dist/runtime/inc/token.mjs +83 -0
  38. package/dist/runtime/index.d.ts +3 -0
  39. package/dist/runtime/index.mjs +3 -0
  40. package/dist/runtime/providers/auth0.d.ts +7 -0
  41. package/dist/runtime/providers/auth0.mjs +15 -0
  42. package/dist/runtime/providers/discord.d.ts +6 -0
  43. package/dist/runtime/providers/discord.mjs +18 -0
  44. package/dist/runtime/providers/facebook.d.ts +6 -0
  45. package/dist/runtime/providers/facebook.mjs +13 -0
  46. package/dist/runtime/providers/github.d.ts +6 -0
  47. package/dist/runtime/providers/github.mjs +15 -0
  48. package/dist/runtime/providers/google.d.ts +6 -0
  49. package/dist/runtime/providers/google.mjs +13 -0
  50. package/dist/runtime/providers/index.d.ts +8 -0
  51. package/dist/runtime/providers/index.mjs +8 -0
  52. package/dist/runtime/providers/laravel-jwt.d.ts +7 -0
  53. package/dist/runtime/providers/laravel-jwt.mjs +47 -0
  54. package/dist/runtime/providers/laravel-passport.d.ts +12 -0
  55. package/dist/runtime/providers/laravel-passport.mjs +69 -0
  56. package/dist/runtime/providers/laravel-sanctum.d.ts +6 -0
  57. package/dist/runtime/providers/laravel-sanctum.mjs +52 -0
  58. package/dist/runtime/schemes/auth0.d.ts +4 -0
  59. package/dist/runtime/schemes/auth0.mjs +13 -0
  60. package/dist/runtime/schemes/base.d.ts +8 -0
  61. package/dist/runtime/schemes/base.mjs +11 -0
  62. package/dist/runtime/schemes/cookie.d.ts +23 -0
  63. package/dist/runtime/schemes/cookie.mjs +111 -0
  64. package/dist/runtime/schemes/index.d.ts +8 -0
  65. package/dist/runtime/schemes/index.mjs +8 -0
  66. package/dist/runtime/schemes/laravel-jwt.d.ts +5 -0
  67. package/dist/runtime/schemes/laravel-jwt.mjs +6 -0
  68. package/dist/runtime/schemes/local.d.ts +38 -0
  69. package/dist/runtime/schemes/local.mjs +160 -0
  70. package/dist/runtime/schemes/oauth2.d.ts +61 -0
  71. package/dist/runtime/schemes/oauth2.mjs +374 -0
  72. package/dist/runtime/schemes/openIDConnect.d.ts +24 -0
  73. package/dist/runtime/schemes/openIDConnect.mjs +190 -0
  74. package/dist/runtime/schemes/refresh.d.ts +26 -0
  75. package/dist/runtime/schemes/refresh.mjs +141 -0
  76. package/dist/runtime/token-nitro.d.ts +2 -0
  77. package/dist/runtime/token-nitro.mjs +9 -0
  78. package/dist/types/index.d.ts +42 -0
  79. package/dist/types/openIDConnectConfigurationDocument.d.ts +31 -0
  80. package/dist/types/options.d.ts +125 -0
  81. package/dist/types/provider.d.ts +21 -0
  82. package/dist/types/request.d.ts +8 -0
  83. package/dist/types/router.d.ts +7 -0
  84. package/dist/types/scheme.d.ts +108 -0
  85. package/dist/types/store.d.ts +30 -0
  86. package/dist/types/strategy.d.ts +16 -0
  87. package/dist/types/utils.d.ts +5 -0
  88. package/dist/utils/index.d.ts +28 -0
  89. package/dist/utils/index.mjs +123 -0
  90. package/dist/utils/provider.d.ts +13 -0
  91. package/dist/utils/provider.mjs +360 -0
  92. package/package.json +5 -3
@@ -0,0 +1,1007 @@
1
+ import { addTemplate, addServerHandler, resolvePath, defineNuxtModule, createResolver, installModule, addPluginTemplate, addImports, addRouteMiddleware } from '@nuxt/kit';
2
+ import { serialize } from '@refactorjs/serialize';
3
+ import { join } from 'pathe';
4
+ import { defu } from 'defu';
5
+ import 'jwt-decode';
6
+ import { existsSync } from 'fs';
7
+ import { hash } from 'ohash';
8
+
9
+ const name = "nuxt-auther";
10
+ const version = "1.0.3";
11
+
12
+ const OAUTH2DEFAULTS = {
13
+ accessType: void 0,
14
+ redirectUri: void 0,
15
+ logoutRedirectUri: void 0,
16
+ clientId: void 0,
17
+ clientSecretTransport: "body",
18
+ audience: void 0,
19
+ grantType: void 0,
20
+ responseMode: void 0,
21
+ acrValues: void 0,
22
+ autoLogout: false,
23
+ endpoints: {
24
+ logout: void 0,
25
+ authorization: void 0,
26
+ token: void 0,
27
+ userInfo: void 0
28
+ },
29
+ scope: [],
30
+ token: {
31
+ property: "access_token",
32
+ expiresProperty: "expires_in",
33
+ type: "Bearer",
34
+ name: "Authorization",
35
+ maxAge: false,
36
+ global: true,
37
+ prefix: "_token.",
38
+ expirationPrefix: "_token_expiration."
39
+ },
40
+ idToken: {
41
+ property: "id_token",
42
+ maxAge: 1800,
43
+ prefix: "_id_token.",
44
+ expirationPrefix: "_id_token_expiration.",
45
+ httpOnly: false
46
+ },
47
+ refreshToken: {
48
+ property: "refresh_token",
49
+ maxAge: 60 * 60 * 24 * 30,
50
+ prefix: "_refresh_token.",
51
+ expirationPrefix: "_refresh_token_expiration.",
52
+ httpOnly: false
53
+ },
54
+ user: {
55
+ property: false
56
+ },
57
+ responseType: "token",
58
+ codeChallengeMethod: false,
59
+ clientWindow: false,
60
+ clientWindowWidth: 400,
61
+ clientWindowHeight: 600
62
+ };
63
+ const LOCALDEFAULTS = {
64
+ cookie: {
65
+ name: void 0
66
+ },
67
+ endpoints: {
68
+ csrf: {
69
+ url: "/api/csrf-cookie"
70
+ },
71
+ login: {
72
+ url: "/api/auth/login",
73
+ method: "post"
74
+ },
75
+ logout: {
76
+ url: "/api/auth/logout",
77
+ method: "post"
78
+ },
79
+ user: {
80
+ url: "/api/auth/user",
81
+ method: "get"
82
+ },
83
+ refresh: {
84
+ url: "/api/auth/refresh",
85
+ method: "post"
86
+ }
87
+ },
88
+ token: {
89
+ expiresProperty: "expires_in",
90
+ property: "token",
91
+ type: "Bearer",
92
+ name: "Authorization",
93
+ maxAge: false,
94
+ global: true,
95
+ required: true,
96
+ prefix: "_token.",
97
+ expirationPrefix: "_token_expiration.",
98
+ httpOnly: false
99
+ },
100
+ refreshToken: {
101
+ property: "refresh_token",
102
+ data: "refresh_token",
103
+ maxAge: 60 * 60 * 24 * 30,
104
+ required: true,
105
+ tokenRequired: false,
106
+ prefix: "_refresh_token.",
107
+ expirationPrefix: "_refresh_token_expiration.",
108
+ httpOnly: false
109
+ },
110
+ autoLogout: false,
111
+ user: {
112
+ property: "user",
113
+ autoFetch: true
114
+ },
115
+ clientId: void 0,
116
+ grantType: void 0,
117
+ scope: void 0
118
+ };
119
+ const ProviderAliases = {
120
+ "laravel/jwt": "laravelJWT",
121
+ "laravel/passport": "laravelPassport",
122
+ "laravel/sanctum": "laravelSanctum"
123
+ };
124
+ const BuiltinSchemes = {
125
+ local: "LocalScheme",
126
+ cookie: "CookieScheme",
127
+ refresh: "RefreshScheme",
128
+ laravelJWT: "LaravelJWTScheme",
129
+ oauth2: "Oauth2Scheme",
130
+ openIDConnect: "OpenIDConnectScheme",
131
+ auth0: "Auth0Scheme"
132
+ };
133
+ const LocalSchemes = [
134
+ "local",
135
+ "cookie",
136
+ "refresh",
137
+ "laravelJWT"
138
+ ];
139
+ const OAuth2Schemes = [
140
+ "oauth",
141
+ "openIDConnect",
142
+ "auth0"
143
+ ];
144
+
145
+ function assignDefaults(strategy, defaults) {
146
+ Object.assign(strategy, defu(strategy, defaults));
147
+ }
148
+ function addAuthorize(nuxt, strategy, useForms = false) {
149
+ const clientSecret = strategy.clientSecret;
150
+ const clientId = strategy.clientId;
151
+ const tokenEndpoint = strategy.endpoints.token;
152
+ const audience = strategy.audience;
153
+ delete strategy.clientSecret;
154
+ const endpoint = `/_auth/oauth/${strategy.name}/authorize`;
155
+ strategy.endpoints.token = endpoint;
156
+ strategy.responseType = "code";
157
+ addTemplate({
158
+ filename: `authorize-${strategy.name}.ts`,
159
+ write: true,
160
+ getContents: () => authorizeGrant({
161
+ strategy,
162
+ useForms,
163
+ clientSecret,
164
+ clientId,
165
+ tokenEndpoint,
166
+ audience
167
+ })
168
+ });
169
+ addServerHandler({
170
+ route: endpoint,
171
+ method: "post",
172
+ handler: join(nuxt.options.buildDir, `authorize-${strategy.name}.ts`)
173
+ });
174
+ }
175
+ function addLocalAuthorize(nuxt, strategy) {
176
+ const tokenEndpoint = strategy.endpoints?.login?.url;
177
+ const refreshEndpoint = strategy.endpoints?.refresh?.url;
178
+ const endpoint = `/_auth/local/${strategy.name}/authorize`;
179
+ strategy.endpoints.login.url = endpoint;
180
+ strategy.endpoints.refresh.url = endpoint;
181
+ addTemplate({
182
+ filename: `local-${strategy.name}.ts`,
183
+ write: true,
184
+ getContents: () => localAuthorizeGrant({
185
+ strategy,
186
+ tokenEndpoint,
187
+ refreshEndpoint
188
+ })
189
+ });
190
+ addServerHandler({
191
+ route: endpoint,
192
+ method: "post",
193
+ handler: join(nuxt.options.buildDir, `local-${strategy.name}.ts`)
194
+ });
195
+ }
196
+ function initializePasswordGrantFlow(nuxt, strategy) {
197
+ const clientSecret = strategy.clientSecret;
198
+ const clientId = strategy.clientId;
199
+ const tokenEndpoint = strategy.endpoints.token;
200
+ delete strategy.clientSecret;
201
+ const endpoint = `/_auth/${strategy.name}/token`;
202
+ strategy.endpoints.login.url = endpoint;
203
+ strategy.endpoints.refresh.url = endpoint;
204
+ addTemplate({
205
+ filename: `password-${strategy.name}.ts`,
206
+ write: true,
207
+ getContents: () => passwordGrant({
208
+ strategy,
209
+ clientSecret,
210
+ clientId,
211
+ tokenEndpoint
212
+ })
213
+ });
214
+ addServerHandler({
215
+ route: endpoint,
216
+ method: "post",
217
+ handler: join(nuxt.options.buildDir, `password-${strategy.name}.ts`)
218
+ });
219
+ }
220
+ function assignAbsoluteEndpoints(strategy) {
221
+ const { url, endpoints } = strategy;
222
+ if (endpoints) {
223
+ for (const key of Object.keys(endpoints)) {
224
+ const endpoint = endpoints[key];
225
+ if (endpoint) {
226
+ if (typeof endpoint === "object") {
227
+ if (!endpoint.url || endpoint.url.startsWith(url)) {
228
+ continue;
229
+ }
230
+ endpoints[key].url = url + endpoint.url;
231
+ } else {
232
+ if (endpoint.startsWith(url)) {
233
+ continue;
234
+ }
235
+ endpoints[key] = url + endpoint;
236
+ }
237
+ }
238
+ }
239
+ }
240
+ }
241
+ function authorizeGrant(opt) {
242
+ return `import { defineEventHandler, readBody, createError, getCookie } from 'h3'
243
+ // @ts-expect-error: virtual file
244
+ import { config } from '#nuxt-auth-options'
245
+ import { serialize } from 'cookie-es'
246
+
247
+ const options = ${serialize(opt, { space: 4 })}
248
+
249
+ function addTokenPrefix(token: string | boolean, tokenType: string | false): string | boolean {
250
+ if (!token || !tokenType || typeof token !== 'string' || token.startsWith(tokenType)) {
251
+ return token;
252
+ }
253
+
254
+ return tokenType + ' ' + token;
255
+ }
256
+
257
+ export default defineEventHandler(async (event) => {
258
+ const {
259
+ code,
260
+ code_verifier: codeVerifier,
261
+ redirect_uri: redirectUri = options.strategy.redirectUri,
262
+ response_type: responseType = options.strategy.responseType,
263
+ grant_type: grantType = options.strategy.grantType,
264
+ refresh_token: refreshToken
265
+ } = await readBody(event)
266
+
267
+ const refreshCookieName = config.stores.cookie.prefix + options.strategy?.refreshToken?.prefix + options.strategy.name
268
+ const tokenCookieName = config.stores.cookie.prefix + options.strategy?.token?.prefix + options.strategy.name
269
+ const idTokenCookieName = config.stores.cookie.prefix + options.strategy?.idToken?.prefix + options.strategy.name
270
+ const serverRefreshToken = getCookie(event, refreshCookieName)
271
+
272
+ // Grant type is authorization code, but code is not available
273
+ if (grantType === 'authorization_code' && !code) {
274
+ return createError({
275
+ statusCode: 500,
276
+ message: 'Missing authorization code'
277
+ })
278
+ }
279
+
280
+ // Grant type is refresh token, but refresh token is not available
281
+ if ((grantType === 'refresh_token' && !options.strategy.refreshToken.httpOnly && !refreshToken) || (grantType === 'refresh_token' && options.strategy.refreshToken.httpOnly && !serverRefreshToken)) {
282
+ return createError({
283
+ statusCode: 500,
284
+ message: 'Missing refresh token'
285
+ })
286
+ }
287
+
288
+ let body = {
289
+ client_id: options.clientId,
290
+ client_secret: options.clientSecret,
291
+ refresh_token: options.strategy.refreshToken.httpOnly ? serverRefreshToken : refreshToken,
292
+ grant_type: grantType,
293
+ response_type: responseType,
294
+ redirect_uri: redirectUri,
295
+ audience: options.audience,
296
+ code_verifier: codeVerifier,
297
+ code
298
+ }
299
+
300
+ if (grantType !== 'refresh_token') {
301
+ delete body.refresh_token
302
+ }
303
+
304
+ const headers = {
305
+ Accept: 'application/json',
306
+ 'Content-Type': 'application/json'
307
+ }
308
+
309
+ if (options.strategy.clientSecretTransport === 'authorization_header') {
310
+ // @ts-ignore
311
+ headers['Authorization'] = 'Basic ' + Buffer.from(options.clientId + ':' + options.clientSecret).toString('base64')
312
+ // client_secret is transported in auth header
313
+ delete body.client_secret
314
+ }
315
+
316
+ const response = await $http.post(options.tokenEndpoint, {
317
+ body,
318
+ headers
319
+ })
320
+
321
+ let cookies = event.node.res.getHeader('Set-Cookie') as string[] || [];
322
+
323
+ const refreshCookieValue = response._data?.[options.strategy?.refreshToken?.property]
324
+ if (config.stores.cookie.enabled && refreshCookieValue && options.strategy.refreshToken.httpOnly) {
325
+ const refreshCookie = serialize(refreshCookieName, refreshCookieValue, { ...config.stores.cookie.options, httpOnly: true })
326
+ cookies.push(refreshCookie);
327
+ }
328
+
329
+ const tokenCookieValue = response._data?.[options.strategy?.token?.property]
330
+ if (config.stores.cookie.enabled && tokenCookieValue && options.strategy.token.httpOnly) {
331
+ const token = addTokenPrefix(tokenCookieValue, options.strategy.token.type) as string
332
+ const tokenCookie = serialize(tokenCookieName, token, { ...config.stores.cookie.options, httpOnly: true })
333
+ cookies.push(tokenCookie);
334
+ }
335
+
336
+ const idTokenCookieValue = response._data?.[options.strategy?.idToken?.property]
337
+ if (config.stores.cookie.enabled && idTokenCookieValue && options.strategy.idToken.httpOnly) {
338
+ const idTokenCookie = serialize(idTokenCookieName, token, { ...config.stores.cookie.options, httpOnly: true })
339
+ cookies.push(idTokenCookie);
340
+ }
341
+
342
+ if (cookies.length) {
343
+ event.node.res.setHeader('Set-Cookie', cookies);
344
+ }
345
+
346
+ event.node.res.end(JSON.stringify(response._data))
347
+ })
348
+ `;
349
+ }
350
+ function localAuthorizeGrant(opt) {
351
+ return `import { defineEventHandler, readBody, createError, getCookie, getRequestHeader } from 'h3'
352
+ // @ts-expect-error: virtual file
353
+ import { config } from '#nuxt-auth-options'
354
+ import { serialize } from 'cookie-es'
355
+
356
+ const options = ${serialize(opt, { space: 4 })}
357
+
358
+ function addTokenPrefix(token: string | boolean, tokenType: string | false): string | boolean {
359
+ if (!token || !tokenType || typeof token !== 'string' || token.startsWith(tokenType)) {
360
+ return token;
361
+ }
362
+
363
+ return tokenType + ' ' + token;
364
+ }
365
+
366
+ export default defineEventHandler(async (event) => {
367
+ const requestBody = await readBody(event)
368
+
369
+ const refreshCookieName = config.stores.cookie.prefix + options.strategy?.refreshToken?.prefix + options.strategy.name
370
+ const refreshTokenDataName = options.strategy.refreshToken.data
371
+ const tokenCookieName = config.stores.cookie.prefix + options.strategy?.token?.prefix + options.strategy.name
372
+ const serverRefreshToken = getCookie(event, refreshCookieName)
373
+ const authHeader = getRequestHeader(event, 'authorization')
374
+
375
+ // Grant type is refresh token, but refresh token is not available
376
+ if ((requestBody.grant_type === 'refresh_token' && !options.strategy.refreshToken.httpOnly && !requestBody[refreshTokenDataName]) || (requestBody.grant_type === 'refresh_token' && options.strategy.refreshToken.httpOnly && !serverRefreshToken)) {
377
+ return createError({
378
+ statusCode: 500,
379
+ message: 'Missing refresh token'
380
+ })
381
+ }
382
+
383
+ let body = {
384
+ ...requestBody,
385
+ [refreshTokenDataName]: options.strategy.refreshToken.httpOnly ? serverRefreshToken : requestBody[refreshTokenDataName],
386
+ }
387
+
388
+ if (requestBody.grant_type !== 'refresh_token') {
389
+ delete body[refreshTokenDataName]
390
+ }
391
+
392
+ let headers = {
393
+ 'Content-Type': 'application/json'
394
+ }
395
+
396
+ let response
397
+
398
+ if (body[refreshTokenDataName]) {
399
+ if (options.strategy?.refreshToken?.tokenRequired && authHeader) {
400
+ headers = {
401
+ ...headers,
402
+ // @ts-ignore
403
+ Authorization: authHeader,
404
+ }
405
+ }
406
+
407
+ response = await $http.post(options.refreshEndpoint, {
408
+ body,
409
+ headers: {
410
+ ...headers,
411
+ // @ts-ignore: headers might not be set
412
+ ...options.strategy?.endpoints?.refresh?.headers
413
+ }
414
+ })
415
+ } else {
416
+ response = await $http.post(options.tokenEndpoint, {
417
+ body,
418
+ headers: {
419
+ ...headers,
420
+ // @ts-ignore: headers might not be set
421
+ ...options.strategy?.endpoints?.login?.headers
422
+ }
423
+ })
424
+ }
425
+
426
+ let cookies = event.node.res.getHeader('Set-Cookie') as string[] || [];
427
+
428
+ const refreshCookieValue = response._data?.[options.strategy?.refreshToken?.property]
429
+ if (config.stores.cookie.enabled && refreshCookieValue && options.strategy.refreshToken.httpOnly) {
430
+ const refreshCookie = serialize(refreshCookieName, refreshCookieValue, { ...config.stores.cookie.options, httpOnly: true })
431
+ cookies.push(refreshCookie);
432
+ }
433
+
434
+ const tokenCookieValue = response._data?.[options.strategy?.token?.property]
435
+ if (config.stores.cookie.enabled && tokenCookieValue && options.strategy.token.httpOnly) {
436
+ const token = addTokenPrefix(tokenCookieValue, options.strategy.token.type) as string
437
+ const tokenCookie = serialize(tokenCookieName, token, { ...config.stores.cookie.options, httpOnly: true })
438
+ cookies.push(tokenCookie);
439
+ }
440
+
441
+ if (cookies.length) {
442
+ event.node.res.setHeader('Set-Cookie', cookies);
443
+ }
444
+
445
+ event.node.res.end(JSON.stringify(response._data))
446
+ })
447
+ `;
448
+ }
449
+ function passwordGrant(opt) {
450
+ return `import requrl from 'requrl';
451
+ import { defineEventHandler, readBody, createError } from 'h3';
452
+
453
+ const options = ${serialize(opt, { space: 4 })}
454
+
455
+ export default defineEventHandler(async (event) => {
456
+ const body = await readBody(event)
457
+
458
+ // If \`grant_type\` is not defined, set default value
459
+ if (!body.grant_type) {
460
+ body.grant_type = options.strategy.grantType
461
+ }
462
+
463
+ // If \`client_id\` is not defined, set default value
464
+ if (!body.client_id) {
465
+ body.grant_type = options.clientId
466
+ }
467
+
468
+ // Grant type is password, but username or password is not available
469
+ if (body.grant_type === 'password' && (!body.username || !body.password)) {
470
+ return createError({
471
+ statusCode: 400,
472
+ message: 'Invalid username or password'
473
+ })
474
+ }
475
+
476
+ // Grant type is refresh token, but refresh token is not available
477
+ if (body.grant_type === 'refresh_token' && !body.refresh_token) {
478
+ event.respondWith({ status: 400, body: JSON.stringify({ message: 'Refresh token not provided' }) });
479
+ return createError({
480
+ statusCode: 400,
481
+ message: 'Refresh token not provided'
482
+ })
483
+ }
484
+
485
+ const response = await $http.post(options.tokenEndpoint, {
486
+ baseURL: requrl(event.node.req),
487
+ body: {
488
+ client_id: options.clientId,
489
+ client_secret: options.clientSecret,
490
+ ...body
491
+ },
492
+ headers: {
493
+ Accept: 'application/json'
494
+ }
495
+ })
496
+
497
+ event.node.res.end(JSON.stringify(response._data))
498
+ })
499
+ `;
500
+ }
501
+
502
+ const hasOwn = (object, key) => Object.hasOwn ? Object.hasOwn(object, key) : Object.prototype.hasOwnProperty.call(object, key);
503
+
504
+ function auth0(nuxt, strategy) {
505
+ const DEFAULTS = Object.assign(OAUTH2DEFAULTS, {
506
+ scheme: "auth0",
507
+ endpoints: {
508
+ authorization: `https://${strategy.domain}/authorize`,
509
+ userInfo: `https://${strategy.domain}/userinfo`,
510
+ token: `https://${strategy.domain}/oauth/token`,
511
+ logout: `https://${strategy.domain}/v2/logout`
512
+ },
513
+ scope: ["openid", "profile", "email"]
514
+ });
515
+ assignDefaults(strategy, DEFAULTS);
516
+ }
517
+
518
+ function discord(nuxt, strategy) {
519
+ const DEFAULTS = Object.assign(OAUTH2DEFAULTS, {
520
+ scheme: "oauth2",
521
+ endpoints: {
522
+ authorization: "https://discord.com/api/oauth2/authorize",
523
+ token: "https://discord.com/api/oauth2/token",
524
+ userInfo: "https://discord.com/api/users/@me"
525
+ // logout: 'https://discord.com/api/oauth2/token/revoke' //TODO: add post method, because discord using the post method to logout
526
+ },
527
+ grantType: "authorization_code",
528
+ codeChallengeMethod: "S256",
529
+ scope: ["identify", "email"]
530
+ });
531
+ assignDefaults(strategy, DEFAULTS);
532
+ addAuthorize(nuxt, strategy, true);
533
+ }
534
+
535
+ function facebook(nuxt, strategy) {
536
+ const DEFAULTS = Object.assign(OAUTH2DEFAULTS, {
537
+ scheme: "oauth2",
538
+ endpoints: {
539
+ authorization: "https://facebook.com/v2.12/dialog/oauth",
540
+ userInfo: "https://graph.facebook.com/v2.12/me?fields=about,name,picture{url},email"
541
+ },
542
+ scope: ["public_profile", "email"]
543
+ });
544
+ assignDefaults(strategy, DEFAULTS);
545
+ }
546
+
547
+ function github(nuxt, strategy) {
548
+ const DEFAULTS = Object.assign(OAUTH2DEFAULTS, {
549
+ scheme: "oauth2",
550
+ endpoints: {
551
+ authorization: "https://github.com/login/oauth/authorize",
552
+ token: "https://github.com/login/oauth/access_token",
553
+ userInfo: "https://api.github.com/user"
554
+ },
555
+ scope: ["user", "email"]
556
+ });
557
+ assignDefaults(strategy, DEFAULTS);
558
+ addAuthorize(nuxt, strategy);
559
+ }
560
+
561
+ function google(nuxt, strategy) {
562
+ const DEFAULTS = Object.assign(OAUTH2DEFAULTS, {
563
+ scheme: "oauth2",
564
+ endpoints: {
565
+ authorization: "https://accounts.google.com/o/oauth2/v2/auth",
566
+ userInfo: "https://www.googleapis.com/oauth2/v3/userinfo"
567
+ },
568
+ scope: ["openid", "profile", "email"]
569
+ });
570
+ assignDefaults(strategy, DEFAULTS);
571
+ }
572
+
573
+ function laravelJWT(nuxt, strategy) {
574
+ const { url } = strategy;
575
+ if (!url) {
576
+ throw new Error("url is required for laravel jwt!");
577
+ }
578
+ const DEFAULTS = Object.assign(LOCALDEFAULTS, {
579
+ name: "laravelJWT",
580
+ scheme: "laravelJWT",
581
+ endpoints: {
582
+ login: {
583
+ url: url + "/api/auth/login"
584
+ },
585
+ refresh: {
586
+ url: url + "/api/auth/refresh"
587
+ },
588
+ logout: {
589
+ url: url + "/api/auth/logout"
590
+ },
591
+ user: {
592
+ url: url + "/api/auth/user"
593
+ }
594
+ },
595
+ token: {
596
+ property: "access_token",
597
+ maxAge: 3600
598
+ },
599
+ refreshToken: {
600
+ property: false,
601
+ data: false,
602
+ maxAge: 1209600,
603
+ required: false,
604
+ tokenRequired: true
605
+ },
606
+ user: {
607
+ property: false
608
+ },
609
+ clientId: false,
610
+ grantType: false
611
+ });
612
+ assignDefaults(strategy, DEFAULTS);
613
+ assignAbsoluteEndpoints(strategy);
614
+ if (strategy.ssr) {
615
+ addLocalAuthorize(nuxt, strategy);
616
+ }
617
+ }
618
+
619
+ function isPasswordGrant(strategy) {
620
+ return strategy.grantType === "password";
621
+ }
622
+ function laravelPassport(nuxt, strategy) {
623
+ const { url } = strategy;
624
+ if (!url) {
625
+ throw new Error("url is required is laravel passport!");
626
+ }
627
+ const defaults = Object.assign(LOCALDEFAULTS, {
628
+ name: "laravelPassport",
629
+ token: {
630
+ property: "access_token",
631
+ type: "Bearer",
632
+ name: "Authorization",
633
+ maxAge: 60 * 60 * 24 * 365
634
+ },
635
+ refreshToken: {
636
+ property: "refresh_token",
637
+ data: "refresh_token",
638
+ maxAge: 60 * 60 * 24 * 30
639
+ },
640
+ user: {
641
+ property: false
642
+ }
643
+ });
644
+ let DEFAULTS;
645
+ if (isPasswordGrant(strategy)) {
646
+ DEFAULTS = {
647
+ ...defaults,
648
+ scheme: "refresh",
649
+ endpoints: {
650
+ token: url + "/oauth/token",
651
+ login: {
652
+ baseURL: ""
653
+ },
654
+ refresh: {
655
+ baseURL: ""
656
+ },
657
+ logout: false,
658
+ user: {
659
+ url: url + "/api/auth/user"
660
+ }
661
+ },
662
+ grantType: "password"
663
+ };
664
+ assignDefaults(strategy, DEFAULTS);
665
+ assignAbsoluteEndpoints(strategy);
666
+ initializePasswordGrantFlow(nuxt, strategy);
667
+ } else {
668
+ DEFAULTS = {
669
+ ...defaults,
670
+ scheme: "oauth2",
671
+ endpoints: {
672
+ authorization: url + "/oauth/authorize",
673
+ token: url + "/oauth/token",
674
+ userInfo: url + "/api/auth/user",
675
+ logout: false
676
+ },
677
+ responseType: "code",
678
+ grantType: "authorization_code",
679
+ scope: "*"
680
+ };
681
+ assignDefaults(strategy, DEFAULTS);
682
+ assignAbsoluteEndpoints(strategy);
683
+ addAuthorize(nuxt, strategy);
684
+ }
685
+ }
686
+
687
+ function laravelSanctum(nuxt, strategy) {
688
+ const { url } = strategy;
689
+ if (!url) {
690
+ throw new Error("URL is required with Laravel Sanctum!");
691
+ }
692
+ const endpointDefaults = {
693
+ credentials: "include"
694
+ };
695
+ const DEFAULTS = Object.assign(LOCALDEFAULTS, {
696
+ scheme: "cookie",
697
+ name: "laravelSanctum",
698
+ cookie: {
699
+ name: "XSRF-TOKEN"
700
+ },
701
+ endpoints: {
702
+ csrf: {
703
+ ...endpointDefaults,
704
+ url: "/sanctum/csrf-cookie"
705
+ },
706
+ login: {
707
+ ...endpointDefaults,
708
+ url: "/login"
709
+ },
710
+ refresh: {
711
+ ...endpointDefaults,
712
+ url: "/refresh"
713
+ },
714
+ logout: {
715
+ ...endpointDefaults,
716
+ url: "/logout"
717
+ },
718
+ user: {
719
+ ...endpointDefaults,
720
+ url: "/api/user"
721
+ }
722
+ },
723
+ user: {
724
+ property: false,
725
+ autoFetch: true
726
+ },
727
+ token: {
728
+ type: "Bearer"
729
+ }
730
+ });
731
+ assignDefaults(strategy, DEFAULTS);
732
+ assignAbsoluteEndpoints(strategy);
733
+ if (strategy.ssr) {
734
+ addLocalAuthorize(nuxt, strategy);
735
+ }
736
+ }
737
+
738
+ const AUTH_PROVIDERS = {
739
+ __proto__: null,
740
+ auth0: auth0,
741
+ discord: discord,
742
+ facebook: facebook,
743
+ github: github,
744
+ google: google,
745
+ laravelJWT: laravelJWT,
746
+ laravelPassport: laravelPassport,
747
+ laravelSanctum: laravelSanctum
748
+ };
749
+
750
+ async function resolveStrategies(nuxt, options) {
751
+ const strategies = [];
752
+ const strategyScheme = {};
753
+ for (const name of Object.keys(options.strategies)) {
754
+ if (!options.strategies?.[name] || options.strategies?.[name].enabled === false) {
755
+ continue;
756
+ }
757
+ const strategy = Object.assign({}, options.strategies[name]);
758
+ if (!strategy.name) {
759
+ strategy.name = name;
760
+ }
761
+ if (!strategy.provider) {
762
+ strategy.provider = strategy.name;
763
+ }
764
+ if (hasOwn(strategy, "ssr")) {
765
+ strategy.ssr = strategy.ssr;
766
+ } else {
767
+ strategy.ssr = nuxt.options.ssr;
768
+ }
769
+ const provider = await resolveProvider(strategy.provider, nuxt, strategy);
770
+ delete strategy.provider;
771
+ if (typeof provider === "function") {
772
+ provider(nuxt, strategy);
773
+ }
774
+ if (!strategy.scheme) {
775
+ strategy.scheme = strategy.name;
776
+ }
777
+ try {
778
+ const schemeImport = await resolveScheme(strategy.scheme);
779
+ delete strategy.scheme;
780
+ strategyScheme[strategy.name] = schemeImport;
781
+ strategies.push(strategy);
782
+ } catch (e) {
783
+ console.error(`[Auth] Error resolving strategy ${strategy.name}: ${e}`);
784
+ }
785
+ }
786
+ return {
787
+ strategies,
788
+ strategyScheme
789
+ };
790
+ }
791
+ async function resolveScheme(scheme) {
792
+ if (typeof scheme !== "string") {
793
+ return;
794
+ }
795
+ if (BuiltinSchemes[scheme]) {
796
+ return {
797
+ name: BuiltinSchemes[scheme],
798
+ as: BuiltinSchemes[scheme],
799
+ from: "#auth/runtime"
800
+ };
801
+ }
802
+ const path = await resolvePath(scheme);
803
+ if (existsSync(path)) {
804
+ const _path = path.replace(/\\/g, "/");
805
+ return {
806
+ name: "default",
807
+ as: "Scheme$" + hash({ path: _path }),
808
+ from: _path
809
+ };
810
+ }
811
+ }
812
+ async function resolveProvider(provider, nuxt, strategy) {
813
+ provider = ProviderAliases[provider] || provider;
814
+ if (AUTH_PROVIDERS[provider]) {
815
+ return AUTH_PROVIDERS[provider];
816
+ }
817
+ if (typeof provider === "function") {
818
+ return provider(nuxt, strategy);
819
+ }
820
+ if (typeof provider === "string") {
821
+ return (nuxt2, strategy2) => {
822
+ if (OAuth2Schemes.includes(strategy2.scheme) && strategy2.ssr) {
823
+ assignDefaults(strategy2, OAUTH2DEFAULTS);
824
+ addAuthorize(nuxt2, strategy2, true);
825
+ }
826
+ if (LocalSchemes.includes(strategy2.scheme) && strategy2.ssr) {
827
+ assignDefaults(strategy2, LOCALDEFAULTS);
828
+ if (strategy2.url) {
829
+ assignAbsoluteEndpoints(strategy2);
830
+ }
831
+ addLocalAuthorize(nuxt2, strategy2);
832
+ }
833
+ };
834
+ }
835
+ }
836
+
837
+ const moduleDefaults = {
838
+ // -- Enable Global Middleware --
839
+ globalMiddleware: false,
840
+ enableMiddleware: true,
841
+ // -- Error handling --
842
+ resetOnError: false,
843
+ resetOnResponseError: false,
844
+ ignoreExceptions: false,
845
+ // -- Authorization --
846
+ scopeKey: "scope",
847
+ // -- Redirects --
848
+ rewriteRedirects: true,
849
+ fullPathRedirect: false,
850
+ redirectStrategy: "storage",
851
+ watchLoggedIn: true,
852
+ tokenValidationInterval: false,
853
+ redirect: {
854
+ login: "/login",
855
+ logout: "/",
856
+ home: "/",
857
+ callback: "/login"
858
+ },
859
+ stores: {
860
+ state: {
861
+ namespace: "auth"
862
+ },
863
+ pinia: {
864
+ enabled: false,
865
+ namespace: "auth"
866
+ },
867
+ cookie: {
868
+ enabled: true,
869
+ prefix: "auth.",
870
+ options: {
871
+ path: "/",
872
+ sameSite: "lax",
873
+ maxAge: 31536e3
874
+ }
875
+ },
876
+ local: {
877
+ enabled: false,
878
+ prefix: "auth."
879
+ },
880
+ session: {
881
+ enabled: false,
882
+ prefix: "auth."
883
+ }
884
+ },
885
+ // -- Strategies --
886
+ defaultStrategy: void 0,
887
+ strategies: {}
888
+ };
889
+
890
+ const getAuthPlugin = (options) => {
891
+ return `import { Auth, ExpiredAuthSessionError } from '#auth/runtime'
892
+ import { defineNuxtPlugin, useRuntimeConfig } from '#imports'
893
+ import { defu } from 'defu';
894
+
895
+ // Active schemes
896
+ ${options.schemeImports.map((i) => `import { ${i.name}${i.name !== i.as ? " as " + i.as : ""} } from '${i.from}'`).join("\n")}
897
+
898
+ // Options
899
+ let options = ${serialize(options.options, { space: 4 })}
900
+
901
+ export default defineNuxtPlugin({
902
+ name: 'nuxt-alt:auth',
903
+ async setup(nuxtApp) {
904
+ // Create a new Auth instance
905
+ const auth = new Auth(nuxtApp, options)
906
+
907
+ // Register strategies
908
+ ${options.strategies.map((strategy) => {
909
+ const scheme = options.strategyScheme[strategy.name];
910
+ const schemeOptions = JSON.stringify(strategy);
911
+ return `auth.registerStrategy('${strategy.name}', new ${scheme.as}(auth, defu(useRuntimeConfig()?.public?.auth?.strategies?.['${strategy.name}'], ${schemeOptions})))`;
912
+ }).join(";\n")}
913
+
914
+ nuxtApp.provide('auth', auth)
915
+
916
+ return auth.init()
917
+ .catch(error => {
918
+ if (process.client) {
919
+ // Don't console log expired auth session errors. This error is common, and expected to happen.
920
+ // The error happens whenever the user does an ssr request (reload/initial navigation) with an expired refresh
921
+ // token. We don't want to log this as an error.
922
+ if (error instanceof ExpiredAuthSessionError) {
923
+ return
924
+ }
925
+
926
+ console.error('[ERROR] [AUTH]', error)
927
+ }
928
+ })
929
+ }
930
+ })`;
931
+ };
932
+
933
+ const CONFIG_KEY = "auth";
934
+ const module = defineNuxtModule({
935
+ meta: {
936
+ name,
937
+ version,
938
+ configKey: CONFIG_KEY,
939
+ compatibility: {
940
+ nuxt: "^3.0.0"
941
+ }
942
+ },
943
+ defaults: ({ options }) => ({
944
+ ...moduleDefaults,
945
+ stores: {
946
+ cookie: {
947
+ secure: options.dev ? false : true
948
+ }
949
+ }
950
+ }),
951
+ async setup(moduleOptions, nuxt) {
952
+ const resolver = createResolver(import.meta.url);
953
+ const runtime = resolver.resolve("runtime");
954
+ const options = defu(nuxt.options.runtimeConfig[CONFIG_KEY], moduleOptions, moduleDefaults);
955
+ const { strategies, strategyScheme } = await resolveStrategies(nuxt, options);
956
+ delete options.strategies;
957
+ const uniqueImports = /* @__PURE__ */ new Set();
958
+ const schemeImports = Object.values(strategyScheme).filter((i) => {
959
+ if (uniqueImports.has(i.as)) {
960
+ return false;
961
+ }
962
+ uniqueImports.add(i.as);
963
+ return true;
964
+ });
965
+ options.defaultStrategy = options.defaultStrategy || strategies.length ? strategies[0].name : "";
966
+ nuxt.hook("nitro:config", (config) => {
967
+ config.virtual = config.virtual || {};
968
+ config.virtual["#nuxt-auth-options"] = `export const config = ${serialize(options, { space: 4 })}`;
969
+ });
970
+ if (!nuxt.options.modules.includes("@nuxt-alt/http")) {
971
+ installModule("@nuxt-alt/http");
972
+ }
973
+ addPluginTemplate({
974
+ getContents: () => getAuthPlugin({ options, strategies, strategyScheme, schemeImports }),
975
+ filename: "auth.plugin.mjs"
976
+ });
977
+ addImports([
978
+ { from: resolver.resolve("runtime/composables"), name: "useAuth" }
979
+ ]);
980
+ nuxt.options.alias["#auth/runtime"] = runtime;
981
+ const providers = resolver.resolve("runtime/providers");
982
+ nuxt.options.alias["#auth/providers"] = providers;
983
+ const utils = resolver.resolve("utils");
984
+ nuxt.options.alias["#auth/utils"] = utils;
985
+ nuxt.options.build.transpile.push(runtime, providers, utils);
986
+ if (nuxt.options.ssr) {
987
+ addServerHandler({
988
+ route: "/_auth/reset",
989
+ method: "post",
990
+ handler: resolver.resolve(runtime, "token-nitro")
991
+ });
992
+ }
993
+ if (options.enableMiddleware) {
994
+ addRouteMiddleware({
995
+ name: "auth",
996
+ path: resolver.resolve("runtime/core/middleware"),
997
+ global: options.globalMiddleware
998
+ }, { override: true });
999
+ }
1000
+ if (options.plugins) {
1001
+ options.plugins.forEach((p) => nuxt.options.plugins.push(p));
1002
+ delete options.plugins;
1003
+ }
1004
+ }
1005
+ });
1006
+
1007
+ export { module as default };