@netlify/identity 0.4.2 → 1.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 +95 -22
- package/dist/index.cjs +32 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +123 -34
- package/dist/index.d.ts +123 -34
- package/dist/index.js +30 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,33 +3,35 @@
|
|
|
3
3
|
A lightweight, no-config headless authentication library for projects using Netlify Identity. Works in both browser and server contexts.
|
|
4
4
|
This is NOT the Netlify Identity Widget. This library exports standalone async functions (e.g., import { login, getUser } from '@netlify/identity'). There is no class to instantiate and no .init() call. Just import the functions you need and call them.
|
|
5
5
|
|
|
6
|
-
> **Status:** Beta. The API may change before 1.0.
|
|
7
|
-
|
|
8
6
|
**Prerequisites:**
|
|
9
7
|
|
|
10
|
-
- [Netlify Identity](https://docs.netlify.com/security/secure-access-to-sites/identity/) must be enabled on your Netlify project
|
|
8
|
+
- [Netlify Identity](https://docs.netlify.com/security/secure-access-to-sites/identity/) must be enabled on your Netlify project. This happens automatically when running within a [Netlify Agent Runner](https://docs.netlify.com/agent-runner/overview/)
|
|
11
9
|
- **Server-side** functions (`getUser`, `login`, `admin.*`, etc.) require [Netlify Functions](https://docs.netlify.com/build/functions/get-started/) (modern/v2, with `export default`) or [Edge Functions](https://docs.netlify.com/edge-functions/overview/). [Lambda-compatible functions](https://docs.netlify.com/build/functions/lambda-compatibility/) (v1, with `export { handler }`) are **not supported**
|
|
12
10
|
- For local development, use [`netlify dev`](https://docs.netlify.com/cli/local-development/) so the Identity endpoint is available
|
|
13
11
|
|
|
14
12
|
## How this library relates to other Netlify auth packages
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
|
14
|
+
`@netlify/identity` is the recommended library for all new projects. It works in both browser and server contexts, handles cookie management, and normalizes the user object.
|
|
15
|
+
|
|
16
|
+
You may encounter two older packages in existing code or documentation:
|
|
17
|
+
|
|
18
|
+
| Package | Status | What it was |
|
|
19
|
+
| ------------------------------------------------------------------------------- | -------------------------------- | --------------------------------------------- |
|
|
20
|
+
| [`netlify-identity-widget`](https://github.com/netlify/netlify-identity-widget) | Not recommended for new projects | Pre-built login/signup modal with built-in UI |
|
|
21
|
+
| [`gotrue-js`](https://github.com/netlify/gotrue-js) | Not recommended for new projects | Low-level GoTrue HTTP client (browser only) |
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
If you need a pre-built login UI, the widget still works. For everything else (custom UI, server-side auth, admin operations, framework integration), use `@netlify/identity`.
|
|
23
24
|
|
|
24
25
|
## Table of contents
|
|
25
26
|
|
|
26
27
|
- [Installation](#installation)
|
|
27
28
|
- [Quick start](#quick-start)
|
|
28
29
|
- [API](#api)
|
|
29
|
-
- [Functions](#functions) -- `getUser`, `login`, `signup`, `logout`, `oauthLogin`, `handleAuthCallback`, `onAuthChange`, `hydrateSession`, `refreshSession`, and more
|
|
30
|
+
- [Functions](#functions) -- `getUser`, `login`, `signup`, `logout`, `oauthLogin`, `handleAuthCallback`, `onAuthChange`, `hydrateSession`, `refreshSession`, `verifyRequestOrigin`, and more
|
|
30
31
|
- [Admin Operations](#admin-operations) -- `admin.listUsers`, `admin.getUser`, `admin.createUser`, `admin.updateUser`, `admin.deleteUser`
|
|
31
|
-
- [Types](#types) -- `User`, `AuthEvent`, `CallbackResult`, `Settings`, `Admin`, `ListUsersOptions`, `CreateUserParams`, etc.
|
|
32
|
+
- [Types](#types) -- `User`, `AuthEvent`, `CallbackResult`, `Settings`, `Admin`, `ListUsersOptions`, `CreateUserParams`, `VerifyRequestOriginOptions`, etc.
|
|
32
33
|
- [Errors](#errors) -- `AuthError`, `MissingIdentityError`
|
|
34
|
+
- [Security: CSRF protection](#security-csrf-protection)
|
|
33
35
|
- [Framework integration](#framework-integration) -- Next.js, Remix, TanStack Start, Astro, SvelteKit
|
|
34
36
|
- [Guides](#guides)
|
|
35
37
|
- [React `useAuth` hook](#react-useauth-hook)
|
|
@@ -97,7 +99,7 @@ export default async (req: Request, context: Context) => {
|
|
|
97
99
|
getUser(): Promise<User | null>
|
|
98
100
|
```
|
|
99
101
|
|
|
100
|
-
Returns the current authenticated user, or `null` if not logged in. Returns the best available normalized `User` from the current context.
|
|
102
|
+
Returns the current authenticated user, or `null` if not logged in. Returns the best available normalized `User` from the current context. When the Identity API is reachable, most persisted and profile fields are populated, but state-dependent fields (invite, recovery, email-change) may still be `undefined` if the user is not in that state. When falling back to JWT claims (e.g., Identity API unreachable), only `id`, `email`, `provider`, `name`, `pictureUrl`, `roles`, `userMetadata`, and `appMetadata` are available. Never throws.
|
|
101
103
|
|
|
102
104
|
> **Next.js note:** Calling `getUser()` in a Server Component opts the page into [dynamic rendering](https://nextjs.org/docs/app/building-your-application/rendering/server-components#dynamic-rendering) because it reads cookies. This is expected and correct for authenticated pages. Next.js handles the internal dynamic rendering signal automatically.
|
|
103
105
|
|
|
@@ -173,7 +175,7 @@ oauthLogin(provider: string): never
|
|
|
173
175
|
|
|
174
176
|
Redirects to an OAuth provider. The page navigates away, so this function never returns normally. Browser only.
|
|
175
177
|
|
|
176
|
-
The `provider` argument should be one of the `AuthProvider` values: `'google'`, `'github'`, `'gitlab'`, `'bitbucket'`,
|
|
178
|
+
The `provider` argument should be one of the `AuthProvider` values: `'google'`, `'github'`, `'gitlab'`, `'bitbucket'`, or `'facebook'`.
|
|
177
179
|
|
|
178
180
|
**Throws:** `MissingIdentityError` if Identity is not configured. `AuthError` if called on the server.
|
|
179
181
|
|
|
@@ -241,6 +243,20 @@ export async function onRequest(context, next) {
|
|
|
241
243
|
}
|
|
242
244
|
```
|
|
243
245
|
|
|
246
|
+
#### `verifyRequestOrigin`
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
verifyRequestOrigin(request: Request, options?: VerifyRequestOriginOptions): void
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
CSRF protection helper for server-side endpoints that call `login()`, `signup()`, or `logout()`. Compares the request's `Origin` header against the request's own origin (or an explicit allowlist via `options.allowedOrigins`) and throws if they don't match. Server-only.
|
|
253
|
+
|
|
254
|
+
The check runs unconditionally on every call: any HTTP method, with or without an `Origin` header. If you don't want the check on a particular route, don't call the helper there.
|
|
255
|
+
|
|
256
|
+
**Throws:** `AuthError` with status `403` when the request has no `Origin` header. `AuthError` with status `403` when the request's `Origin` is not in the allowed origins.
|
|
257
|
+
|
|
258
|
+
See [Security: CSRF protection](#security-csrf-protection) for the full threat model and per-framework guidance.
|
|
259
|
+
|
|
244
260
|
#### `requestPasswordRecovery`
|
|
245
261
|
|
|
246
262
|
```ts
|
|
@@ -361,7 +377,7 @@ Gets a single user by ID.
|
|
|
361
377
|
admin.createUser(params: CreateUserParams): Promise<User>
|
|
362
378
|
```
|
|
363
379
|
|
|
364
|
-
Creates a new user. The user is auto-confirmed. Optional `data` forwards allowed fields (`role`, `
|
|
380
|
+
Creates a new user. The user is auto-confirmed. Optional `data` forwards allowed fields (`role`, `app_metadata`, `user_metadata`) to the request body. Other keys are silently ignored. `data` cannot override `email`, `password`, or `confirm`.
|
|
365
381
|
|
|
366
382
|
**Throws:** `AuthError` if called from a browser, the email already exists, or the operator token is missing.
|
|
367
383
|
|
|
@@ -393,16 +409,22 @@ Deletes a user by ID.
|
|
|
393
409
|
interface User {
|
|
394
410
|
id: string
|
|
395
411
|
email?: string
|
|
396
|
-
|
|
412
|
+
confirmedAt?: string
|
|
397
413
|
createdAt?: string
|
|
398
414
|
updatedAt?: string
|
|
415
|
+
role?: string
|
|
399
416
|
provider?: AuthProvider
|
|
400
417
|
name?: string
|
|
401
418
|
pictureUrl?: string
|
|
402
419
|
roles?: string[]
|
|
403
|
-
|
|
420
|
+
invitedAt?: string
|
|
421
|
+
confirmationSentAt?: string
|
|
422
|
+
recoverySentAt?: string
|
|
423
|
+
pendingEmail?: string
|
|
424
|
+
emailChangeSentAt?: string
|
|
425
|
+
lastSignInAt?: string
|
|
426
|
+
userMetadata?: Record<string, unknown>
|
|
404
427
|
appMetadata?: Record<string, unknown>
|
|
405
|
-
rawGoTrueData?: Record<string, unknown>
|
|
406
428
|
}
|
|
407
429
|
```
|
|
408
430
|
|
|
@@ -428,7 +450,7 @@ interface IdentityConfig {
|
|
|
428
450
|
#### `AuthProvider`
|
|
429
451
|
|
|
430
452
|
```ts
|
|
431
|
-
type AuthProvider = 'google' | 'github' | 'gitlab' | 'bitbucket' | 'facebook' | '
|
|
453
|
+
type AuthProvider = 'google' | 'github' | 'gitlab' | 'bitbucket' | 'facebook' | 'email'
|
|
432
454
|
```
|
|
433
455
|
|
|
434
456
|
#### `UserUpdates`
|
|
@@ -451,14 +473,13 @@ interface AdminUserUpdates {
|
|
|
451
473
|
email?: string
|
|
452
474
|
password?: string
|
|
453
475
|
role?: string
|
|
454
|
-
aud?: string
|
|
455
476
|
confirm?: boolean
|
|
456
477
|
app_metadata?: Record<string, unknown>
|
|
457
478
|
user_metadata?: Record<string, unknown>
|
|
458
479
|
}
|
|
459
480
|
```
|
|
460
481
|
|
|
461
|
-
Fields accepted by `admin.updateUser()`. Unlike `UserUpdates`, admin updates can set `role`,
|
|
482
|
+
Fields accepted by `admin.updateUser()`. Unlike `UserUpdates`, admin updates can set `role`, force-confirm a user, and write to `app_metadata`. Only these typed fields are forwarded.
|
|
462
483
|
|
|
463
484
|
#### `SignupData`
|
|
464
485
|
|
|
@@ -499,7 +520,7 @@ interface CreateUserParams {
|
|
|
499
520
|
}
|
|
500
521
|
```
|
|
501
522
|
|
|
502
|
-
Parameters for `admin.createUser()`. Optional `data` forwards allowed fields (`role`, `
|
|
523
|
+
Parameters for `admin.createUser()`. Optional `data` forwards allowed fields (`role`, `app_metadata`, `user_metadata`) to the request body. Other keys are silently ignored.
|
|
503
524
|
|
|
504
525
|
#### `Admin`
|
|
505
526
|
|
|
@@ -563,6 +584,16 @@ The `token` field is only present for `invite` callbacks, where the user hasn't
|
|
|
563
584
|
|
|
564
585
|
For all other types (`oauth`, `confirmation`, `recovery`, `email_change`), the user is logged in directly and `token` is not set.
|
|
565
586
|
|
|
587
|
+
#### `VerifyRequestOriginOptions`
|
|
588
|
+
|
|
589
|
+
```ts
|
|
590
|
+
interface VerifyRequestOriginOptions {
|
|
591
|
+
allowedOrigins?: string[]
|
|
592
|
+
}
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Options for [`verifyRequestOrigin`](#verifyrequestorigin). When `allowedOrigins` is set, the list replaces the default same-origin check, so include the request's own origin if you still want it allowed. Each value is a full origin string with scheme and host (`'https://example.com'`).
|
|
596
|
+
|
|
566
597
|
### Errors
|
|
567
598
|
|
|
568
599
|
#### `AuthError`
|
|
@@ -582,6 +613,45 @@ class MissingIdentityError extends Error {}
|
|
|
582
613
|
|
|
583
614
|
Thrown when Identity is not configured in the current environment.
|
|
584
615
|
|
|
616
|
+
## Security: CSRF protection
|
|
617
|
+
|
|
618
|
+
If you expose server-side `login()`, `signup()`, or `logout()` through an HTTP endpoint, that endpoint needs Cross-Site Request Forgery (CSRF) protection. The library cannot enforce this itself because it only sees the email and password arguments handed to it, not the incoming request.
|
|
619
|
+
|
|
620
|
+
**Why it matters.** A specific flavor called _login CSRF_ lets an attacker trick a victim's browser into logging into the attacker's account. The victim then performs actions inside that session (saving payment info, linking third-party services, uploading content), and the attacker harvests the result later by signing in with the credentials they always controlled. `SameSite=Lax` cookies do not catch this attack because the session is being created on the victim's browser, not ridden from an existing one.
|
|
621
|
+
|
|
622
|
+
### `verifyRequestOrigin`
|
|
623
|
+
|
|
624
|
+
`verifyRequestOrigin(request, options?)` compares the request's `Origin` header against the request's own origin (or an explicit allowlist) and throws `AuthError` with status 403 on mismatch. Call it at the start of any handler that performs an auth mutation.
|
|
625
|
+
|
|
626
|
+
```ts
|
|
627
|
+
// netlify/functions/login.ts
|
|
628
|
+
import { login, verifyRequestOrigin } from '@netlify/identity'
|
|
629
|
+
import type { Context } from '@netlify/functions'
|
|
630
|
+
|
|
631
|
+
export default async (req: Request, context: Context) => {
|
|
632
|
+
verifyRequestOrigin(req)
|
|
633
|
+
const { email, password } = await req.json()
|
|
634
|
+
await login(email, password)
|
|
635
|
+
return new Response(null, { status: 302, headers: { Location: '/dashboard' } })
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
The helper runs unconditionally on every call. It checks any HTTP method, with or without an `Origin` header. If you don't want the check on a particular route, don't call the helper there.
|
|
640
|
+
|
|
641
|
+
### Custom allowed origins
|
|
642
|
+
|
|
643
|
+
By default, the helper accepts only the request's own origin. Pass `allowedOrigins` to allow additional trusted origins (for example, a separate frontend domain that POSTs to an API on another domain). The list replaces the default, so include the request's own origin if you still want it allowed:
|
|
644
|
+
|
|
645
|
+
```ts
|
|
646
|
+
verifyRequestOrigin(req, {
|
|
647
|
+
allowedOrigins: ['https://app.example.com', 'https://www.example.com'],
|
|
648
|
+
})
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
### When to call the helper
|
|
652
|
+
|
|
653
|
+
Some frameworks check the request's `Origin` on state-changing requests by default; others don't. Check your framework's documentation. If same-origin enforcement is already on by default for the endpoint where you invoke `login()` / `signup()` / `logout()`, calling `verifyRequestOrigin` yourself is redundant. If it isn't, call `verifyRequestOrigin(request)` at the start of the handler before invoking the auth function.
|
|
654
|
+
|
|
585
655
|
## Framework integration
|
|
586
656
|
|
|
587
657
|
### Recommended pattern for SSR frameworks
|
|
@@ -655,11 +725,12 @@ Use `window.location.href` instead of Next.js `redirect()` after server-side aut
|
|
|
655
725
|
|
|
656
726
|
```tsx
|
|
657
727
|
// app/routes/login.tsx
|
|
658
|
-
import { login } from '@netlify/identity'
|
|
728
|
+
import { login, verifyRequestOrigin } from '@netlify/identity'
|
|
659
729
|
import { redirect, json } from '@remix-run/node'
|
|
660
730
|
import type { ActionFunctionArgs } from '@remix-run/node'
|
|
661
731
|
|
|
662
732
|
export async function action({ request }: ActionFunctionArgs) {
|
|
733
|
+
verifyRequestOrigin(request)
|
|
663
734
|
const formData = await request.formData()
|
|
664
735
|
const email = formData.get('email') as string
|
|
665
736
|
const password = formData.get('password') as string
|
|
@@ -687,6 +758,8 @@ export async function loader() {
|
|
|
687
758
|
|
|
688
759
|
Remix `redirect()` works after server-side `login()` because Remix actions return real HTTP responses. The browser receives a 302 with the `Set-Cookie` header already applied, so the next request includes the auth cookie. This is different from Next.js, where `redirect()` in a Server Action triggers a client-side (soft) navigation that may not include newly-set cookies.
|
|
689
760
|
|
|
761
|
+
> The example calls [`verifyRequestOrigin`](#verifyrequestorigin) at the top of the action. See [Security: CSRF protection](#security-csrf-protection) for when this is needed.
|
|
762
|
+
|
|
690
763
|
### TanStack Start
|
|
691
764
|
|
|
692
765
|
**Login from the browser (recommended):**
|
package/dist/index.cjs
CHANGED
|
@@ -51,12 +51,13 @@ __export(index_exports, {
|
|
|
51
51
|
requestPasswordRecovery: () => requestPasswordRecovery,
|
|
52
52
|
signup: () => signup,
|
|
53
53
|
updateUser: () => updateUser,
|
|
54
|
-
verifyEmailChange: () => verifyEmailChange
|
|
54
|
+
verifyEmailChange: () => verifyEmailChange,
|
|
55
|
+
verifyRequestOrigin: () => verifyRequestOrigin
|
|
55
56
|
});
|
|
56
57
|
module.exports = __toCommonJS(index_exports);
|
|
57
58
|
|
|
58
59
|
// src/types.ts
|
|
59
|
-
var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "
|
|
60
|
+
var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "email"];
|
|
60
61
|
|
|
61
62
|
// src/environment.ts
|
|
62
63
|
var import_gotrue_js = __toESM(require("gotrue-js"), 1);
|
|
@@ -681,6 +682,7 @@ var hydrateSession = async () => {
|
|
|
681
682
|
|
|
682
683
|
// src/user.ts
|
|
683
684
|
var toAuthProvider = (value) => typeof value === "string" && AUTH_PROVIDERS.includes(value) ? value : void 0;
|
|
685
|
+
var toOptionalString = (value) => typeof value === "string" && value !== "" ? value : void 0;
|
|
684
686
|
var toRoles = (appMeta) => {
|
|
685
687
|
const roles = appMeta.roles;
|
|
686
688
|
if (Array.isArray(roles) && roles.every((r) => typeof r === "string")) {
|
|
@@ -693,20 +695,25 @@ var toUser = (userData) => {
|
|
|
693
695
|
const appMeta = userData.app_metadata ?? {};
|
|
694
696
|
const name = userMeta.full_name || userMeta.name;
|
|
695
697
|
const pictureUrl = userMeta.avatar_url;
|
|
696
|
-
const { token: _token, ...safeUserData } = userData;
|
|
697
698
|
return {
|
|
698
699
|
id: userData.id,
|
|
699
700
|
email: userData.email,
|
|
700
|
-
|
|
701
|
+
confirmedAt: toOptionalString(userData.confirmed_at),
|
|
701
702
|
createdAt: userData.created_at,
|
|
702
703
|
updatedAt: userData.updated_at,
|
|
704
|
+
role: toOptionalString(userData.role),
|
|
703
705
|
provider: toAuthProvider(appMeta.provider),
|
|
704
706
|
name: typeof name === "string" ? name : void 0,
|
|
705
707
|
pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
|
|
706
708
|
roles: toRoles(appMeta),
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
709
|
+
invitedAt: toOptionalString(userData.invited_at),
|
|
710
|
+
confirmationSentAt: toOptionalString(userData.confirmation_sent_at),
|
|
711
|
+
recoverySentAt: toOptionalString(userData.recovery_sent_at),
|
|
712
|
+
pendingEmail: toOptionalString(userData.new_email),
|
|
713
|
+
emailChangeSentAt: toOptionalString(userData.email_change_sent_at),
|
|
714
|
+
lastSignInAt: toOptionalString(userData.last_sign_in_at),
|
|
715
|
+
userMetadata: userMeta,
|
|
716
|
+
appMetadata: appMeta
|
|
710
717
|
};
|
|
711
718
|
};
|
|
712
719
|
var claimsToUser = (claims) => {
|
|
@@ -721,7 +728,7 @@ var claimsToUser = (claims) => {
|
|
|
721
728
|
name: typeof name === "string" ? name : void 0,
|
|
722
729
|
pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
|
|
723
730
|
roles: toRoles(appMeta),
|
|
724
|
-
|
|
731
|
+
userMetadata: userMeta,
|
|
725
732
|
appMetadata: appMeta
|
|
726
733
|
};
|
|
727
734
|
};
|
|
@@ -818,8 +825,7 @@ var getSettings = async () => {
|
|
|
818
825
|
gitlab: external.gitlab ?? false,
|
|
819
826
|
bitbucket: external.bitbucket ?? false,
|
|
820
827
|
facebook: external.facebook ?? false,
|
|
821
|
-
email: external.email ?? false
|
|
822
|
-
saml: external.saml ?? false
|
|
828
|
+
email: external.email ?? false
|
|
823
829
|
}
|
|
824
830
|
};
|
|
825
831
|
} catch (err) {
|
|
@@ -827,6 +833,18 @@ var getSettings = async () => {
|
|
|
827
833
|
}
|
|
828
834
|
};
|
|
829
835
|
|
|
836
|
+
// src/csrf.ts
|
|
837
|
+
var verifyRequestOrigin = (request, options) => {
|
|
838
|
+
const origin = request.headers.get("origin");
|
|
839
|
+
if (!origin) {
|
|
840
|
+
throw new AuthError("Cross-origin request refused: missing Origin header.", 403);
|
|
841
|
+
}
|
|
842
|
+
const allowed = options?.allowedOrigins ?? [new URL(request.url).origin];
|
|
843
|
+
if (!allowed.includes(origin)) {
|
|
844
|
+
throw new AuthError(`Cross-origin request refused: Origin ${origin} did not match an allowed origin.`, 403);
|
|
845
|
+
}
|
|
846
|
+
};
|
|
847
|
+
|
|
830
848
|
// src/account.ts
|
|
831
849
|
var resolveCurrentUser = async () => {
|
|
832
850
|
const client = getClient();
|
|
@@ -996,7 +1014,7 @@ var createUser = async (params) => {
|
|
|
996
1014
|
confirm: true
|
|
997
1015
|
};
|
|
998
1016
|
if (params.data) {
|
|
999
|
-
const allowedKeys = ["role", "
|
|
1017
|
+
const allowedKeys = ["role", "app_metadata", "user_metadata"];
|
|
1000
1018
|
for (const key of allowedKeys) {
|
|
1001
1019
|
if (key in params.data) {
|
|
1002
1020
|
body[key] = params.data[key];
|
|
@@ -1014,7 +1032,7 @@ var updateUser2 = async (userId, attributes) => {
|
|
|
1014
1032
|
assertServer();
|
|
1015
1033
|
const sanitizedUserId = sanitizeUserId(userId);
|
|
1016
1034
|
const body = {};
|
|
1017
|
-
const allowedKeys = ["email", "password", "role", "
|
|
1035
|
+
const allowedKeys = ["email", "password", "role", "confirm", "app_metadata", "user_metadata"];
|
|
1018
1036
|
for (const key of allowedKeys) {
|
|
1019
1037
|
if (key in attributes) {
|
|
1020
1038
|
body[key] = attributes[key];
|
|
@@ -1056,6 +1074,7 @@ var admin = { listUsers, getUser: getUser2, createUser, updateUser: updateUser2,
|
|
|
1056
1074
|
requestPasswordRecovery,
|
|
1057
1075
|
signup,
|
|
1058
1076
|
updateUser,
|
|
1059
|
-
verifyEmailChange
|
|
1077
|
+
verifyEmailChange,
|
|
1078
|
+
verifyRequestOrigin
|
|
1060
1079
|
});
|
|
1061
1080
|
//# sourceMappingURL=index.cjs.map
|