Compare commits

...

86 Commits

Author SHA1 Message Date
Pilou
9f81ba9713 Merge pull request #956 from nhost/changeset-release/main
chore: update versions
2022-09-26 16:26:49 +02:00
Pierre-Louis Mercereau
2f815e5eb6 chore: correct version bump 2022-09-26 16:12:08 +02:00
Pierre-Louis Mercereau
2cabd2d29a Merge branch 'changeset-release/main' of https://github.com/nhost/nhost into changeset-release/main 2022-09-26 16:08:40 +02:00
github-actions[bot]
d4ee6cc756 chore: update versions 2022-09-26 14:00:32 +00:00
Szilárd Dóró
8208b1c385 Merge pull request #958 from nhost/fix/nextjs-ssg
fix (react-apollo): broken Next.js SSG
2022-09-26 15:59:15 +02:00
Johan Eliasson
4c6c094f71 Merge pull request #957 from nhost/fix/stripe-graphql-updates
stripe graphiql option + readme updates
2022-09-26 15:57:57 +02:00
Johan Eliasson
3dadc7eab9 Merge pull request #954 from nhost/fix/import-users
docs: import users
2022-09-26 15:56:05 +02:00
Johan Eliasson
784041020b Create spotty-wasps-remember.md 2022-09-26 15:55:49 +02:00
Szilárd Dóró
74758f2c36 fix (react-apollo): broken Next.js SSG
Fixes #873
2022-09-26 15:44:02 +02:00
Johan Eliasson
ea34a3856b update 2022-09-26 13:59:08 +02:00
Johan Eliasson
c9175b76d3 readme update 2022-09-26 13:57:57 +02:00
Pierre-Louis Mercereau
1c82522163 chore: undo major peer bumps 2022-09-26 13:45:47 +02:00
github-actions[bot]
5794357374 chore: update versions 2022-09-26 11:40:59 +00:00
Pilou
3edf41f989 Merge pull request #942 from nhost/webauthn-signup
WebAuthn: signup
2022-09-26 13:39:41 +02:00
Johan Eliasson
44f069a253 graphiql 2022-09-26 13:37:21 +02:00
Johan Eliasson
cb0988cb87 readme about impor users 2022-09-26 09:05:06 +02:00
Pierre-Louis Mercereau
27752ca8a7 chore: lint 2022-09-23 13:00:42 +02:00
Pierre-Louis Mercereau
855181abbc refactor: complete name consistency 2022-09-23 12:57:46 +02:00
Pierre-Louis Mercereau
bc0515bd59 Merge branch 'webauthn-signup' of https://github.com/nhost/nhost into webauthn-signup 2022-09-23 12:47:55 +02:00
Pierre-Louis Mercereau
271c401b1a refactor: 💡 consistent names, and adjust example nav 2022-09-23 12:47:34 +02:00
Pilou
cbed7cdc72 Update .changeset/old-games-talk.md
Co-authored-by: Johan Eliasson <johan@nhost.io>
2022-09-23 12:31:39 +02:00
Pilou
fca620f050 Update .changeset/grumpy-ghosts-kneel.md
Co-authored-by: Johan Eliasson <johan@nhost.io>
2022-09-23 12:31:33 +02:00
Pilou
5200a4f272 Update .changeset/angry-dragons-carry.md
Co-authored-by: Johan Eliasson <johan@nhost.io>
2022-09-23 12:31:16 +02:00
Pierre-Louis Mercereau
19458cf076 refactor: bump hasura-auth to v0.13.0 2022-09-23 11:25:48 +02:00
Pierre-Louis Mercereau
1a94359a81 fix: add security key nickname to sign up options 2022-09-22 11:57:26 +02:00
Pierre-Louis Mercereau
96001f683a docs: adapt react-apollo example to the blog post 2022-09-22 09:57:39 +02:00
Pierre-Louis Mercereau
dd08453fb5 chore: adjust from review 2022-09-21 19:27:22 +02:00
Pierre-Louis Mercereau
739a3c4563 chore: 🤖 update changesets 2022-09-21 15:07:00 +02:00
Pierre-Louis Mercereau
20f3eb9086 refactor: 💡 remove irrelevant test 2022-09-21 14:54:36 +02:00
Pierre-Louis Mercereau
7b5f8647fb test: 💍 security key sign up 2022-09-21 14:49:03 +02:00
Pilou
486ddec751 Merge pull request #945 from nhost/guicurcio-patch-3
Update README.md
2022-09-21 13:50:27 +02:00
Guido Curcio
6475047158 Update README.md 2022-09-21 04:47:03 -07:00
Pierre-Louis Mercereau
14b26bdbc7 Merge branch 'main' into webauthn-signup 2022-09-21 12:37:48 +02:00
Pierre-Louis Mercereau
8e4d790b04 feat: 🎸 sign up with an email and a security key 2022-09-21 12:34:01 +02:00
Johan Eliasson
d814c7b46b Merge pull request #944 from nhost/fix/graphql-stripe-js
Fix/graphql stripe js
2022-09-20 20:17:54 +02:00
Johan Eliasson
5baeddba0b removed tmp changeset 2022-09-20 20:14:34 +02:00
Johan Eliasson
0262723329 Merge branch 'main' into fix/graphql-stripe-js 2022-09-20 20:14:17 +02:00
Johan Eliasson
1cf8a58d2c updated version 2022-09-20 20:12:13 +02:00
Johan Eliasson
b9a19d8251 Merge pull request #943 from nhost/fix/graphql-stripe-js
changeset update
2022-09-20 19:40:45 +02:00
Johan Eliasson
465d248456 changeset update 2022-09-20 19:19:00 +02:00
Pierre-Louis Mercereau
9e4861f2bb refactor: sign-in screens 2022-09-20 16:46:49 +02:00
Johan Eliasson
4ca738ba56 Merge pull request #916 from nhost/feat/graphql-stripe
feat: Stripe GraphQL
2022-09-20 12:49:53 +02:00
Johan Eliasson
be27ed73e1 new lock file 2022-09-20 12:21:15 +02:00
Johan Eliasson
f4d81d33b9 Merge branch 'main' into feat/graphql-stripe 2022-09-20 12:17:54 +02:00
Johan Eliasson
730c7d7b28 update 2022-09-20 12:16:25 +02:00
github-actions[bot]
38de442a7f chore: update versions 2022-09-20 12:15:55 +02:00
Johan Eliasson
22b8f02504 Update packages/stripe-graphql-js/README.md
Co-authored-by: Pilou <24897252+plmercereau@users.noreply.github.com>
2022-09-20 12:13:59 +02:00
Pierre-Louis Mercereau
24825adb08 feat: improve navigation and names 2022-09-20 11:48:59 +02:00
Johan Eliasson
96e59f0251 update 2022-09-20 11:18:53 +02:00
Johan Eliasson
9e43c320b9 remove unused variable 2022-09-20 11:04:03 +02:00
Johan Eliasson
f199ed5474 update 2022-09-20 11:03:33 +02:00
Johan Eliasson
2f00d7f309 updates 2022-09-20 10:44:54 +02:00
Johan Eliasson
d35dfb1aa0 readme update 2022-09-20 08:35:17 +02:00
Johan Eliasson
93f1d1944c rename 2022-09-19 17:05:05 +02:00
Johan Eliasson
efd3904966 update 2022-09-19 16:53:54 +02:00
Johan Eliasson
133e682e91 claims update 2022-09-19 15:57:34 +02:00
Johan Eliasson
72eebe538e reworked permissions a bit 2022-09-19 14:17:11 +02:00
Johan Eliasson
af313212f7 added metadata 2022-09-19 10:45:11 +02:00
Johan Eliasson
06b29f14fc minor updates 2022-09-19 09:40:16 +02:00
Johan Eliasson
4b960227cf README notice message 2022-09-19 09:37:14 +02:00
Johan Eliasson
a9e2db678d update 2022-09-16 16:33:57 +02:00
Johan Eliasson
4d0738d51c Create tiny-monkeys-jog.md 2022-09-16 15:47:16 +02:00
Johan Eliasson
1a8160632e merge 2022-09-16 15:44:51 +02:00
Johan Eliasson
084ea77355 Merge branch 'main' into feat/graphql-stripe 2022-09-16 15:43:17 +02:00
Johan Eliasson
19e5abb4a9 customers 2022-09-16 11:37:04 +02:00
Johan Eliasson
fe6514fa14 update 2022-09-16 11:14:08 +02:00
Johan Eliasson
92e9659cc7 invoice updates 2022-09-16 11:12:56 +02:00
Johan Eliasson
d5a2a259ce more invoice implementations 2022-09-15 15:19:41 +02:00
Johan Eliasson
6929c7f423 invoice updates 2022-09-14 18:38:34 +02:00
Johan Eliasson
5e5a9d6efa updates 2022-09-08 16:16:29 +02:00
Johan Eliasson
a365cadbd7 stripe internally + dotenv fix 2022-09-08 12:29:51 +02:00
Johan Eliasson
8221664f61 payment methods completed 2022-09-07 10:48:27 +02:00
Johan Eliasson
9396bdbbe3 working 2022-09-07 09:35:33 +02:00
Johan Eliasson
63fd6abd54 enum updates 2022-09-07 09:21:54 +02:00
Johan Eliasson
4e30b4ee21 allowed updated 2022-09-06 21:14:21 +02:00
Johan Eliasson
b07a61b8e4 updates 2022-09-06 10:00:06 +02:00
Johan Eliasson
f52336f698 restructure and started adding payment methods and subscriptions 2022-09-06 09:33:03 +02:00
Johan Eliasson
2d6e95b8b5 cleanup 2022-09-05 10:25:34 +02:00
Johan Eliasson
648c880445 update readme 2022-09-05 10:23:26 +02:00
Johan Eliasson
c286a0bbb1 adding payment method 2022-09-05 10:16:12 +02:00
Johan Eliasson
745d9a958d using pothos instead 2022-09-05 10:13:08 +02:00
Johan Eliasson
8c12b4117b updates 2022-09-05 07:57:04 +02:00
Johan Eliasson
afcced2417 readme update 2022-09-03 15:44:03 +02:00
Johan Eliasson
88fa68e74c update readme 2022-09-03 15:37:08 +02:00
Johan Eliasson
47b4a3ecf1 updates 2022-09-03 15:35:06 +02:00
Johan Eliasson
9095a0f6ae init 2022-09-03 15:21:47 +02:00
189 changed files with 4288 additions and 937 deletions

View File

@@ -39,7 +39,7 @@ query {
Users should be created using the sign-up or sign-in flows as described under [sign-in methods](/platform/authentication/sign-in-methods).
- **Never** create users directly via GraphQL or database.
- **Never** create users directly via GraphQL or database, unless you [import users](#import-users) from an external system.
- **Never** modify the `auth.users` table.
- **Never** modify the GraphQL root queries or fields for any of the tables in the `auth` schema.
@@ -136,3 +136,31 @@ await nhost.auth.signUp({
}
})
```
## Import Users
If you have users in a different system, you can import them into Nhost. When importing users you should insert the users directly into the database instead of using the authentication endpoints (`/signup/email-password`).
It's possible to insert users via GraphQL or SQL.
### GraphQL
Make a GraphQL request to insert a user like this:
```graphql
mutation insertUser($user: users_insert_input!) {
insertUser(object: $user) {
id
}
}
```
### SQL
Connect directly to the database and insert a user like this:
```sql
INSERT INTO auth.users (id, email, display_name, password_hash, ..) VALUES ('<user-id>', '<email>', '<display-name>', '<password-hash>', ..);
```
User passwords are hashed using [bcrypt](https://en.wikipedia.org/wiki/Bcrypt) in Nhost.

View File

@@ -4,7 +4,7 @@ title: signUp()
sidebar_label: signUp()
slug: /reference/javascript/auth/sign-up
description: Use `nhost.auth.signUp` to sign up a user using email and password. If you want to sign up a user using passwordless email (Magic Link), SMS, or an OAuth provider, use the `signIn` function instead.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L106
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L107
---
# `signUp()`
@@ -22,12 +22,6 @@ nhost.auth.signUp({
---
**<span className="parameter-name">\_\_namedParameters</span>** <span className="optional-status">required</span> [`SignUpEmailPasswordParams`](/reference/docgen/javascript/auth/types/sign-up-email-password-params)
| Property | Type | Required | Notes |
| :------------------------------------------------------------------------------------------------------- | :-------------- | :------: | :---- |
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>password</span> | `string` | ✔️ | |
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>email</span> | `string` | ✔️ | |
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>options</span> | `SignUpOptions` | | |
**<span className="parameter-name">params</span>** <span className="optional-status">required</span> [`SignUpParams`](/reference/docgen/javascript/auth/types/sign-up-params)
---

View File

@@ -4,7 +4,7 @@ title: signIn()
sidebar_label: signIn()
slug: /reference/javascript/auth/sign-in
description: Use `nhost.auth.signIn` to sign in a user using email and password, passwordless (email or sms) or an external provider. `signIn` can be used to sign in a user in various ways depending on the parameters.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L149
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L156
---
# `signIn()`

View File

@@ -4,7 +4,7 @@ title: signOut()
sidebar_label: signOut()
slug: /reference/javascript/auth/sign-out
description: Use `nhost.auth.signOut` to sign out the user.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L245
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L252
---
# `signOut()`

View File

@@ -4,7 +4,7 @@ title: resetPassword()
sidebar_label: resetPassword()
slug: /reference/javascript/auth/reset-password
description: Use `nhost.auth.resetPassword` to reset the password for a user. This will send a reset-password link in an email to the user. When the user clicks the reset-password link the user is automatically signed-in. Once signed-in, the user can change their password using `nhost.auth.changePassword()`.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L261
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L268
---
# `resetPassword()`

View File

@@ -4,7 +4,7 @@ title: changePassword()
sidebar_label: changePassword()
slug: /reference/javascript/auth/change-password
description: Use `nhost.auth.changePassword` to change the password for the signed-in user. The old password is not needed. In case the user is not signed-in, a password reset ticket needs to be provided.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L277
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L284
---
# `changePassword()`

View File

@@ -4,7 +4,7 @@ title: sendVerificationEmail()
sidebar_label: sendVerificationEmail()
slug: /reference/javascript/auth/send-verification-email
description: Use `nhost.auth.sendVerificationEmail` to send a verification email to the specified email. The email contains a verification-email link. When the user clicks the verification-email link their email is verified.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L296
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L303
---
# `sendVerificationEmail()`

View File

@@ -4,7 +4,7 @@ title: changeEmail()
sidebar_label: changeEmail()
slug: /reference/javascript/auth/change-email
description: Use `nhost.auth.changeEmail` to change a user's email. This will send a confirm-email-change link in an email to the new email. Once the user clicks on the confirm-email-change link the email will be change to the new email.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L315
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L322
---
# `changeEmail()`

View File

@@ -4,7 +4,7 @@ title: deanonymize()
sidebar_label: deanonymize()
slug: /reference/javascript/auth/deanonymize
description: Use `nhost.auth.deanonymize` to deanonymize a user.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L331
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L338
---
# `deanonymize()`

View File

@@ -4,7 +4,7 @@ title: addSecurityKey()
sidebar_label: addSecurityKey()
slug: /reference/javascript/auth/add-security-key
description: Use `nhost.auth.addSecurityKey to add a security key to the user, using the WebAuthn API.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L369
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L376
---
# `addSecurityKey()`

View File

@@ -4,7 +4,7 @@ title: onTokenChanged()
sidebar_label: onTokenChanged()
slug: /reference/javascript/auth/on-token-changed
description: Use `nhost.auth.onTokenChanged` to add a custom function that runs every time the access or refresh token is changed.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L387
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L394
---
# `onTokenChanged()`

View File

@@ -4,7 +4,7 @@ title: onAuthStateChanged()
sidebar_label: onAuthStateChanged()
slug: /reference/javascript/auth/on-auth-state-changed
description: Use `nhost.auth.onAuthStateChanged` to add a custom function that runs every time the authentication status of the user changes. E.g. add a custom function that runs every time the authentication status changes from signed-in to signed-out.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L422
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L429
---
# `onAuthStateChanged()`

View File

@@ -4,7 +4,7 @@ title: isAuthenticated()
sidebar_label: isAuthenticated()
slug: /reference/javascript/auth/is-authenticated
description: Use `nhost.auth.isAuthenticated` to check if the user is authenticated or not.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L464
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L471
---
# `isAuthenticated()`

View File

@@ -4,7 +4,7 @@ title: isAuthenticatedAsync()
sidebar_label: isAuthenticatedAsync()
slug: /reference/javascript/auth/is-authenticated-async
description: Use `nhost.auth.isAuthenticatedAsync` to wait (await) for any internal authentication network requests to finish and then return the authentication status.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L482
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L489
---
# `isAuthenticatedAsync()`

View File

@@ -4,7 +4,7 @@ title: getAuthenticationStatus()
sidebar_label: getAuthenticationStatus()
slug: /reference/javascript/auth/get-authentication-status
description: Use `nhost.auth.getAuthenticationStatus` to get the authentication status of the user.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L508
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L515
---
# `getAuthenticationStatus()`

View File

@@ -4,7 +4,7 @@ title: getAccessToken()
sidebar_label: getAccessToken()
slug: /reference/javascript/auth/get-access-token
description: Use `nhost.auth.getAccessToken` to get the access token of the user.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L538
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L545
---
# `getAccessToken()`

View File

@@ -4,7 +4,7 @@ title: getDecodedAccessToken()
sidebar_label: getDecodedAccessToken()
slug: /reference/javascript/auth/get-decoded-access-token
description: Use `nhost.auth.getDecodedAccessToken` to get the decoded access token of the user.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L553
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L560
---
# `getDecodedAccessToken()`

View File

@@ -4,7 +4,7 @@ title: getHasuraClaims()
sidebar_label: getHasuraClaims()
slug: /reference/javascript/auth/get-hasura-claims
description: Use `nhost.auth.getHasuraClaims` to get the Hasura claims of the user.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L570
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L577
---
# `getHasuraClaims()`

View File

@@ -4,7 +4,7 @@ title: getHasuraClaim()
sidebar_label: getHasuraClaim()
slug: /reference/javascript/auth/get-hasura-claim
description: Use `nhost.auth.getHasuraClaim` to get the value of a specific Hasura claim of the user.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L588
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L595
---
# `getHasuraClaim()`

View File

@@ -4,7 +4,7 @@ title: refreshSession()
sidebar_label: refreshSession()
slug: /reference/javascript/auth/refresh-session
description: Use `nhost.auth.refreshSession` to refresh the session with either the current internal refresh token or an external refresh token.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L611
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L618
---
# `refreshSession()`

View File

@@ -4,7 +4,7 @@ title: getSession()
sidebar_label: getSession()
slug: /reference/javascript/auth/get-session
description: Use `nhost.auth.getSession()` to get the session of the user.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L652
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L659
---
# `getSession()`

View File

@@ -4,7 +4,7 @@ title: getUser()
sidebar_label: getUser()
slug: /reference/javascript/auth/get-user
description: Use `nhost.auth.getUser()` to get the signed-in user.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L667
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L674
---
# `getUser()`

View File

@@ -4,7 +4,7 @@ title: HasuraAuthClient
sidebar_label: Auth
description: No description provided.
slug: /reference/javascript/auth
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L63
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/hasura-auth-client.ts#L64
---
# `HasuraAuthClient`

View File

@@ -4,7 +4,7 @@ title: AuthChangeEvent
sidebar_label: AuthChangeEvent
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L107
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L118
---
# `AuthChangeEvent`

View File

@@ -4,7 +4,7 @@ title: AuthChangedFunction
sidebar_label: AuthChangedFunction
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L109
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L120
---
# `AuthChangedFunction`

View File

@@ -4,7 +4,7 @@ title: ChangeEmailParams
sidebar_label: ChangeEmailParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L89
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L99
---
# `ChangeEmailParams`

View File

@@ -4,7 +4,7 @@ title: ChangePasswordParams
sidebar_label: ChangePasswordParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L79
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L89
---
# `ChangePasswordParams`

View File

@@ -0,0 +1,18 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: CommonSignUpParams
sidebar_label: CommonSignUpParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L25
---
# `CommonSignUpParams`
## Parameters
---
**<span className="parameter-name">options</span>** <span className="optional-status">optional</span> `SignUpOptions`
---

View File

@@ -4,14 +4,14 @@ title: DeanonymizeParams
sidebar_label: DeanonymizeParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L94
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L104
---
# `DeanonymizeParams`
```ts
type DeanonymizeParams =
| ({ signInMethod: 'email-password' } & SignUpParams)
| ({ signInMethod: 'email-password' } & SignUpEmailPasswordParams)
| ({
signInMethod: 'passwordless'
connection: 'email'

View File

@@ -4,7 +4,7 @@ title: NhostAuthConstructorParams
sidebar_label: NhostAuthConstructorParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L16
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L17
---
# `NhostAuthConstructorParams`

View File

@@ -4,7 +4,7 @@ title: OnTokenChangedFunction
sidebar_label: OnTokenChangedFunction
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L111
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L122
---
# `OnTokenChangedFunction`

View File

@@ -4,7 +4,7 @@ title: Provider
sidebar_label: Provider
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/core/src/types.ts#L148
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/core/src/types.ts#L153
---
# `Provider`

View File

@@ -4,7 +4,7 @@ title: ResetPasswordParams
sidebar_label: ResetPasswordParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L74
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L84
---
# `ResetPasswordParams`

View File

@@ -4,7 +4,7 @@ title: SendVerificationEmailParams
sidebar_label: SendVerificationEmailParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L84
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L94
---
# `SendVerificationEmailParams`

View File

@@ -4,7 +4,7 @@ title: SignInEmailPasswordOtpParams
sidebar_label: SignInEmailPasswordOtpParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L36
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L46
---
# `SignInEmailPasswordOtpParams`

View File

@@ -4,7 +4,7 @@ title: SignInEmailPasswordParams
sidebar_label: SignInEmailPasswordParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L31
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L41
---
# `SignInEmailPasswordParams`

View File

@@ -4,7 +4,7 @@ title: SignInParams
sidebar_label: SignInParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L65
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L75
---
# `SignInParams`

View File

@@ -4,7 +4,7 @@ title: SignInPasswordlessEmailParams
sidebar_label: SignInPasswordlessEmailParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L41
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L51
---
# `SignInPasswordlessEmailParams`

View File

@@ -4,7 +4,7 @@ title: SignInPasswordlessSecurityKeyParams
sidebar_label: SignInPasswordlessSecurityKeyParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L46
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L56
---
# `SignInPasswordlessSecurityKeyParams`

View File

@@ -4,7 +4,7 @@ title: SignInPasswordlessSmsOtpParams
sidebar_label: SignInPasswordlessSmsOtpParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L56
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L66
---
# `SignInPasswordlessSmsOtpParams`

View File

@@ -4,7 +4,7 @@ title: SignInPasswordlessSmsParams
sidebar_label: SignInPasswordlessSmsParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L51
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L61
---
# `SignInPasswordlessSmsParams`

View File

@@ -4,7 +4,7 @@ title: SignInWithProviderOptions
sidebar_label: SignInWithProviderOptions
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L61
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L71
---
# `SignInWithProviderOptions`

View File

@@ -4,7 +4,7 @@ title: SignUpEmailPasswordParams
sidebar_label: SignUpEmailPasswordParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L24
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L29
---
# `SignUpEmailPasswordParams`
@@ -13,7 +13,7 @@ custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-j
---
**<span className="parameter-name">password</span>** <span className="optional-status">required</span> `string`
**<span className="parameter-name">options</span>** <span className="optional-status">optional</span> `SignUpOptions`
---
@@ -21,6 +21,6 @@ custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-j
---
**<span className="parameter-name">options</span>** <span className="optional-status">optional</span> `SignUpOptions`
**<span className="parameter-name">password</span>** <span className="optional-status">required</span> `string`
---

View File

@@ -4,7 +4,11 @@ title: SignUpParams
sidebar_label: SignUpParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L30
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L40
---
# `SignUpParams`
```ts
type SignUpParams = SignUpEmailPasswordParams | SignUpSecurityKeyParams
```

View File

@@ -0,0 +1,26 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignUpSecurityKeyParams
sidebar_label: SignUpSecurityKeyParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L34
---
# `SignUpSecurityKeyParams`
## Parameters
---
**<span className="parameter-name">email</span>** <span className="optional-status">required</span> `string`
---
**<span className="parameter-name">options</span>** <span className="optional-status">optional</span> `SignUpSecurityKeyOptions`
---
**<span className="parameter-name">securityKey</span>** <span className="optional-status">required</span> `"true"`
---

View File

@@ -4,7 +4,7 @@ title: User
sidebar_label: User
description: User information
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/core/src/types.ts#L101
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/core/src/types.ts#L106
---
# `User`

View File

@@ -4,7 +4,7 @@ title: NhostAuthConstructorParams
sidebar_label: NhostAuthConstructorParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L16
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-auth-js/src/utils/types.ts#L17
---
# `NhostAuthConstructorParams`

View File

@@ -1,31 +1,31 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: useSignInSecurityKeyEmail()
sidebar_label: useSignInSecurityKeyEmail()
slug: /reference/nextjs/use-sign-in-security-key-email
description: Use the hook `useSignInSecurityKeyEmail` to sign in a user using their email and a security key using the WebAuthn API.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSecurityKeyEmail.ts#L41
title: useSignInEmailSecurityKey()
sidebar_label: useSignInEmailSecurityKey()
slug: /reference/nextjs/use-sign-in-email-security-key
description: Use the hook `useSignInEmailSecurityKey` to sign in a user using their email and a security key using the WebAuthn API.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInEmailSecurityKey.ts#L41
---
# `useSignInSecurityKeyEmail()`
# `useSignInEmailSecurityKey()`
Use the hook `useSignInSecurityKeyEmail` to sign in a user using their email and a security key using the WebAuthn API.
Use the hook `useSignInEmailSecurityKey` to sign in a user using their email and a security key using the WebAuthn API.
```tsx
const {
signInSecurityKeyEmail,
signInEmailSecurityKey,
needsEmailVerification,
isLoading,
isSuccess,
isError,
error
} = useSignInSecurityKeyEmail()
} = useSignInEmailSecurityKey()
console.log({ needsEmailVerification, isLoading, isSuccess, isError, error })
const handleFormSubmit = async (e) => {
e.preventDefault()
await signInSecurityKeyEmail('joe@example.com')
await signInEmailSecurityKey('joe@example.com')
}
```

View File

@@ -0,0 +1,39 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: useSignUpEmailSecurityKeyEmail()
sidebar_label: useSignUpEmailSecurityKeyEmail()
slug: /reference/nextjs/use-sign-up-email-security-key-email
description: Use the hook `useSignUpEmailSecurityKey` to sign up a user with security key and an email using the WebAuthn API.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignUpEmailSecurityKey.ts#L43
---
# `useSignUpEmailSecurityKeyEmail()`
Use the hook `useSignUpEmailSecurityKey` to sign up a user with security key and an email using the WebAuthn API.
```tsx
const {
signUpEmailSecurityKey,
needsEmailVerification,
isLoading,
isSuccess,
isError,
error
} = useSignUpEmailSecurityKey()
console.log({ needsEmailVerification, isLoading, isSuccess, isError, error })
const handleFormSubmit = async (e) => {
e.preventDefault()
await signUpEmailSecurityKey('joe@example.com')
}
```
## Parameters
---
**<span className="parameter-name">options</span>** <span className="optional-status">optional</span> `SignUpSecurityKeyOptions`
---

View File

@@ -4,7 +4,7 @@ title: NhostSession
sidebar_label: NhostSession
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/core/src/types.ts#L136
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/core/src/types.ts#L141
---
# `NhostSession`

View File

@@ -4,7 +4,7 @@ title: SignInSecurityKeyPasswordlessHookResult
sidebar_label: SignInSecurityKeyPasswordlessHookResult
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSecurityKeyEmail.ts#L14
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInEmailSecurityKey.ts#L14
---
# `SignInSecurityKeyPasswordlessHookResult`
@@ -65,6 +65,6 @@ Access token (JWT)
---
**<span className="parameter-name">signInSecurityKeyEmail</span>** <span className="optional-status">required</span> `SignInSecurityKeyPasswordlessHandler`
**<span className="parameter-name">signInEmailSecurityKey</span>** <span className="optional-status">required</span> `SignInSecurityKeyPasswordlessHandler`
---

View File

@@ -0,0 +1,72 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignUpSecurityKeyHookResult
sidebar_label: SignUpSecurityKeyHookResult
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignUpEmailSecurityKey.ts#L16
---
# `SignUpSecurityKeyHookResult`
## Parameters
---
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` if an error occurred
**`@depreacted`**
use `!isSuccess` or `!!error` instead
---
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> `null` | `ErrorPayload`
Provides details about the error
---
**<span className="parameter-name">isLoading</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` when the action is executing, `false` when it finished its execution.
---
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> `boolean`
Returns `true` if the action is successful.
---
**<span className="parameter-name">user</span>** <span className="optional-status">required</span> `null` | `User`
User information
---
**<span className="parameter-name">accessToken</span>** <span className="optional-status">required</span> `null` | `string`
Access token (JWT)
---
**<span className="parameter-name">needsEmailVerification</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` if an email is required to complete the action, and that a verification email has been sent to complete the action.
---
**<span className="parameter-name">signUpEmailSecurityKey</span>** <span className="optional-status">required</span> `SignUpSecurityKeyHandler`
Used for a new user to sign up with a security key. Returns a promise with the current context
---

View File

@@ -1,31 +1,31 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: useSignInSecurityKeyEmail()
sidebar_label: useSignInSecurityKeyEmail()
slug: /reference/react/use-sign-in-security-key-email
description: Use the hook `useSignInSecurityKeyEmail` to sign in a user using their email and a security key using the WebAuthn API.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSecurityKeyEmail.ts#L41
title: useSignInEmailSecurityKey()
sidebar_label: useSignInEmailSecurityKey()
slug: /reference/react/use-sign-in-email-security-key
description: Use the hook `useSignInEmailSecurityKey` to sign in a user using their email and a security key using the WebAuthn API.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInEmailSecurityKey.ts#L41
---
# `useSignInSecurityKeyEmail()`
# `useSignInEmailSecurityKey()`
Use the hook `useSignInSecurityKeyEmail` to sign in a user using their email and a security key using the WebAuthn API.
Use the hook `useSignInEmailSecurityKey` to sign in a user using their email and a security key using the WebAuthn API.
```tsx
const {
signInSecurityKeyEmail,
signInEmailSecurityKey,
needsEmailVerification,
isLoading,
isSuccess,
isError,
error
} = useSignInSecurityKeyEmail()
} = useSignInEmailSecurityKey()
console.log({ needsEmailVerification, isLoading, isSuccess, isError, error })
const handleFormSubmit = async (e) => {
e.preventDefault()
await signInSecurityKeyEmail('joe@example.com')
await signInEmailSecurityKey('joe@example.com')
}
```

View File

@@ -0,0 +1,39 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: useSignUpEmailSecurityKeyEmail()
sidebar_label: useSignUpEmailSecurityKeyEmail()
slug: /reference/react/use-sign-up-email-security-key-email
description: Use the hook `useSignUpEmailSecurityKey` to sign up a user with security key and an email using the WebAuthn API.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignUpEmailSecurityKey.ts#L43
---
# `useSignUpEmailSecurityKeyEmail()`
Use the hook `useSignUpEmailSecurityKey` to sign up a user with security key and an email using the WebAuthn API.
```tsx
const {
signUpEmailSecurityKey,
needsEmailVerification,
isLoading,
isSuccess,
isError,
error
} = useSignUpEmailSecurityKey()
console.log({ needsEmailVerification, isLoading, isSuccess, isError, error })
const handleFormSubmit = async (e) => {
e.preventDefault()
await signUpEmailSecurityKey('joe@example.com')
}
```
## Parameters
---
**<span className="parameter-name">options</span>** <span className="optional-status">optional</span> `SignUpSecurityKeyOptions`
---

View File

@@ -4,7 +4,7 @@ title: SignInSecurityKeyPasswordlessHookResult
sidebar_label: SignInSecurityKeyPasswordlessHookResult
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSecurityKeyEmail.ts#L14
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInEmailSecurityKey.ts#L14
---
# `SignInSecurityKeyPasswordlessHookResult`
@@ -65,6 +65,6 @@ Access token (JWT)
---
**<span className="parameter-name">signInSecurityKeyEmail</span>** <span className="optional-status">required</span> `SignInSecurityKeyPasswordlessHandler`
**<span className="parameter-name">signInEmailSecurityKey</span>** <span className="optional-status">required</span> `SignInSecurityKeyPasswordlessHandler`
---

View File

@@ -0,0 +1,72 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignUpSecurityKeyHookResult
sidebar_label: SignUpSecurityKeyHookResult
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignUpEmailSecurityKey.ts#L16
---
# `SignUpSecurityKeyHookResult`
## Parameters
---
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` if an error occurred
**`@depreacted`**
use `!isSuccess` or `!!error` instead
---
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> `null` | `ErrorPayload`
Provides details about the error
---
**<span className="parameter-name">isLoading</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` when the action is executing, `false` when it finished its execution.
---
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> `boolean`
Returns `true` if the action is successful.
---
**<span className="parameter-name">user</span>** <span className="optional-status">required</span> `null` | `User`
User information
---
**<span className="parameter-name">accessToken</span>** <span className="optional-status">required</span> `null` | `string`
Access token (JWT)
---
**<span className="parameter-name">needsEmailVerification</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` if an email is required to complete the action, and that a verification email has been sent to complete the action.
---
**<span className="parameter-name">signUpEmailSecurityKey</span>** <span className="optional-status">required</span> `SignUpSecurityKeyHandler`
Used for a new user to sign up with a security key. Returns a promise with the current context
---

View File

@@ -5,7 +5,7 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.11.0
image: nhost/hasura-auth:0.13.0
storage:
image: nhost/hasura-storage:0.2.4
auth:

View File

@@ -5,7 +5,7 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.11.0
image: nhost/hasura-auth:0.13.0
storage:
image: nhost/hasura-storage:0.2.4
auth:

View File

@@ -0,0 +1,9 @@
{
"name": "functions",
"version": "1.0.0",
"description": "",
"main": "index.js",
"keywords": [],
"author": "",
"license": "ISC"
}

View File

@@ -0,0 +1,11 @@
{
"compilerOptions": {
"allowJs": true,
"skipLibCheck": true,
"noEmit": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"isolatedModules": true,
"strictNullChecks": false
}
}

View File

@@ -5,7 +5,7 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.11.0
image: nhost/hasura-auth:0.13.0
storage:
image: nhost/hasura-storage:0.2.4
auth:

View File

@@ -5,7 +5,7 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.11.0
image: nhost/hasura-auth:0.13.0
storage:
image: nhost/hasura-storage:0.2.4
auth:

View File

@@ -5,7 +5,7 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.11.0
image: nhost/hasura-auth:0.13.0
storage:
image: nhost/hasura-storage:0.2.4
auth:

View File

@@ -0,0 +1,34 @@
# @nhost-examples/react-apollo
## 0.1.0
### Minor Changes
- 739a3c45: Sign up with an email and a security key.
Use the hook `useSignUpEmailSecurityKey` to sign up a user with security key and an email using the WebAuthn API.
```tsx
const {
signUpEmailSecurityKey,
needsEmailVerification,
isLoading,
isSuccess,
isError,
error
} = useSignUpEmailSecurityKey()
console.log({ needsEmailVerification, isLoading, isSuccess, isError, error })
const handleFormSubmit = async (e) => {
e.preventDefault()
await signUpEmailSecurityKey('joe@example.com')
}
```
### Patch Changes
- Updated dependencies [739a3c45]
- Updated dependencies [74758f2c]
- @nhost/react@0.13.0
- @nhost/react-apollo@5.0.0

View File

@@ -37,3 +37,4 @@ nhost dev
```sh
pnpm run dev
```

View File

@@ -27,7 +27,7 @@ context('Anonymous users', () => {
})
})
it('should deanonymise with passwordless email', () => {
it('should deanonymise with a magic link', () => {
cy.fetchUserData()
.its('id')
.then((id) => {

View File

@@ -1,7 +1,7 @@
import { faker } from '@faker-js/faker'
context('Sign up with passwordless email', () => {
it('should sign-up with passwordless email', () => {
context('Sign up with a magic link', () => {
it('should sign-up with a magic link', () => {
const email = faker.internet.email()
cy.signUpEmailPasswordless(email)
cy.contains('Verification email sent').should('be.visible')

View File

@@ -11,7 +11,7 @@ context('Sign in with email+password', () => {
cy.contains('Verification email sent').should('be.visible')
cy.confirmEmail(email)
cy.signOut()
cy.contains('Log in to the Application').should('be.visible')
cy.contains('Sign in to the Application').should('be.visible')
cy.signInEmailPassword(email, password)
cy.contains('You are authenticated')

View File

@@ -4,7 +4,7 @@ context('Sign in with a refresh token', () => {
cy.contains('Profile page')
cy.clearLocalStorage()
cy.reload()
cy.contains('Log in to the Application')
cy.contains('Sign in to the Application')
cy.visitPathWithRefreshToken('/profile')
cy.contains('Profile page')
})
@@ -15,7 +15,7 @@ context('Sign in with a refresh token', () => {
cy.disconnectBackend()
cy.clearLocalStorage()
cy.reload()
cy.contains('Log in to the Application')
cy.contains('Sign in to the Application')
cy.visitPathWithRefreshToken('/profile')
cy.location('pathname').should('equal', '/sign-in')
})

View File

@@ -8,6 +8,6 @@ context('Sign out', () => {
cy.goToProfilePage()
cy.contains('Profile page')
cy.signOut()
cy.contains('Log in to the Application')
cy.contains('Sign in to the Application')
})
})

View File

@@ -52,7 +52,7 @@ Cypress.Commands.add('signUpEmailPassword', (email, password) => {
Cypress.Commands.add('signUpEmailPasswordless', (email) => {
cy.visit('/sign-up')
cy.findByRole('button', { name: /Continue with passwordless email/i }).click()
cy.findByRole('button', { name: /Continue with a magic link/i }).click()
cy.findByPlaceholderText('Email Address').type(email)
cy.findByRole('button', { name: /Continue with email/i }).click()
})

View File

@@ -5,7 +5,7 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.11.0
image: nhost/hasura-auth:0.13.0
storage:
image: nhost/hasura-storage:0.2.4
auth:
@@ -129,7 +129,7 @@ auth:
issuer: nhost
webauthn:
enabled: true
rp_name: 'Nhost React Apollo Example'
rp_name: Nhost React Apollo Example
storage:
force_download_for_content_types: text/html,application/javascript
version: 3

View File

@@ -1,5 +1,5 @@
table:
name: user_authenticators
name: user_security_keys
schema: auth
configuration:
column_config:
@@ -13,17 +13,17 @@ configuration:
credential_id: credentialId
credential_public_key: credentialPublicKey
user_id: userId
custom_name: authUserAuthenticators
custom_name: authUserSecurityKeys
custom_root_fields:
delete: deleteAuthUserAuthenticators
delete_by_pk: deleteAuthUserAuthenticator
insert: insertAuthUserAuthenticators
insert_one: insertAuthUserAuthenticator
select: authUserAuthenticators
select_aggregate: authUserAuthenticatorsAggregate
select_by_pk: authUserAuthenticator
update: updateAuthUserAuthenticators
update_by_pk: updateAuthUserAuthenticator
delete: deleteAuthUserSecurityKeys
delete_by_pk: deleteAuthUserSecurityKey
insert: insertAuthUserSecurityKeys
insert_one: insertAuthUserSecurityKey
select: authUserSecurityKeys
select_aggregate: authUserSecurityKeysAggregate
select_by_pk: authUserSecurityKey
update: updateAuthUserSecurityKeys
update_by_pk: updateAuthUserSecurityKey
object_relationships:
- name: user
using:
@@ -32,14 +32,12 @@ select_permissions:
- role: user
permission:
columns:
- counter
- id
- nickname
- user_id
filter:
user_id:
_eq: X-Hasura-User-Id
allow_aggregations: true
delete_permissions:
- role: user
permission:

View File

@@ -77,13 +77,6 @@ object_relationships:
using:
foreign_key_constraint_on: default_role
array_relationships:
- name: authenticators
using:
foreign_key_constraint_on:
column: user_id
table:
name: user_authenticators
schema: auth
- name: refreshTokens
using:
foreign_key_constraint_on:
@@ -98,6 +91,13 @@ array_relationships:
table:
name: user_roles
schema: auth
- name: securityKeys
using:
foreign_key_constraint_on:
column: user_id
table:
name: user_security_keys
schema: auth
- name: userProviders
using:
foreign_key_constraint_on:

View File

@@ -2,9 +2,9 @@
- "!include auth_providers.yaml"
- "!include auth_refresh_tokens.yaml"
- "!include auth_roles.yaml"
- "!include auth_user_authenticators.yaml"
- "!include auth_user_providers.yaml"
- "!include auth_user_roles.yaml"
- "!include auth_user_security_keys.yaml"
- "!include auth_users.yaml"
- "!include public_todos.yaml"
- "!include storage_buckets.yaml"

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost-examples/react-apollo",
"version": "0.0.1",
"version": "0.1.0",
"private": true,
"dependencies": {
"@apollo/client": "^3.6.9",

View File

@@ -1,22 +1,19 @@
import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { FormEvent, useState } from 'react'
import { Button, Modal, SimpleGrid, TextInput } from '@mantine/core'
import { showNotification } from '@mantine/notifications'
import { useSignInEmailPasswordless, useSignInSecurityKeyEmail } from '@nhost/react'
import { useSignInEmailPasswordless } from '@nhost/react'
export const SignUpPasswordlessForm: React.FC = () => {
const navigate = useNavigate()
const { signInEmailPasswordless } = useSignInEmailPasswordless({ redirectTo: '/profile' })
const { signInSecurityKeyEmail } = useSignInSecurityKeyEmail()
const [emailVerificationToggle, setEmailVerificationToggle] = useState(false)
const [emailNeedsVerificationToggle, setEmailNeedsVerificationToggle] = useState(false)
const [email, setEmail] = useState('')
const signInEmail = async () => {
const signInEmail = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
const result = await signInEmailPasswordless(email)
if (result.isError) {
showNotification({
@@ -28,21 +25,6 @@ export const SignUpPasswordlessForm: React.FC = () => {
setEmailVerificationToggle(true)
}
}
const signInDevice = async () => {
const result = await signInSecurityKeyEmail(email)
if (result.needsEmailVerification) {
return
}
if (result.isError) {
showNotification({
color: 'red',
title: 'Error',
message: result.error?.message || null
})
return
}
navigate('/', { replace: true })
}
return (
<SimpleGrid cols={1} spacing={6}>
<Modal
@@ -70,18 +52,19 @@ export const SignUpPasswordlessForm: React.FC = () => {
You need to verify your email first. Please check your mailbox and follow the confirmation
link to complete the registration.
</Modal>
<TextInput
type="email"
placeholder="Email Address"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<Button fullWidth onClick={signInDevice}>
Use a security key
</Button>
<Button fullWidth onClick={signInEmail}>
Send a magic link
</Button>
<form onSubmit={signInEmail}>
<TextInput
type="email"
placeholder="Email Address"
value={email}
onChange={(e) => setEmail(e.target.value)}
autoFocus
style={{ marginBottom: '0.5em' }}
/>
<Button fullWidth type="submit">
Send a magic link
</Button>
</form>
</SimpleGrid>
)
}

View File

@@ -10,7 +10,6 @@ export type Scalars = {
Boolean: boolean;
Int: number;
Float: number;
bigint: number;
citext: string;
jsonb: any;
timestamptz: string;
@@ -76,10 +75,9 @@ export type StringComparisonExp = {
_similar?: InputMaybe<Scalars['String']>;
};
/** User webauthn authenticators. Don't modify its structure as Hasura Auth relies on it to function properly. */
export type AuthUserAuthenticators = {
__typename?: 'authUserAuthenticators';
counter: Scalars['bigint'];
/** User webauthn security keys. Don't modify its structure as Hasura Auth relies on it to function properly. */
export type AuthUserSecurityKeys = {
__typename?: 'authUserSecurityKeys';
id: Scalars['uuid'];
nickname?: Maybe<Scalars['String']>;
/** An object relationship */
@@ -87,130 +85,57 @@ export type AuthUserAuthenticators = {
userId: Scalars['uuid'];
};
/** aggregated selection of "auth.user_authenticators" */
export type AuthUserAuthenticatorsAggregate = {
__typename?: 'authUserAuthenticators_aggregate';
aggregate?: Maybe<AuthUserAuthenticatorsAggregateFields>;
nodes: Array<AuthUserAuthenticators>;
};
/** aggregate fields of "auth.user_authenticators" */
export type AuthUserAuthenticatorsAggregateFields = {
__typename?: 'authUserAuthenticators_aggregate_fields';
avg?: Maybe<AuthUserAuthenticatorsAvgFields>;
count: Scalars['Int'];
max?: Maybe<AuthUserAuthenticatorsMaxFields>;
min?: Maybe<AuthUserAuthenticatorsMinFields>;
stddev?: Maybe<AuthUserAuthenticatorsStddevFields>;
stddev_pop?: Maybe<AuthUserAuthenticatorsStddevPopFields>;
stddev_samp?: Maybe<AuthUserAuthenticatorsStddevSampFields>;
sum?: Maybe<AuthUserAuthenticatorsSumFields>;
var_pop?: Maybe<AuthUserAuthenticatorsVarPopFields>;
var_samp?: Maybe<AuthUserAuthenticatorsVarSampFields>;
variance?: Maybe<AuthUserAuthenticatorsVarianceFields>;
};
/** aggregate fields of "auth.user_authenticators" */
export type AuthUserAuthenticatorsAggregateFieldsCountArgs = {
columns?: InputMaybe<Array<AuthUserAuthenticatorsSelectColumn>>;
distinct?: InputMaybe<Scalars['Boolean']>;
};
/** order by aggregate values of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsAggregateOrderBy = {
avg?: InputMaybe<AuthUserAuthenticatorsAvgOrderBy>;
/** order by aggregate values of table "auth.user_security_keys" */
export type AuthUserSecurityKeysAggregateOrderBy = {
count?: InputMaybe<OrderBy>;
max?: InputMaybe<AuthUserAuthenticatorsMaxOrderBy>;
min?: InputMaybe<AuthUserAuthenticatorsMinOrderBy>;
stddev?: InputMaybe<AuthUserAuthenticatorsStddevOrderBy>;
stddev_pop?: InputMaybe<AuthUserAuthenticatorsStddevPopOrderBy>;
stddev_samp?: InputMaybe<AuthUserAuthenticatorsStddevSampOrderBy>;
sum?: InputMaybe<AuthUserAuthenticatorsSumOrderBy>;
var_pop?: InputMaybe<AuthUserAuthenticatorsVarPopOrderBy>;
var_samp?: InputMaybe<AuthUserAuthenticatorsVarSampOrderBy>;
variance?: InputMaybe<AuthUserAuthenticatorsVarianceOrderBy>;
max?: InputMaybe<AuthUserSecurityKeysMaxOrderBy>;
min?: InputMaybe<AuthUserSecurityKeysMinOrderBy>;
};
/** aggregate avg on columns */
export type AuthUserAuthenticatorsAvgFields = {
__typename?: 'authUserAuthenticators_avg_fields';
counter?: Maybe<Scalars['Float']>;
};
/** order by avg() on columns of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsAvgOrderBy = {
counter?: InputMaybe<OrderBy>;
};
/** Boolean expression to filter rows from the table "auth.user_authenticators". All fields are combined with a logical 'AND'. */
export type AuthUserAuthenticatorsBoolExp = {
_and?: InputMaybe<Array<AuthUserAuthenticatorsBoolExp>>;
_not?: InputMaybe<AuthUserAuthenticatorsBoolExp>;
_or?: InputMaybe<Array<AuthUserAuthenticatorsBoolExp>>;
counter?: InputMaybe<BigintComparisonExp>;
/** Boolean expression to filter rows from the table "auth.user_security_keys". All fields are combined with a logical 'AND'. */
export type AuthUserSecurityKeysBoolExp = {
_and?: InputMaybe<Array<AuthUserSecurityKeysBoolExp>>;
_not?: InputMaybe<AuthUserSecurityKeysBoolExp>;
_or?: InputMaybe<Array<AuthUserSecurityKeysBoolExp>>;
id?: InputMaybe<UuidComparisonExp>;
nickname?: InputMaybe<StringComparisonExp>;
user?: InputMaybe<UsersBoolExp>;
userId?: InputMaybe<UuidComparisonExp>;
};
/** aggregate max on columns */
export type AuthUserAuthenticatorsMaxFields = {
__typename?: 'authUserAuthenticators_max_fields';
counter?: Maybe<Scalars['bigint']>;
id?: Maybe<Scalars['uuid']>;
nickname?: Maybe<Scalars['String']>;
userId?: Maybe<Scalars['uuid']>;
};
/** order by max() on columns of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsMaxOrderBy = {
counter?: InputMaybe<OrderBy>;
/** order by max() on columns of table "auth.user_security_keys" */
export type AuthUserSecurityKeysMaxOrderBy = {
id?: InputMaybe<OrderBy>;
nickname?: InputMaybe<OrderBy>;
userId?: InputMaybe<OrderBy>;
};
/** aggregate min on columns */
export type AuthUserAuthenticatorsMinFields = {
__typename?: 'authUserAuthenticators_min_fields';
counter?: Maybe<Scalars['bigint']>;
id?: Maybe<Scalars['uuid']>;
nickname?: Maybe<Scalars['String']>;
userId?: Maybe<Scalars['uuid']>;
};
/** order by min() on columns of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsMinOrderBy = {
counter?: InputMaybe<OrderBy>;
/** order by min() on columns of table "auth.user_security_keys" */
export type AuthUserSecurityKeysMinOrderBy = {
id?: InputMaybe<OrderBy>;
nickname?: InputMaybe<OrderBy>;
userId?: InputMaybe<OrderBy>;
};
/** response of any mutation on the table "auth.user_authenticators" */
export type AuthUserAuthenticatorsMutationResponse = {
__typename?: 'authUserAuthenticators_mutation_response';
/** response of any mutation on the table "auth.user_security_keys" */
export type AuthUserSecurityKeysMutationResponse = {
__typename?: 'authUserSecurityKeys_mutation_response';
/** number of rows affected by the mutation */
affected_rows: Scalars['Int'];
/** data from the rows affected by the mutation */
returning: Array<AuthUserAuthenticators>;
returning: Array<AuthUserSecurityKeys>;
};
/** Ordering options when selecting data from "auth.user_authenticators". */
export type AuthUserAuthenticatorsOrderBy = {
counter?: InputMaybe<OrderBy>;
/** Ordering options when selecting data from "auth.user_security_keys". */
export type AuthUserSecurityKeysOrderBy = {
id?: InputMaybe<OrderBy>;
nickname?: InputMaybe<OrderBy>;
user?: InputMaybe<UsersOrderBy>;
userId?: InputMaybe<OrderBy>;
};
/** select columns of table "auth.user_authenticators" */
export enum AuthUserAuthenticatorsSelectColumn {
/** column name */
Counter = 'counter',
/** select columns of table "auth.user_security_keys" */
export enum AuthUserSecurityKeysSelectColumn {
/** column name */
Id = 'id',
/** column name */
@@ -219,96 +144,6 @@ export enum AuthUserAuthenticatorsSelectColumn {
UserId = 'userId'
}
/** aggregate stddev on columns */
export type AuthUserAuthenticatorsStddevFields = {
__typename?: 'authUserAuthenticators_stddev_fields';
counter?: Maybe<Scalars['Float']>;
};
/** order by stddev() on columns of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsStddevOrderBy = {
counter?: InputMaybe<OrderBy>;
};
/** aggregate stddev_pop on columns */
export type AuthUserAuthenticatorsStddevPopFields = {
__typename?: 'authUserAuthenticators_stddev_pop_fields';
counter?: Maybe<Scalars['Float']>;
};
/** order by stddev_pop() on columns of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsStddevPopOrderBy = {
counter?: InputMaybe<OrderBy>;
};
/** aggregate stddev_samp on columns */
export type AuthUserAuthenticatorsStddevSampFields = {
__typename?: 'authUserAuthenticators_stddev_samp_fields';
counter?: Maybe<Scalars['Float']>;
};
/** order by stddev_samp() on columns of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsStddevSampOrderBy = {
counter?: InputMaybe<OrderBy>;
};
/** aggregate sum on columns */
export type AuthUserAuthenticatorsSumFields = {
__typename?: 'authUserAuthenticators_sum_fields';
counter?: Maybe<Scalars['bigint']>;
};
/** order by sum() on columns of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsSumOrderBy = {
counter?: InputMaybe<OrderBy>;
};
/** aggregate var_pop on columns */
export type AuthUserAuthenticatorsVarPopFields = {
__typename?: 'authUserAuthenticators_var_pop_fields';
counter?: Maybe<Scalars['Float']>;
};
/** order by var_pop() on columns of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsVarPopOrderBy = {
counter?: InputMaybe<OrderBy>;
};
/** aggregate var_samp on columns */
export type AuthUserAuthenticatorsVarSampFields = {
__typename?: 'authUserAuthenticators_var_samp_fields';
counter?: Maybe<Scalars['Float']>;
};
/** order by var_samp() on columns of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsVarSampOrderBy = {
counter?: InputMaybe<OrderBy>;
};
/** aggregate variance on columns */
export type AuthUserAuthenticatorsVarianceFields = {
__typename?: 'authUserAuthenticators_variance_fields';
counter?: Maybe<Scalars['Float']>;
};
/** order by variance() on columns of table "auth.user_authenticators" */
export type AuthUserAuthenticatorsVarianceOrderBy = {
counter?: InputMaybe<OrderBy>;
};
/** Boolean expression to compare columns of type "bigint". All fields are combined with logical 'AND'. */
export type BigintComparisonExp = {
_eq?: InputMaybe<Scalars['bigint']>;
_gt?: InputMaybe<Scalars['bigint']>;
_gte?: InputMaybe<Scalars['bigint']>;
_in?: InputMaybe<Array<Scalars['bigint']>>;
_is_null?: InputMaybe<Scalars['Boolean']>;
_lt?: InputMaybe<Scalars['bigint']>;
_lte?: InputMaybe<Scalars['bigint']>;
_neq?: InputMaybe<Scalars['bigint']>;
_nin?: InputMaybe<Array<Scalars['bigint']>>;
};
/** Boolean expression to compare columns of type "citext". All fields are combined with logical 'AND'. */
export type CitextComparisonExp = {
_eq?: InputMaybe<Scalars['citext']>;
@@ -535,10 +370,10 @@ export type JsonbComparisonExp = {
/** mutation root */
export type MutationRoot = {
__typename?: 'mutation_root';
/** delete single row from the table: "auth.user_authenticators" */
deleteAuthUserAuthenticator?: Maybe<AuthUserAuthenticators>;
/** delete data from the table: "auth.user_authenticators" */
deleteAuthUserAuthenticators?: Maybe<AuthUserAuthenticatorsMutationResponse>;
/** delete single row from the table: "auth.user_security_keys" */
deleteAuthUserSecurityKey?: Maybe<AuthUserSecurityKeys>;
/** delete data from the table: "auth.user_security_keys" */
deleteAuthUserSecurityKeys?: Maybe<AuthUserSecurityKeysMutationResponse>;
/** delete single row from the table: "storage.files" */
deleteFile?: Maybe<Files>;
/** delete data from the table: "storage.files" */
@@ -571,14 +406,14 @@ export type MutationRoot = {
/** mutation root */
export type MutationRootDeleteAuthUserAuthenticatorArgs = {
export type MutationRootDeleteAuthUserSecurityKeyArgs = {
id: Scalars['uuid'];
};
/** mutation root */
export type MutationRootDeleteAuthUserAuthenticatorsArgs = {
where: AuthUserAuthenticatorsBoolExp;
export type MutationRootDeleteAuthUserSecurityKeysArgs = {
where: AuthUserSecurityKeysBoolExp;
};
@@ -693,12 +528,10 @@ export enum OrderBy {
export type QueryRoot = {
__typename?: 'query_root';
/** fetch data from the table: "auth.user_authenticators" using primary key columns */
authUserAuthenticator?: Maybe<AuthUserAuthenticators>;
/** fetch data from the table: "auth.user_authenticators" */
authUserAuthenticators: Array<AuthUserAuthenticators>;
/** fetch aggregated fields from the table: "auth.user_authenticators" */
authUserAuthenticatorsAggregate: AuthUserAuthenticatorsAggregate;
/** fetch data from the table: "auth.user_security_keys" using primary key columns */
authUserSecurityKey?: Maybe<AuthUserSecurityKeys>;
/** fetch data from the table: "auth.user_security_keys" */
authUserSecurityKeys: Array<AuthUserSecurityKeys>;
/** fetch data from the table: "storage.files" using primary key columns */
file?: Maybe<Files>;
/** fetch data from the table: "storage.files" */
@@ -716,26 +549,17 @@ export type QueryRoot = {
};
export type QueryRootAuthUserAuthenticatorArgs = {
export type QueryRootAuthUserSecurityKeyArgs = {
id: Scalars['uuid'];
};
export type QueryRootAuthUserAuthenticatorsArgs = {
distinct_on?: InputMaybe<Array<AuthUserAuthenticatorsSelectColumn>>;
export type QueryRootAuthUserSecurityKeysArgs = {
distinct_on?: InputMaybe<Array<AuthUserSecurityKeysSelectColumn>>;
limit?: InputMaybe<Scalars['Int']>;
offset?: InputMaybe<Scalars['Int']>;
order_by?: InputMaybe<Array<AuthUserAuthenticatorsOrderBy>>;
where?: InputMaybe<AuthUserAuthenticatorsBoolExp>;
};
export type QueryRootAuthUserAuthenticatorsAggregateArgs = {
distinct_on?: InputMaybe<Array<AuthUserAuthenticatorsSelectColumn>>;
limit?: InputMaybe<Scalars['Int']>;
offset?: InputMaybe<Scalars['Int']>;
order_by?: InputMaybe<Array<AuthUserAuthenticatorsOrderBy>>;
where?: InputMaybe<AuthUserAuthenticatorsBoolExp>;
order_by?: InputMaybe<Array<AuthUserSecurityKeysOrderBy>>;
where?: InputMaybe<AuthUserSecurityKeysBoolExp>;
};
@@ -791,12 +615,10 @@ export type QueryRootUsersArgs = {
export type SubscriptionRoot = {
__typename?: 'subscription_root';
/** fetch data from the table: "auth.user_authenticators" using primary key columns */
authUserAuthenticator?: Maybe<AuthUserAuthenticators>;
/** fetch data from the table: "auth.user_authenticators" */
authUserAuthenticators: Array<AuthUserAuthenticators>;
/** fetch aggregated fields from the table: "auth.user_authenticators" */
authUserAuthenticatorsAggregate: AuthUserAuthenticatorsAggregate;
/** fetch data from the table: "auth.user_security_keys" using primary key columns */
authUserSecurityKey?: Maybe<AuthUserSecurityKeys>;
/** fetch data from the table: "auth.user_security_keys" */
authUserSecurityKeys: Array<AuthUserSecurityKeys>;
/** fetch data from the table: "storage.files" using primary key columns */
file?: Maybe<Files>;
/** fetch data from the table: "storage.files" */
@@ -814,26 +636,17 @@ export type SubscriptionRoot = {
};
export type SubscriptionRootAuthUserAuthenticatorArgs = {
export type SubscriptionRootAuthUserSecurityKeyArgs = {
id: Scalars['uuid'];
};
export type SubscriptionRootAuthUserAuthenticatorsArgs = {
distinct_on?: InputMaybe<Array<AuthUserAuthenticatorsSelectColumn>>;
export type SubscriptionRootAuthUserSecurityKeysArgs = {
distinct_on?: InputMaybe<Array<AuthUserSecurityKeysSelectColumn>>;
limit?: InputMaybe<Scalars['Int']>;
offset?: InputMaybe<Scalars['Int']>;
order_by?: InputMaybe<Array<AuthUserAuthenticatorsOrderBy>>;
where?: InputMaybe<AuthUserAuthenticatorsBoolExp>;
};
export type SubscriptionRootAuthUserAuthenticatorsAggregateArgs = {
distinct_on?: InputMaybe<Array<AuthUserAuthenticatorsSelectColumn>>;
limit?: InputMaybe<Scalars['Int']>;
offset?: InputMaybe<Scalars['Int']>;
order_by?: InputMaybe<Array<AuthUserAuthenticatorsOrderBy>>;
where?: InputMaybe<AuthUserAuthenticatorsBoolExp>;
order_by?: InputMaybe<Array<AuthUserSecurityKeysOrderBy>>;
where?: InputMaybe<AuthUserSecurityKeysBoolExp>;
};
@@ -1045,10 +858,6 @@ export type TodosUpdates = {
export type Users = {
__typename?: 'users';
activeMfaType?: Maybe<Scalars['String']>;
/** An array relationship */
authenticators: Array<AuthUserAuthenticators>;
/** An aggregate relationship */
authenticators_aggregate: AuthUserAuthenticatorsAggregate;
avatarUrl: Scalars['String'];
createdAt: Scalars['timestamptz'];
currentChallenge?: Maybe<Scalars['String']>;
@@ -1066,42 +875,33 @@ export type Users = {
otpMethodLastUsed?: Maybe<Scalars['String']>;
phoneNumber?: Maybe<Scalars['String']>;
phoneNumberVerified: Scalars['Boolean'];
/** An array relationship */
securityKeys: Array<AuthUserSecurityKeys>;
updatedAt: Scalars['timestamptz'];
};
/** User account information. Don't modify its structure as Hasura Auth relies on it to function properly. */
export type UsersAuthenticatorsArgs = {
distinct_on?: InputMaybe<Array<AuthUserAuthenticatorsSelectColumn>>;
limit?: InputMaybe<Scalars['Int']>;
offset?: InputMaybe<Scalars['Int']>;
order_by?: InputMaybe<Array<AuthUserAuthenticatorsOrderBy>>;
where?: InputMaybe<AuthUserAuthenticatorsBoolExp>;
};
/** User account information. Don't modify its structure as Hasura Auth relies on it to function properly. */
export type UsersAuthenticatorsAggregateArgs = {
distinct_on?: InputMaybe<Array<AuthUserAuthenticatorsSelectColumn>>;
limit?: InputMaybe<Scalars['Int']>;
offset?: InputMaybe<Scalars['Int']>;
order_by?: InputMaybe<Array<AuthUserAuthenticatorsOrderBy>>;
where?: InputMaybe<AuthUserAuthenticatorsBoolExp>;
};
/** User account information. Don't modify its structure as Hasura Auth relies on it to function properly. */
export type UsersMetadataArgs = {
path?: InputMaybe<Scalars['String']>;
};
/** User account information. Don't modify its structure as Hasura Auth relies on it to function properly. */
export type UsersSecurityKeysArgs = {
distinct_on?: InputMaybe<Array<AuthUserSecurityKeysSelectColumn>>;
limit?: InputMaybe<Scalars['Int']>;
offset?: InputMaybe<Scalars['Int']>;
order_by?: InputMaybe<Array<AuthUserSecurityKeysOrderBy>>;
where?: InputMaybe<AuthUserSecurityKeysBoolExp>;
};
/** Boolean expression to filter rows from the table "auth.users". All fields are combined with a logical 'AND'. */
export type UsersBoolExp = {
_and?: InputMaybe<Array<UsersBoolExp>>;
_not?: InputMaybe<UsersBoolExp>;
_or?: InputMaybe<Array<UsersBoolExp>>;
activeMfaType?: InputMaybe<StringComparisonExp>;
authenticators?: InputMaybe<AuthUserAuthenticatorsBoolExp>;
avatarUrl?: InputMaybe<StringComparisonExp>;
createdAt?: InputMaybe<TimestamptzComparisonExp>;
currentChallenge?: InputMaybe<StringComparisonExp>;
@@ -1119,13 +919,13 @@ export type UsersBoolExp = {
otpMethodLastUsed?: InputMaybe<StringComparisonExp>;
phoneNumber?: InputMaybe<StringComparisonExp>;
phoneNumberVerified?: InputMaybe<BooleanComparisonExp>;
securityKeys?: InputMaybe<AuthUserSecurityKeysBoolExp>;
updatedAt?: InputMaybe<TimestamptzComparisonExp>;
};
/** Ordering options when selecting data from "auth.users". */
export type UsersOrderBy = {
activeMfaType?: InputMaybe<OrderBy>;
authenticators_aggregate?: InputMaybe<AuthUserAuthenticatorsAggregateOrderBy>;
avatarUrl?: InputMaybe<OrderBy>;
createdAt?: InputMaybe<OrderBy>;
currentChallenge?: InputMaybe<OrderBy>;
@@ -1143,6 +943,7 @@ export type UsersOrderBy = {
otpMethodLastUsed?: InputMaybe<OrderBy>;
phoneNumber?: InputMaybe<OrderBy>;
phoneNumberVerified?: InputMaybe<OrderBy>;
securityKeys_aggregate?: InputMaybe<AuthUserSecurityKeysAggregateOrderBy>;
updatedAt?: InputMaybe<OrderBy>;
};
@@ -1220,11 +1021,11 @@ export type SecurityKeysQueryVariables = Exact<{
}>;
export type SecurityKeysQuery = { __typename?: 'query_root', authUserAuthenticators: Array<{ __typename?: 'authUserAuthenticators', id: string, nickname?: string | null }> };
export type SecurityKeysQuery = { __typename?: 'query_root', authUserSecurityKeys: Array<{ __typename?: 'authUserSecurityKeys', id: string, nickname?: string | null }> };
export type RemoveSecurityKeyMutationVariables = Exact<{
id: Scalars['uuid'];
}>;
export type RemoveSecurityKeyMutation = { __typename?: 'mutation_root', deleteAuthUserAuthenticator?: { __typename?: 'authUserAuthenticators', id: string } | null };
export type RemoveSecurityKeyMutation = { __typename?: 'mutation_root', deleteAuthUserSecurityKey?: { __typename?: 'authUserSecurityKeys', id: string } | null };

View File

@@ -10,7 +10,7 @@ import { useAuthQuery } from '@nhost/react-apollo'
const SECURITY_KEYS_LIST = gql`
query securityKeys($userId: uuid!) {
authUserAuthenticators(where: { userId: { _eq: $userId } }) {
authUserSecurityKeys(where: { userId: { _eq: $userId } }) {
id
nickname
}
@@ -19,7 +19,7 @@ const SECURITY_KEYS_LIST = gql`
const REMOVE_SECURITY_KEY = gql`
mutation removeSecurityKey($id: uuid!) {
deleteAuthUserAuthenticator(id: $id) {
deleteAuthUserSecurityKey(id: $id) {
id
}
}
@@ -28,13 +28,14 @@ const REMOVE_SECURITY_KEY = gql`
export const SecurityKeys: React.FC = () => {
const { add } = useAddSecurityKey()
const userId = useUserId()
// Nickname of the security key
const [nickname, setNickname] = useInputState('')
const [list, setList] = useState<{ id: string; nickname?: string | null }[]>([])
useAuthQuery<SecurityKeysQuery>(SECURITY_KEYS_LIST, {
variables: { userId },
onCompleted: ({ authUserAuthenticators }) => {
if (authUserAuthenticators) {
setList(authUserAuthenticators || [])
onCompleted: ({ authUserSecurityKeys }) => {
if (authUserSecurityKeys) {
setList(authUserSecurityKeys || [])
}
}
})
@@ -52,9 +53,9 @@ export const SecurityKeys: React.FC = () => {
}
}
const [removeKey] = useMutation<RemoveSecurityKeyMutation>(REMOVE_SECURITY_KEY, {
onCompleted: ({ deleteAuthUserAuthenticator }) => {
if (deleteAuthUserAuthenticator?.id) {
setList(list.filter((item) => item.id !== deleteAuthUserAuthenticator.id))
onCompleted: ({ deleteAuthUserSecurityKey }) => {
if (deleteAuthUserSecurityKey?.id) {
setList(list.filter((item) => item.id !== deleteAuthUserSecurityKey.id))
}
}
})

View File

@@ -3,12 +3,11 @@ import { useNavigate } from 'react-router-dom'
import { Button, Modal, TextInput } from '@mantine/core'
import { showNotification } from '@mantine/notifications'
import { useSignInEmailPassword, useSignInSecurityKeyEmail } from '@nhost/react'
import { useSignInEmailPassword } from '@nhost/react'
import AuthLink from '../components/AuthLink'
export const EmailPassword: React.FC = () => {
const { signInSecurityKeyEmail } = useSignInSecurityKeyEmail()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [otp, setOtp] = useState('')
@@ -91,20 +90,6 @@ export const EmailPassword: React.FC = () => {
size="lg"
style={{ marginBottom: '0.5em' }}
/>
<Button
fullWidth
onClick={() => {
signInSecurityKeyEmail(email)
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log('bummer', err)
})
}}
>
SecurityKey
</Button>
<Button fullWidth onClick={signIn}>
Sign in
</Button>

View File

@@ -1,4 +1,4 @@
import { FaLock } from 'react-icons/fa'
import { FaFingerprint, FaLock } from 'react-icons/fa'
import { Link, Route, Routes, useNavigate } from 'react-router-dom'
import { Anchor, Center, Divider, Text } from '@mantine/core'
@@ -11,13 +11,17 @@ import OAuthLinks from '../components/OauthLinks'
import { EmailPassword } from './email-password'
import { EmailPasswordless } from './email-passwordless'
import { ForgotPassword } from './forgot-password'
import { SecurityKeySignIn } from './security-key'
const Index: React.FC = () => (
<>
<OAuthLinks />
<Divider my="sm" />
<AuthLink leftIcon={<FaFingerprint />} variant="outline" link="/sign-in/security-key">
Continue with a security key
</AuthLink>
<AuthLink leftIcon={<FaLock />} variant="outline" link="/sign-in/email-passwordless">
Continue passwordless
Continue with a magic link
</AuthLink>
<AuthLink variant="subtle" link="/sign-in/email-password">
Continue with email + password
@@ -36,7 +40,7 @@ export const SignInPage: React.FC = () => {
return (
<AuthLayout
title="Log in to the Application"
title="Sign in to the Application"
footer={
<Center>
<Text>
@@ -57,6 +61,7 @@ export const SignInPage: React.FC = () => {
<Route path="/email-password" element={<EmailPassword />} />
<Route path="/forgot-password" element={<ForgotPassword />} />
<Route path="/email-passwordless" element={<EmailPasswordless />} />
<Route path="/security-key" element={<SecurityKeySignIn />} />
</Routes>
</AuthLayout>
)

View File

@@ -0,0 +1,61 @@
import { FormEvent, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { Button, Modal, SimpleGrid, TextInput } from '@mantine/core'
import { showNotification } from '@mantine/notifications'
import { useSignInEmailSecurityKey } from '@nhost/react'
export const SecurityKeySignIn: React.FC = () => {
const { signInEmailSecurityKey } = useSignInEmailSecurityKey()
const [email, setEmail] = useState('')
const navigate = useNavigate()
const [emailVerificationToggle, setEmailVerificationToggle] = useState(false)
const signIn = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
const { isError, isSuccess, needsEmailVerification, error } = await signInEmailSecurityKey(
email
)
if (isError) {
showNotification({
color: 'red',
title: 'Error',
message: error?.message
})
} else if (needsEmailVerification) {
setEmailVerificationToggle(true)
} else if (isSuccess) {
navigate('/', { replace: true })
}
}
return (
<SimpleGrid cols={1} spacing={6}>
<Modal
title="Awaiting email verification"
transition="fade"
centered
transitionDuration={600}
opened={emailVerificationToggle}
onClose={() => {
setEmailVerificationToggle(false)
}}
>
You need to verify your email first. Please check your mailbox and follow the confirmation
link to complete the registration.
</Modal>
<form onSubmit={signIn}>
<TextInput
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email Address"
autoFocus
style={{ marginBottom: '0.5em' }}
/>
<Button fullWidth type="submit">
Sign in with a security key
</Button>
</form>
</SimpleGrid>
)
}

View File

@@ -1,62 +0,0 @@
import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { Button, Modal, TextInput } from '@mantine/core'
import { showNotification } from '@mantine/notifications'
import { useSignInSecurityKeyEmail } from '@nhost/react'
import AuthLink from '../components/AuthLink'
export const EmailPassword: React.FC = () => {
const { signInSecurityKeyEmail } = useSignInSecurityKeyEmail()
const [email, setEmail] = useState('')
const navigate = useNavigate()
const [emailVerificationToggle, setEmailVerificationToggle] = useState(false)
const signIn = async () => {
const result = await signInSecurityKeyEmail(email)
if (result.isError) {
showNotification({
color: 'red',
title: 'Error',
message: result.error?.message
})
} else if (result.needsEmailVerification) {
setEmailVerificationToggle(true)
} else if (result.isSuccess) {
navigate('/', { replace: true })
}
}
return (
<>
<Modal
title="Awaiting email verification"
transition="fade"
centered
transitionDuration={600}
opened={emailVerificationToggle}
onClose={() => {
setEmailVerificationToggle(false)
}}
>
You need to verify your email first. Please check your mailbox and follow the confirmation
link to complete the registration.
</Modal>
<TextInput
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email Address"
size="lg"
autoFocus
style={{ marginBottom: '0.5em' }}
/>
<Button fullWidth onClick={signIn}>
Sign in
</Button>
<AuthLink link="/sign-in/forgot-password" variant="white">
Forgot password?
</AuthLink>
</>
)
}

View File

@@ -1,4 +1,4 @@
import { FaLock } from 'react-icons/fa'
import { FaFingerprint, FaLock } from 'react-icons/fa'
import { Link, Route, Routes } from 'react-router-dom'
import { Anchor, Center, Divider, Text } from '@mantine/core'
@@ -10,6 +10,7 @@ import OAuthLinks from '../components/OauthLinks'
import { EmailPassword } from './email-password'
import { EmailPasswordless } from './email-passwordless'
import { SecurityKeySignUp } from './security-key'
const Index: React.FC = () => {
const isAnonymous = useUserIsAnonymous()
@@ -21,8 +22,11 @@ const Index: React.FC = () => {
<Divider my="sm" />
</>
)}
<AuthLink leftIcon={<FaFingerprint />} variant="outline" link="/sign-up/security-key">
Continue with a security key
</AuthLink>
<AuthLink leftIcon={<FaLock />} variant="outline" link="/sign-up/email-passwordless">
Continue with passwordless email
Continue with a magic link
</AuthLink>
<AuthLink variant="subtle" link="/sign-up/email-password">
Continue with email + password
@@ -33,13 +37,13 @@ const Index: React.FC = () => {
export const SignUpPage: React.FC = () => {
return (
<AuthLayout
title="Sign up"
title="Sign up to the application"
footer={
<Center>
<Text>
Already have an account?{' '}
<Anchor component={Link} to="/sign-in">
Log in
Sign in
</Anchor>
</Text>
</Center>
@@ -49,6 +53,7 @@ export const SignUpPage: React.FC = () => {
<Route path="/" element={<Index />} />
<Route path="/email-password" element={<EmailPassword />} />
<Route path="/email-passwordless" element={<EmailPasswordless />} />
<Route path="/security-key" element={<SecurityKeySignUp />} />
</Routes>
</AuthLayout>
)

View File

@@ -0,0 +1,61 @@
import { FormEvent, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { Button, Modal, SimpleGrid, TextInput } from '@mantine/core'
import { showNotification } from '@mantine/notifications'
import { useSignUpEmailSecurityKeyEmail } from '@nhost/react'
export const SecurityKeySignUp: React.FC = () => {
const { signUpEmailSecurityKey } = useSignUpEmailSecurityKeyEmail()
const [email, setEmail] = useState('')
const navigate = useNavigate()
const [emailVerificationToggle, setEmailVerificationToggle] = useState(false)
const signIn = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
const { isError, isSuccess, needsEmailVerification, error } = await signUpEmailSecurityKey(
email
)
if (isError) {
showNotification({
color: 'red',
title: 'Error',
message: error?.message
})
} else if (needsEmailVerification) {
setEmailVerificationToggle(true)
} else if (isSuccess) {
navigate('/', { replace: true })
}
}
return (
<SimpleGrid cols={1} spacing={6}>
<Modal
title="Awaiting email verification"
transition="fade"
centered
transitionDuration={600}
opened={emailVerificationToggle}
onClose={() => {
setEmailVerificationToggle(false)
}}
>
A email has been sent to {email}. Please follow the link to verify your email address and to
complete your registration.
</Modal>
<form onSubmit={signIn}>
<TextInput
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email Address"
autoFocus
style={{ marginBottom: '0.5em' }}
/>
<Button fullWidth type="submit">
Sign up with a security key
</Button>
</form>
</SimpleGrid>
)
}

View File

@@ -5,7 +5,7 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.11.0
image: nhost/hasura-auth:0.13.0
storage:
image: nhost/hasura-storage:0.2.4
auth:

View File

@@ -1,4 +1,4 @@
# Docker image versions used in the cloud
hasura: v2.10.1
auth: 0.11.0
auth: 0.13.0
storage: 0.2.4

View File

@@ -1,5 +1,12 @@
# @nhost/apollo
## 0.5.30
### Patch Changes
- Updated dependencies [739a3c45]
- @nhost/nhost-js@1.5.0
## 0.5.29
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/apollo",
"version": "0.5.29",
"version": "0.5.30",
"description": "Nhost Apollo Client library",
"license": "MIT",
"keywords": [

View File

@@ -1,5 +1,11 @@
# @nhost/core
## 0.8.0
### Minor Changes
- 8e4d790b: Sign up with an email and a security key.
## 0.7.7
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/core",
"version": "0.7.7",
"version": "0.8.0",
"description": "Nhost core client library",
"license": "MIT",
"keywords": [

View File

@@ -1,4 +1,9 @@
import type { NhostSession, PasswordlessOptions, SignUpOptions } from '../types'
import type {
NhostSession,
PasswordlessOptions,
SignUpOptions,
SignUpSecurityKeyOptions
} from '../types'
export type AuthEvents =
| { type: 'SESSION_UPDATE'; data: { session: NhostSession } }
@@ -18,6 +23,7 @@ export type AuthEvents =
}
| { type: 'PASSWORDLESS_SMS_OTP'; phoneNumber?: string; otp?: string }
| { type: 'SIGNUP_EMAIL_PASSWORD'; email?: string; password?: string; options?: SignUpOptions }
| { type: 'SIGNUP_SECURITY_KEY'; email?: string; options?: SignUpSecurityKeyOptions }
| { type: 'SIGNOUT'; all?: boolean }
| { type: 'SIGNIN_MFA_TOTP'; ticket?: string; otp?: string }
| { type: 'SIGNED_IN' }

View File

@@ -1,10 +1,12 @@
import type { AxiosRequestConfig } from 'axios'
import { assign, createMachine, send } from 'xstate'
import { startAuthentication } from '@simplewebauthn/browser'
import { startAuthentication, startRegistration } from '@simplewebauthn/browser'
import type {
AuthenticationCredentialJSON,
PublicKeyCredentialRequestOptionsJSON
PublicKeyCredentialCreationOptionsJSON,
PublicKeyCredentialRequestOptionsJSON,
RegistrationCredentialJSON
} from '@simplewebauthn/typescript-types'
import {
@@ -72,6 +74,7 @@ type AuthServices = {
refreshToken: { data: NhostSessionResponse }
signout: { data: SignOutResponse }
signUpEmailPassword: { data: SignUpResponse }
signUpSecurityKey: { data: SignUpResponse }
importRefreshToken: { data: NhostSessionResponse }
}
@@ -371,6 +374,7 @@ export const createAuthMachine = ({
incomplete: {
on: {
SIGNUP_EMAIL_PASSWORD: 'emailPassword',
SIGNUP_SECURITY_KEY: 'securityKey',
PASSWORDLESS_EMAIL: 'passwordlessEmail',
PASSWORDLESS_SMS: 'passwordlessSms',
PASSWORDLESS_SMS_OTP: 'passwordlessSmsOtp'
@@ -411,6 +415,34 @@ export const createAuthMachine = ({
]
}
},
securityKey: {
entry: ['resetErrors'],
invoke: {
src: 'signUpSecurityKey',
id: 'signUpSecurityKey',
onDone: [
{
cond: 'hasSession',
actions: ['saveSession', 'reportTokenChanged'],
target: '#nhost.authentication.signedIn'
},
{
actions: 'clearContext',
target: ['#nhost.authentication.signedOut', 'incomplete.needsEmailVerification']
}
],
onError: [
{
cond: 'unverified',
target: 'incomplete.needsEmailVerification'
},
{
actions: 'saveRegistrationError',
target: 'incomplete.failed'
}
]
}
},
passwordlessEmail: {
entry: ['resetErrors'],
invoke: {
@@ -772,7 +804,36 @@ export const createAuthMachine = ({
})
}
},
signUpSecurityKey: async (_, { email, options }) => {
if (!isValidEmail(email)) {
return Promise.reject<SignUpResponse>({ error: INVALID_EMAIL_ERROR })
}
// TODO anonymous users
const nickname = options?.nickname
/*
* The `/signup/webauthn` endpoint accepts any option from SignUpOptions,
* We therefore remove the nickname from the options object before sending it to the server,
* as options if of type `SignUpSecurityKeyOptions`, which extends `SignUpOptions` with the optional `nickname` property.
*/
if (nickname) delete options.nickname
const webAuthnOptions = await postRequest<PublicKeyCredentialCreationOptionsJSON>(
'/signup/webauthn',
{ email, options }
)
let credential: RegistrationCredentialJSON
try {
credential = await startRegistration(webAuthnOptions)
} catch (e) {
throw new CodifiedError(e as Error)
}
return postRequest<SignUpResponse>('/signup/webauthn/verify', {
credential,
options: {
redirectTo: options?.redirectTo,
nickname
}
})
},
importRefreshToken: async () => {
let error: ValidationErrorPayload | null = null
if (autoSignIn) {

View File

@@ -2,110 +2,10 @@
export interface Typegen0 {
'@@xstate/typegen': true
eventsCausingActions: {
saveSession:
| 'SESSION_UPDATE'
| 'done.invoke.importRefreshToken'
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.refreshToken'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.passwordlessSmsOtp'
resetTimer: 'SESSION_UPDATE' | 'done.invoke.refreshToken' | ''
reportTokenChanged:
| 'SESSION_UPDATE'
| 'done.invoke.importRefreshToken'
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.refreshToken'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.passwordlessSmsOtp'
saveAuthenticationError:
| 'error.platform.importRefreshToken'
| 'error.platform.signingOut'
| 'error.platform.authenticateUserWithPassword'
| 'error.platform.authenticateAnonymously'
| 'error.platform.signInMfaTotp'
| 'error.platform.authenticateUserWithSecurityKey'
| 'error.platform.authenticateWithToken'
saveMfaTicket: 'done.invoke.authenticateUserWithPassword'
saveRefreshAttempt: 'error.platform.refreshToken'
clearContext:
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.passwordlessEmail'
| 'done.invoke.passwordlessSms'
saveRegistrationError:
| 'error.platform.signUpEmailPassword'
| 'error.platform.passwordlessEmail'
| 'error.platform.passwordlessSms'
| 'error.platform.passwordlessSmsOtp'
resetErrors:
| 'SESSION_UPDATE'
| 'done.invoke.importRefreshToken'
| ''
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.passwordlessSmsOtp'
| 'SIGNUP_EMAIL_PASSWORD'
| 'PASSWORDLESS_EMAIL'
| 'PASSWORDLESS_SMS'
| 'PASSWORDLESS_SMS_OTP'
reportSignedOut:
| 'error.platform.importRefreshToken'
| 'error.platform.authenticateUserWithPassword'
| 'error.platform.authenticateUserWithSecurityKey'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.passwordlessEmail'
| 'done.invoke.passwordlessSms'
destroyRefreshToken: 'xstate.init'
clearContextExceptRefreshToken: 'SIGNOUT'
reportSignedIn:
| 'SESSION_UPDATE'
| 'done.invoke.importRefreshToken'
| ''
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.passwordlessSmsOtp'
cleanUrl:
| 'SESSION_UPDATE'
| 'done.invoke.importRefreshToken'
| ''
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.passwordlessSmsOtp'
broadcastToken:
| 'SESSION_UPDATE'
| 'done.invoke.importRefreshToken'
| ''
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.passwordlessSmsOtp'
}
internalEvents: {
'done.invoke.importRefreshToken': {
type: 'done.invoke.importRefreshToken'
'': { type: '' }
'done.invoke.authenticateAnonymously': {
type: 'done.invoke.authenticateAnonymously'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
@@ -114,65 +14,21 @@ export interface Typegen0 {
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.authenticateAnonymously': {
type: 'done.invoke.authenticateAnonymously'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.signInMfaTotp': {
type: 'done.invoke.signInMfaTotp'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.authenticateUserWithSecurityKey': {
type: 'done.invoke.authenticateUserWithSecurityKey'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.refreshToken': {
type: 'done.invoke.refreshToken'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.authenticateWithToken': {
type: 'done.invoke.authenticateWithToken'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.signUpEmailPassword': {
type: 'done.invoke.signUpEmailPassword'
'done.invoke.importRefreshToken': {
type: 'done.invoke.importRefreshToken'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.passwordlessSmsOtp': {
type: 'done.invoke.passwordlessSmsOtp'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'': { type: '' }
'error.platform.importRefreshToken': {
type: 'error.platform.importRefreshToken'
data: unknown
}
'error.platform.signingOut': { type: 'error.platform.signingOut'; data: unknown }
'error.platform.authenticateUserWithPassword': {
type: 'error.platform.authenticateUserWithPassword'
data: unknown
}
'error.platform.authenticateAnonymously': {
type: 'error.platform.authenticateAnonymously'
data: unknown
}
'error.platform.signInMfaTotp': { type: 'error.platform.signInMfaTotp'; data: unknown }
'error.platform.authenticateUserWithSecurityKey': {
type: 'error.platform.authenticateUserWithSecurityKey'
data: unknown
}
'error.platform.authenticateWithToken': {
type: 'error.platform.authenticateWithToken'
data: unknown
}
'error.platform.refreshToken': { type: 'error.platform.refreshToken'; data: unknown }
'done.invoke.passwordlessEmail': {
type: 'done.invoke.passwordlessEmail'
data: unknown
@@ -183,8 +39,54 @@ export interface Typegen0 {
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'error.platform.signUpEmailPassword': {
type: 'error.platform.signUpEmailPassword'
'done.invoke.passwordlessSmsOtp': {
type: 'done.invoke.passwordlessSmsOtp'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.refreshToken': {
type: 'done.invoke.refreshToken'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.signInMfaTotp': {
type: 'done.invoke.signInMfaTotp'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.signUpEmailPassword': {
type: 'done.invoke.signUpEmailPassword'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.signUpSecurityKey': {
type: 'done.invoke.signUpSecurityKey'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'done.invoke.signingOut': {
type: 'done.invoke.signingOut'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'error.platform.authenticateAnonymously': {
type: 'error.platform.authenticateAnonymously'
data: unknown
}
'error.platform.authenticateUserWithPassword': {
type: 'error.platform.authenticateUserWithPassword'
data: unknown
}
'error.platform.authenticateUserWithSecurityKey': {
type: 'error.platform.authenticateUserWithSecurityKey'
data: unknown
}
'error.platform.authenticateWithToken': {
type: 'error.platform.authenticateWithToken'
data: unknown
}
'error.platform.importRefreshToken': {
type: 'error.platform.importRefreshToken'
data: unknown
}
'error.platform.passwordlessEmail': { type: 'error.platform.passwordlessEmail'; data: unknown }
@@ -193,28 +95,33 @@ export interface Typegen0 {
type: 'error.platform.passwordlessSmsOtp'
data: unknown
}
'error.platform.refreshToken': { type: 'error.platform.refreshToken'; data: unknown }
'error.platform.signInMfaTotp': { type: 'error.platform.signInMfaTotp'; data: unknown }
'error.platform.signUpEmailPassword': {
type: 'error.platform.signUpEmailPassword'
data: unknown
}
'error.platform.signUpSecurityKey': { type: 'error.platform.signUpSecurityKey'; data: unknown }
'error.platform.signingOut': { type: 'error.platform.signingOut'; data: unknown }
'xstate.after(1000)#nhost.authentication.signedIn.refreshTimer.running.pending': {
type: 'xstate.after(1000)#nhost.authentication.signedIn.refreshTimer.running.pending'
}
'xstate.init': { type: 'xstate.init' }
'done.invoke.signingOut': {
type: 'done.invoke.signingOut'
data: unknown
__tip: 'See the XState TS docs to learn how to strongly type this.'
}
'xstate.stop': { type: 'xstate.stop' }
}
invokeSrcNameMap: {
importRefreshToken: 'done.invoke.importRefreshToken'
signout: 'done.invoke.signingOut'
signInPassword: 'done.invoke.authenticateUserWithPassword'
signInAnonymous: 'done.invoke.authenticateAnonymously'
signInMfaTotp: 'done.invoke.signInMfaTotp'
signInSecurityKeyEmail: 'done.invoke.authenticateUserWithSecurityKey'
refreshToken: 'done.invoke.refreshToken' | 'done.invoke.authenticateWithToken'
signUpEmailPassword: 'done.invoke.signUpEmailPassword'
passwordlessEmail: 'done.invoke.passwordlessEmail'
passwordlessSms: 'done.invoke.passwordlessSms'
passwordlessSmsOtp: 'done.invoke.passwordlessSmsOtp'
refreshToken: 'done.invoke.refreshToken' | 'done.invoke.authenticateWithToken'
signInAnonymous: 'done.invoke.authenticateAnonymously'
signInMfaTotp: 'done.invoke.signInMfaTotp'
signInPassword: 'done.invoke.authenticateUserWithPassword'
signInSecurityKeyEmail: 'done.invoke.authenticateUserWithSecurityKey'
signUpEmailPassword: 'done.invoke.signUpEmailPassword'
signUpSecurityKey: 'done.invoke.signUpSecurityKey'
signout: 'done.invoke.signingOut'
}
missingImplementations: {
actions: never
@@ -222,92 +129,238 @@ export interface Typegen0 {
guards: never
delays: never
}
eventsCausingActions: {
broadcastToken:
| ''
| 'SESSION_UPDATE'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.importRefreshToken'
| 'done.invoke.passwordlessSmsOtp'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.signUpSecurityKey'
cleanUrl:
| ''
| 'SESSION_UPDATE'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.importRefreshToken'
| 'done.invoke.passwordlessSmsOtp'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.signUpSecurityKey'
clearContext:
| 'done.invoke.passwordlessEmail'
| 'done.invoke.passwordlessSms'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.signUpSecurityKey'
clearContextExceptRefreshToken: 'SIGNOUT'
destroyRefreshToken:
| 'SESSION_UPDATE'
| 'SIGNIN_ANONYMOUS'
| 'SIGNIN_MFA_TOTP'
| 'SIGNIN_PASSWORD'
| 'SIGNIN_SECURITY_KEY_EMAIL'
| 'done.invoke.signingOut'
| 'error.platform.signingOut'
| 'xstate.stop'
reportSignedIn:
| ''
| 'SESSION_UPDATE'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.importRefreshToken'
| 'done.invoke.passwordlessSmsOtp'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.signUpSecurityKey'
reportSignedOut:
| 'SIGNOUT'
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.passwordlessEmail'
| 'done.invoke.passwordlessSms'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.signUpSecurityKey'
| 'error.platform.authenticateAnonymously'
| 'error.platform.authenticateUserWithPassword'
| 'error.platform.authenticateUserWithSecurityKey'
| 'error.platform.authenticateWithToken'
| 'error.platform.importRefreshToken'
| 'error.platform.signInMfaTotp'
reportTokenChanged:
| 'SESSION_UPDATE'
| 'SIGNIN_ANONYMOUS'
| 'SIGNIN_MFA_TOTP'
| 'SIGNIN_PASSWORD'
| 'SIGNIN_SECURITY_KEY_EMAIL'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.importRefreshToken'
| 'done.invoke.passwordlessSmsOtp'
| 'done.invoke.refreshToken'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.signUpSecurityKey'
| 'done.invoke.signingOut'
| 'error.platform.signingOut'
| 'xstate.stop'
resetErrors:
| ''
| 'PASSWORDLESS_EMAIL'
| 'PASSWORDLESS_SMS'
| 'PASSWORDLESS_SMS_OTP'
| 'SESSION_UPDATE'
| 'SIGNIN_ANONYMOUS'
| 'SIGNIN_MFA_TOTP'
| 'SIGNIN_PASSWORD'
| 'SIGNIN_SECURITY_KEY_EMAIL'
| 'SIGNUP_EMAIL_PASSWORD'
| 'SIGNUP_SECURITY_KEY'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.importRefreshToken'
| 'done.invoke.passwordlessEmail'
| 'done.invoke.passwordlessSms'
| 'done.invoke.passwordlessSmsOtp'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.signUpSecurityKey'
| 'error.platform.authenticateWithToken'
| 'xstate.init'
resetTimer: '' | 'SESSION_UPDATE' | 'done.invoke.refreshToken'
saveAuthenticationError:
| 'error.platform.authenticateAnonymously'
| 'error.platform.authenticateUserWithPassword'
| 'error.platform.authenticateUserWithSecurityKey'
| 'error.platform.authenticateWithToken'
| 'error.platform.importRefreshToken'
| 'error.platform.signInMfaTotp'
| 'error.platform.signingOut'
saveMfaTicket: 'done.invoke.authenticateUserWithPassword'
saveRefreshAttempt: 'error.platform.refreshToken'
saveRegistrationError:
| 'error.platform.passwordlessEmail'
| 'error.platform.passwordlessSms'
| 'error.platform.passwordlessSmsOtp'
| 'error.platform.signUpEmailPassword'
| 'error.platform.signUpSecurityKey'
saveSession:
| 'SESSION_UPDATE'
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.authenticateUserWithPassword'
| 'done.invoke.authenticateUserWithSecurityKey'
| 'done.invoke.authenticateWithToken'
| 'done.invoke.importRefreshToken'
| 'done.invoke.passwordlessSmsOtp'
| 'done.invoke.refreshToken'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.signUpSecurityKey'
}
eventsCausingServices: {
importRefreshToken: 'xstate.init'
signInPassword: 'SIGNIN_PASSWORD'
signInAnonymous: 'SIGNIN_ANONYMOUS'
signInSecurityKeyEmail: 'SIGNIN_SECURITY_KEY_EMAIL'
signInMfaTotp: 'SIGNIN_MFA_TOTP'
signout: 'SIGNOUT'
refreshToken: '' | 'TRY_TOKEN'
signUpEmailPassword: 'SIGNUP_EMAIL_PASSWORD'
importRefreshToken:
| 'done.invoke.authenticateWithToken'
| 'done.invoke.passwordlessEmail'
| 'done.invoke.passwordlessSms'
| 'done.invoke.passwordlessSmsOtp'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.signUpSecurityKey'
| 'error.platform.authenticateWithToken'
| 'xstate.init'
passwordlessEmail: 'PASSWORDLESS_EMAIL'
passwordlessSms: 'PASSWORDLESS_SMS'
passwordlessSmsOtp: 'PASSWORDLESS_SMS_OTP'
refreshToken: '' | 'TRY_TOKEN'
signInAnonymous: 'SIGNIN_ANONYMOUS'
signInMfaTotp: 'SIGNIN_MFA_TOTP'
signInPassword: 'SIGNIN_PASSWORD'
signInSecurityKeyEmail: 'SIGNIN_SECURITY_KEY_EMAIL'
signUpEmailPassword: 'SIGNUP_EMAIL_PASSWORD'
signUpSecurityKey: 'SIGNUP_SECURITY_KEY'
signout: 'SIGNOUT'
}
eventsCausingGuards: {
hasSession: 'SESSION_UPDATE' | 'done.invoke.signUpEmailPassword'
isSignedIn: '' | 'error.platform.authenticateWithToken'
hasMfaTicket: 'done.invoke.authenticateUserWithPassword'
hasRefreshToken: ''
hasSession:
| 'SESSION_UPDATE'
| 'done.invoke.signUpEmailPassword'
| 'done.invoke.signUpSecurityKey'
isAnonymous: 'SIGNED_IN'
isAutoRefreshDisabled: ''
isSignedIn: '' | 'error.platform.authenticateWithToken'
noToken: ''
refreshTimerShouldRefresh: ''
unverified:
| 'error.platform.authenticateUserWithPassword'
| 'error.platform.authenticateUserWithSecurityKey'
| 'error.platform.signUpEmailPassword'
noToken: ''
isAutoRefreshDisabled: ''
hasRefreshToken: ''
refreshTimerShouldRefresh: ''
isAnonymous: 'SIGNED_IN'
| 'error.platform.signUpSecurityKey'
}
eventsCausingDelays: {}
matchesStates:
| 'authentication'
| 'authentication.starting'
| 'authentication.signedOut'
| 'authentication.signedOut.noErrors'
| 'authentication.signedOut.success'
| 'authentication.signedOut.needsSmsOtp'
| 'authentication.signedOut.needsMfa'
| 'authentication.signedOut.failed'
| 'authentication.signedOut.signingOut'
| 'authentication.authenticating'
| 'authentication.authenticating.password'
| 'authentication.authenticating.anonymous'
| 'authentication.authenticating.mfa'
| 'authentication.authenticating.mfa.totp'
| 'authentication.authenticating.password'
| 'authentication.authenticating.securityKeyEmail'
| 'authentication.signedIn'
| 'authentication.signedIn.refreshTimer'
| 'authentication.signedIn.refreshTimer.disabled'
| 'authentication.signedIn.refreshTimer.stopped'
| 'authentication.signedIn.refreshTimer.idle'
| 'authentication.signedIn.refreshTimer.running'
| 'authentication.signedIn.refreshTimer.running.pending'
| 'authentication.signedIn.refreshTimer.running.refreshing'
| 'token'
| 'token.idle'
| 'token.idle.noErrors'
| 'token.idle.error'
| 'token.running'
| 'authentication.signedIn.refreshTimer.stopped'
| 'authentication.signedOut'
| 'authentication.signedOut.failed'
| 'authentication.signedOut.needsMfa'
| 'authentication.signedOut.needsSmsOtp'
| 'authentication.signedOut.noErrors'
| 'authentication.signedOut.signingOut'
| 'authentication.signedOut.success'
| 'authentication.starting'
| 'registration'
| 'registration.complete'
| 'registration.emailPassword'
| 'registration.incomplete'
| 'registration.incomplete.noErrors'
| 'registration.incomplete.failed'
| 'registration.incomplete.needsEmailVerification'
| 'registration.incomplete.needsOtp'
| 'registration.incomplete.failed'
| 'registration.emailPassword'
| 'registration.incomplete.noErrors'
| 'registration.passwordlessEmail'
| 'registration.passwordlessSms'
| 'registration.passwordlessSmsOtp'
| 'registration.complete'
| 'registration.securityKey'
| 'token'
| 'token.idle'
| 'token.idle.error'
| 'token.idle.noErrors'
| 'token.running'
| {
authentication?:
| 'starting'
| 'signedOut'
| 'authenticating'
| 'signedIn'
| 'signedOut'
| 'starting'
| {
signedOut?:
| 'noErrors'
| 'success'
| 'needsSmsOtp'
| 'needsMfa'
| 'failed'
| 'signingOut'
authenticating?:
| 'password'
| 'anonymous'
| 'mfa'
| 'password'
| 'securityKeyEmail'
| { mfa?: 'totp' }
signedIn?:
@@ -315,21 +368,29 @@ export interface Typegen0 {
| {
refreshTimer?:
| 'disabled'
| 'stopped'
| 'idle'
| 'running'
| 'stopped'
| { running?: 'pending' | 'refreshing' }
}
signedOut?:
| 'failed'
| 'needsMfa'
| 'needsSmsOtp'
| 'noErrors'
| 'signingOut'
| 'success'
}
token?: 'idle' | 'running' | { idle?: 'noErrors' | 'error' }
registration?:
| 'incomplete'
| 'complete'
| 'emailPassword'
| 'incomplete'
| 'passwordlessEmail'
| 'passwordlessSms'
| 'passwordlessSmsOtp'
| 'complete'
| { incomplete?: 'noErrors' | 'needsEmailVerification' | 'needsOtp' | 'failed' }
| 'securityKey'
| { incomplete?: 'failed' | 'needsEmailVerification' | 'needsOtp' | 'noErrors' }
token?: 'idle' | 'running' | { idle?: 'error' | 'noErrors' }
}
tags: 'loading'
}

View File

@@ -7,10 +7,11 @@ export * from './sendVerificationEmail'
export * from './signInAnonymous'
export * from './signInEmailPassword'
export * from './signInEmailPasswordless'
export * from './signInEmailSecurityKey'
export * from './signInMfaTotp'
export * from './signInSecurityKeyEmail'
export * from './signInSmsPasswordless'
export * from './signInSmsPasswordlessOtp'
export * from './signOut'
export * from './signUpEmailPassword'
export * from './signUpEmailSecurityKey'
export * from './types'

View File

@@ -15,7 +15,7 @@ export interface SignInSecurityKeyPasswordlessState
extends SignInSecurityKeyPasswordlessHandlerResult,
ActionLoadingState {}
export const signInSecurityKeyEmailPromise = (interpreter: AuthInterpreter, email: string) =>
export const signInEmailSecurityKeyPromise = (interpreter: AuthInterpreter, email: string) =>
new Promise<SignInSecurityKeyPasswordlessHandlerResult>((resolve) => {
const { changed, context } = interpreter.send({ type: 'SIGNIN_SECURITY_KEY_EMAIL', email })
if (!changed) {

View File

@@ -0,0 +1,73 @@
import { USER_ALREADY_SIGNED_IN } from '../errors'
import { AuthInterpreter, SignUpSecurityKeyOptions } from '../types'
import {
ActionLoadingState,
NeedsEmailVerificationState,
SessionActionHandlerResult
} from './types'
export interface SignUpSecurityKeyHandlerResult
extends SessionActionHandlerResult,
NeedsEmailVerificationState {}
export interface SignUpSecurityKeyState
extends SignUpSecurityKeyHandlerResult,
ActionLoadingState {}
export const signUpEmailSecurityKeyPromise = (
interpreter: AuthInterpreter,
email: string,
options?: SignUpSecurityKeyOptions
): Promise<SignUpSecurityKeyHandlerResult> =>
new Promise<SignUpSecurityKeyHandlerResult>((resolve) => {
const { changed, context } = interpreter.send('SIGNUP_SECURITY_KEY', {
email,
options
})
if (!changed) {
return resolve({
error: USER_ALREADY_SIGNED_IN,
accessToken: context.accessToken.value,
isError: true,
isSuccess: false,
needsEmailVerification: false,
user: context.user
})
}
interpreter.onTransition((state) => {
if (state.matches('registration.incomplete.failed')) {
resolve({
accessToken: null,
error: state.context.errors.registration || null,
isError: true,
isSuccess: false,
needsEmailVerification: false,
user: null
})
} else if (
state.matches({
authentication: { signedOut: 'noErrors' },
registration: { incomplete: 'needsEmailVerification' }
})
) {
resolve({
accessToken: null,
error: null,
isError: false,
isSuccess: false,
needsEmailVerification: true,
user: null
})
} else if (state.matches({ authentication: 'signedIn', registration: 'complete' })) {
resolve({
accessToken: state.context.accessToken.value,
error: null,
isError: false,
isSuccess: true,
needsEmailVerification: false,
user: state.context.user
})
}
})
})

View File

@@ -80,6 +80,11 @@ export interface RedirectOption {
export interface PasswordlessOptions extends RegistrationOptions, RedirectOption {}
export interface SignUpOptions extends RegistrationOptions, RedirectOption {}
export interface SignUpSecurityKeyOptions extends SignUpOptions {
/** Optional nickname for the security key */
nickname?: string
}
export interface ChangeEmailOptions extends RedirectOption {}
export interface ResetPasswordOptions extends RedirectOption {}
export interface SendVerificationEmailOptions extends RedirectOption {}

View File

@@ -10,5 +10,6 @@ export * from './resetPasswordHandlers'
export * from './sendVerificationEmailHandlers'
export * from './signOutHandlers'
export * from './signUpHandlers'
export * from './securityKeySignUpHandlers'
export * from './anonymousHandlers'
export * from './securityKeySignInHandlers'

Some files were not shown because too many files have changed in this diff Show More