Git Product home page Git Product logo

hasura-auth's Introduction

Hasura Auth

Authentication for Hasura

license: MIT commitizen: friendly code style: prettier

Core Features

  • ๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ Users are stored in Postgres and accessed via GraphQL
  • ๐Ÿ”‘ Multiple sign-in methods.
  • โœจ Integrates with GraphQL and Hasura Permissions
  • ๐Ÿ” JWT tokens and Refresh Tokens.
  • โœ‰๏ธ Emails sent on various operations
  • โœ… Optional checking for Pwned Passwords.

Sign in methods

  • Email and Password - simple email and password method.
  • Email - also called passwordless email or magic link.
  • SMS - also called passwordless sms.
  • Anonymous - sign in users without any method. Anonymous users can be converted to regular users.
  • OAuth providers: Facebook, Google, GitHub, Twitter, Apple, Azure AD, LinkedIn, Windows Live, Spotify, Strava, GitLab, BitBucket, Discord, WorkOS.
  • Security keys with WebAuthn

Deploy Hasura Auth in Seconds

Use Nhost to start using Hasura Auth in seconds.

Using Docker-compose

git clone https://github.com/nhost/hasura-auth.git
cd hasura-auth
cp .env.example .env
docker-compose -f docker-compose-example.yaml up

Configuration

Read our configuration guide to customise the Hasura Auth settings.

Workflows

Recipes

Reference

๐Ÿค Contributing

Contributions and issues are welcome. Please have a look at the developer's guide if you want to prepare a pull request.

Feel free to check the issues page.

Show your support

Give a โญ๏ธ if this project helped you!

๐Ÿ“ License

This project is MIT licensed.

hasura-auth's People

Contributors

alveshelio avatar anjerodev avatar apperside avatar azlekov avatar blib avatar dbarrosop avatar dependabot[bot] avatar elephant3 avatar elitan avatar erwinpetit avatar fmanzali avatar github-actions[bot] avatar iangabrielsanchez avatar jdahlborg avatar juicygoose avatar komninoschatzipapas avatar kwiky avatar linden avatar mmmmillar avatar nbourdin avatar niieani avatar nunopato avatar ofux avatar onehassan avatar plmercereau avatar quentin-decre avatar suplere avatar svarto avatar szilarddoro avatar totzk9 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

hasura-auth's Issues

container fails to start due to failed migrations called

Hi
I installed the latest hasura-auth docker image and I am getting the following error when it starts:

2021-11-18T17:36:13.215063196Z yarn run v1.22.15 2021-11-18T17:36:13.310451921Z $ node -r ./dist/start.js 2021-11-18T17:36:16.010300921Z {"level":30,"time":1637256976007,"pid":29,"hostname":"f89ed166a3bd","msg":"Hasura is ready"} 2021-11-18T17:36:16.090766635Z (node:29) UnhandledPromiseRejectionWarning: Error: Migration failed. Reason: An error occurred running 'create-initial-tables'. Rolled back this migration. No further migrations were run. Reason: function "set_current_timestamp_updated_at" already exists with same argument types 2021-11-18T17:36:16.090800706Z at /app/node_modules/@djgrant/postgres-migrations/dist/migrate.js:63:27 2021-11-18T17:36:16.090806676Z at processTicksAndRejections (internal/process/task_queues.js:95:5) 2021-11-18T17:36:16.090811016Z at async /app/node_modules/@djgrant/postgres-migrations/dist/with-lock.js:24:28 2021-11-18T17:36:16.090815196Z at async Object.applyMigrations (/app/dist/migrations.js:16:9) 2021-11-18T17:36:16.090819126Z at async start (/app/dist/ts-start.js:42:5) 2021-11-18T17:36:16.090822686Z (Use node --trace-warnings ...to show where the warning was created) 2021-11-18T17:36:16.090826926Z (node:29) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag--unhandled-rejections=strict(see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1) 2021-11-18T17:36:16.090833916Z (node:29) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. 2021-11-18T17:36:16.136545350Z Done in 2.93s.
this keeps going on and on in a restart loop.

I have also set the following env variables:

HASURA_GRAPHQL_DATABASE_URL=postgres://ourPGDB
HASURA_GRAPHQL_JWT_SECRET={ "type": "HS256", "key": "ourkey"}
HASURA_GRAPHQL_ADMIN_SECRET=oursecret
HASURA_GRAPHQL_GRAPHQL_URL=http://srv-captain--hasura-graphql-engine:8080/v1/graphql

(the hasura installation itself works fine, so the details above are correct)

I had installed the migrations SQL manually before (so all the tables in auth are already there), but I would expect the script to notice that and move on.

Improve Signup Error interface

Currently when a user tries to signup and gets an error, the Error signature isn't very helpful.
This is the error type signature

interface Error {
    name: string;
    message: string;
    stack?: string;
}

It's hard to handle different cases and let the user know what was exactly the error. For example if we receive a 409 it means the email is already in use, if we get 401 it means password and email doesn't match, if we receive a 500 it means there was an error with the server but in all these cases the Error doesn't provide much help since the error is embedded in the message and it's hard to extract the error code from the message because if the message changes it's format we'll never know.
It would very helpful if it Error could return the error code so we can handle these errors appropriately.

The new Error signature could be

interface Error {
    name: string;
    code: 401 | 409 | 500 // any other error that can be handled
    message: string;
    stack?: string;
}

Accept `pathNames` as valid redirectTo in addition to full URLs

Looking at isValidRedirectTo it only returns true if redirectTo starts with ENV.AUTH_CLIENT_URL (http://localhost:3000)
I'm wondering if we couldn't have a helper to create the redirectTo

Right now if we want to send a redirect URL, we need to provide a full URL (http://localhost:300/my-custom-url). However I'm wondering if we couldn't simplify things a bit for the user.

In my case I'd like to redirect the user to translated URL, so if I'm in fr-ca I'd send the user to http://localhost:300/fr-ca/mon-url-personalise, otherwise I'd send the user to http://localhost:300/en-ca/my-custom-url. However, in order for this to work in dev or prod I'd probably have an environment variable that I'd have to set both in local and in prod, something like WEBSITE_URL=http://localhost:3000 and then build the url as follow ${process.env.WEBSITE_URL}/en-ca/my-custom-url.

So what we could allow the user to do is either send a full url or only a portion of the url and we could have a helper function sanitizeRedirectTo (I'm sure there's a better name for it) where it would take redirectTo and would check if it would NOT start with either http or https and would start with /, then we would go ahead and build the url for the user like so ${ENV.AUTH_CLIENT_URL}${ENV.AUTH_CLIENT_URL} then we would check if starts with ENV.AUTH_CLIENT_URL.

What do you guys thing about this?

I would gladly create a PR for this :)

Locale default value not set on registration

{"type":"http-log","timestamp":"2021-06-23T15:29:28.372+0000","level":"error","detail":{"operation":{"user_vars":{"x-hasura-role":"admin"},"error":{"path":"$.selectionSet.insert_auth_accounts.args.objects[0]","error":"Not-NULL violation. null value in column \"locale\" violates not-null constraint","code":"constraint-violation"},"request_id":"c14293f7-b574-4105-a87b-a267429dace0","response_size":183,"query":{"variables":{"account":{"email":"[email protected]","account_roles":{"data":[{"role":"user"}]},"user":{"data":{"display_name":"[email protected]"}},"ticket":"05517e44-e7ea-4c36-bd5d-3f343e5bd264","active":true,"password_hash":"$2a$10$TvirZTMEAzc6L2T.Gi8EXOLI35K4M0kk8Fhv3jCJO7gwXfxRR9iTq","default_role":"user","ticket_expires_at":"2021-06-23T16:29:28.393Z"}},"query":"mutation ($account: auth_accounts_insert_input!) {\n  insert_auth_accounts(objects: [$account]) {\n    affected_rows\n    returning {\n      ...accountFragment\n    }\n  }\n}\n\nfragment accountFragment on auth_accounts {\n  id\n  active\n  default_role\n  account_roles {\n    role\n  }\n  user {\n    id\n    display_name\n  }\n  is_anonymous\n  ticket\n  email\n  new_email\n  otp_secret\n  mfa_enabled\n  password_hash\n}\n"}},"request_id":"c14293f7-b574-4105-a87b-a267429dace0","http_info":{"status":200,"http_version":"HTTP/1.1","url":"/v1/graphql","ip":"172.27.0.2","method":"POST","content_encoding":null}}}

The `/email-templates` endpoint is not reliable with on a stateless container

This endpoint allows admin users to modify email templates files in the backend. However, these changes will be only stored in a container, which should be stateless.
As a result, it will create inconsistencies when scaling up horizontally. Also, changes would be lost when restarting/replacing the container.
We should come up with a better alternative, maybe in implementing the logic of the AUTH_EMAIL_TEMPLATE_FETCH_URL ghost environment variable

Docs needed for deployed app with magic links auth

For Nhost Auth.

In nhost/config.yaml on a nhost cli BE setup.

  • what's client_url and allowed_redirect_urls? Is allowed_redirect_urls expecting a comma separated values (strings)?

Search in source code is disconnected on hasura backend plus vs hasura-auth repos, and there's no website docs for these. When deployed apps need magic link to hit and redirect not on localhost.

Deploying FE on Vercel and BE on nhost.io

limit passwordless authentication to existing and active users

For the moment, when passwordless is enabled, any user with a valid email address can register and login, even when the user has been disabled.

In some cases we may want to block new users registering and to let the admin create new users.

To do so, we could change the behaviour in checking if AUTH_EMAIL_SIGNIN_EMAIL_VERIFIED_REQUIRED is set to false before registering a user.

This also should be analysed more thoroughly as passwordless also works with SMS.

last seen

update last seen timestamp for the user every time the user signs in or refresh token.

Error message for body validation

If I log in with:

{
    "email": "[email protected]",
    "password": "hejsan",
    "cookie": false
}

I get:

Error validating request body. "value" does not match any of the allowed types.

I would expect to get an error message like "cookie not allowed as a property or something".

"null" value in custom claims when AUTH_JWT_CUSTOM_CLAIMS cannot generate a value

When for a given user some claim cannot be calculated for the AUTH_JWT_CUSTOM_CLAIMS hasura-auth generates "null" string value for that claim, for example:

{
  "https://hasura.io/jwt/claims": {
    "x-hasura-service-account-id": "1",
    "x-hasura-organization-id": "null",
    "x-hasura-allowed-roles": [
      "user",
      "me",
      "accountadmin"
    ],
    "x-hasura-default-role": "accountadmin",
    "x-hasura-user-id": "9b0ac75f-8d35-4a81-a3c2-1fc70a030dcc",
    "x-hasura-user-isAnonymous": "false"
  },
  "sub": "9b0ac75f-8d35-4a81-a3c2-1fc70a030dcc",
  "iss": "hasura-auth",
  "iat": 1645271890,
  "exp": 1645272790
}

In this case we have "x-hasura-organization-id": "null", because the user trying to log in is not associated with an organization.

It may be better to leave out custom claim fields from the JWT, which result in "null" value, otherwise a Hasura permission rule may use this "null" value and accidently it may have a match, when it actually should not. Not in case of a numeric ID, but let say for a username field, which could have the valid value "null".

Allow locale with country in locale in users table

Right now, the users table has a column locale which unfortunately only accepts the locale and not the locale plus country. Working with internationalization means that we need to take into account not only the locale but also the country since there's a lot of information that depends on the country.

We should be able to enter en-ca, fr-ca, pt-pt, pt-br, etc

Development documentation

It would be great to have some a documentation about how to do development on nhost-auth so that we could submit PR-s. I just tried

yarn dev

but it failed with

[0] Service 'hasura-auth' failed to build : COPY failed: Forbidden path outside the build context: ../../ ()
error Command failed with exit code 1.

because of this line in docker/dev/Dockerfile

COPY ../../ .

What is the intended way to run nhost-auth for development?

How to handle invalid or expired tickets

Hi,

Right now when we send an email validation on sign up, we can specify an redirectTo, however, this only works if the ticket is valid. If the ticket is not valid or has expired then the user stays in this URL
https://my-backend-url.nhost.run/v1/auth/verify?&ticket=verifyEmail:ticket-id&type=emailVerify&redirectTo=my-front-end-url
And it simply display a JSON object {"statusCode":401,"error":"Unauthorized","message":"Invalid or expired ticket"}. This isn't a very nice user experience and there isn't much we can do about at this point.

It would be nice to either always redirect the user to the redirectTo URL with the response and in our side we'd handle the response or have a redirectToSuccess and a redirectToFailure and redirect the user to either redirectTo/Success/Failure and we could decide what to do in each case.

Only use one REDIRECT_URL_* env var

Right now we use both PROVIDER_SUCCESS_REDIRECT and REDIRECT_URL_SUCCESS. We should deprecate PROVIDER_SUCCESS_REDIRECT and only use REDIRECT_URL so we only have to change one variable to handle redirects on HBP

User is deleted if Twilio message fails on sms passwordless login

If Twilio errors when attempt to sign in via sms passwordless, the user will be deleted whether it was newly inserted or not

try {
  await twilioClient.messages.create({
    body: `Your code is ${otp}`,
    messagingServiceSid: ENV.AUTH_SMS_TWILIO_MESSAGING_SERVICE_ID,
    to: phoneNumber,
  });
} catch (error) {
  // delete user that was inserted because we were not able to send the SMS
  await gqlSdk.deleteUser({
    userId,
  });

  return res.boom.internal('Error sending SMS');
}

signUp should return userId, email, etc. when registering user with email verification enabled

Now, when hasura-auth is started from nhost cli with the following config

auth:
  email:
    signin_email_verified_required: true

and trying to register a user using the JS client's signUp() function it returns

{"session": null, "error": null}

It would be good to receive some descriptive data of the newly registered user, at least its userId and email, so that we could make some operations on the new user even if their email address is not yet validated.

For example, I would like to assign some new roles to the new user, which I cannot do at signUp() time (ie. I don't want users to be able to register themselves as "editor" but I would have an "admin" user who can assign an "editor" role to selected newly registered users - I do this on the server side)

'user' and 'me' roles not added when use allowedRoles

Given I have the following set in nhost/config.yaml:

user:
    allowed_roles: user,me,company,freelancer
    default_allowed_roles: user,me,company,freelancer

When I then do a signUp I expect the user and me roles to be added the to user by default even if I did not add them to the allowedRoles option.

nhost.auth.signUp({
  email,
  password,
  options: {
    displayName: name,
    defaultRole: 'freelancer',
    allowedRoles: ['freelancer'],
  },
});

New refresh token expiration approach

Every time a user signs in or refresh their access token (currently happens every 15 minutes) the existing refresh token gets deleted and a new refresh token is saved in the database and returned to the client.

This does not have any clear benefit. Instead it comes with some downsides:

  • Race condition issues (the same refresh token is being used in two browser tabs at the same time to get a new access token)
  • Extra operations on the database.

Instead, I propose that we change this strategy to how Firebase (link) handles refresh tokens:

  • Refresh tokens never expire except if:
  • The user gets deleted
  • The user updates their email
  • The user updates their password

Expose Hasura-auth over GraphQL rather than "REST"

I always wondered why the auth API-s are in REST and not in graphql, but I guess it is for compatibility, broader access and that you didn't want to manage two API-s.

Now as Hasura 2.1 is out and REST Connectors are public it should be fairly easy to provide builtin transformers for the auth API which would also expose it via Hasura:

https://hasura.io/blog/bring-rest-apis-as-a-data-source-to-hasura-announcing-rest-connectors-data-hub/

What do you think?

Start hasura-auth without an external SQL init script

Local docker for auth return below error for initiate migration for first time

yarn run v1.22.17

$ node ./dist/start.js

{"level":30,"time":1643888397013,"pid":28,"hostname":"1265cd3406a3","msg":"Hasura is not ready. Retry in 5 seconds."}

{"level":30,"time":1643888403082,"pid":28,"hostname":"1265cd3406a3","msg":"Hasura is not ready. Retry in 5 seconds."}

{"level":30,"time":1643888411152,"pid":28,"hostname":"1265cd3406a3","msg":"Hasura is not ready. Retry in 5 seconds."}

{"level":30,"time":1643888416174,"pid":28,"hostname":"1265cd3406a3","msg":"Hasura is ready"}

(node:28) UnhandledPromiseRejectionWarning: Error: Migration failed. Reason: An error occurred running 'create-migrations-table'. Rolled back this migration. No further migrations were run. Reason: schema "auth" does not exist

    at /app/node_modules/@djgrant/postgres-migrations/dist/migrate.js:63:27

    at processTicksAndRejections (internal/process/task_queues.js:95:5)

    at async /app/node_modules/@djgrant/postgres-migrations/dist/with-lock.js:24:28

    at async applyMigrations (/app/dist/migrations.js:16:9)

    at async start (/app/dist/server.js:37:5)

(Use `node --trace-warnings ...` to show where the warning was created)

(node:28) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 4)

(node:28) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Done in 20.67s.

Custom JWT Claims

nhost and HBP used to support custom JWT claim, however hasura-auth doesn't support them. As @elitan wrote: "For JWT custom fields, we've temporary dropped support for it in v2 because we don't want users to edit the new auth.users table. Everything in the auth schema is managed by Hasura Auth."

I would like to suggest an alternative solution, which would not require us developers to touch auth.users and would not require hasura-auth to have any knowledge of the developers schema and tables.

I would suggest to have a nhost configuration option, which allows us to define a hasura query for custom claim values. A separate query for each claim. The query should have a single $userId: uuid! parameter and the query result, whatever it is - a single value or a complete json - would be set in the custom claim field.

For example:

auth:
  custom_claims: 
      organization-id: >
        query customClaim($userId: uuid!) {
          profiles(where:{userId:{eq:{$userId}}}) {
            organizationId
          }
        }
      service-account-id: >
        query customClaim($userId: uuid!) {
          profiles(where:{userId:{eq:{$userId}}}) {
            serviceAccountId
          }
        }

This would result in a x-hasura-organization-id: 123 and a x-hasura-service-account-id: 456 custom claim in the JWT.

This solution would not require accessing/modifying auth.user by the developers and hasura-auth should not take care of any specific tables in the public schema: it is the duty of the developer to query and return an appropriate value from its own schema based on a $userId.

auth.resetPassword throws error when providing options

When trying to provide an options object to auth.resetPassword like so:

auth.resetPassword({ 
  email: '[email protected]', 
  option: { redirectTo: 'http://localhost:3000/en-ca/change-password' }
 })

I get a 400 error: Error validating request body. "options" is not allowed.

changePassword accepts params of type ResetPasswordParams

export declare type ResetPasswordParams = {
    email: string;
    options?: {
        redirectTo?: string;
    };
};

Looking at endpoint user/password/reset

router.post(
  '/user/password/reset',
  createValidator().body(userPasswordResetSchema),
  aw(userPasswordResetHandler)
);

userPasswordResetHandler accepts following body

type BodyType = {
  email: string;
  options?: {
    redirectTo?: string;
  };
};

And we can see in the code this: const { email, options } = req.body;

However, it seems that userPasswordResetSchema only accepts the email

export const userPasswordResetSchema = Joi.object({
  email: emailRule.required(),
});

I've created this PR to fix the issue: #51

Allow users to use their own email provider and email templates

Right now Nhost custom email templates isn't ready to go into production, as such and in order to not delay customers who are ready to go into production it would be nice if nhost-auth could provide some mechanism to allow us to handle email ourselves or let Nhost handle it.

Let's take an example here:
If we take a look at the sign up through email/password: https://github.com/nhost/hasura-auth/blob/main/src/routes/signup/email-password.ts
It checks the following

if (
    !ENV.AUTH_DISABLE_NEW_USERS &&
    ENV.AUTH_EMAIL_SIGNIN_EMAIL_VERIFIED_REQUIRED
  )

If it passes, it then sends an email to the user.

It would be nice if we could send an option to these endpoint that would give us a bit more control over email notifications,
For example in this endpoint we could have in an option manageEmail: boolean and if manageEmail is true then it would skip sending the email and instead in

if (!ENV.AUTH_EMAIL_SIGNIN_EMAIL_VERIFIED_REQUIRED) {
    const signInResponse = await getSignInResponse({
      userId: user.id,
      checkMFA: false,
      emailURL: manageEmail ? `${ENV._SITE_URL}/ticket` : null
    });

    // return logged in session because user does not have to verify their email
    // to sign in
    return res.send(signInResponse);
  }

  return res.send({ session: null, mfa: null, emailURL: manageEmail ? `${ENV._SITE_URL}/ticket` : null });
};

With this, we could then retrieve the url with the ticket to embed in our email and we could use our own email templates.

Better handling for email types and templates

I've noticed when creating tests to change the password with ticket or send emails we were using strings to check the type of email.

For people foreign to the project like me it can be a bit confusing.
We can get the email type like so: const emailType = message.Content.Headers['X-Email-Template'][0];
And we assert that the emailType is 'email-confirm-change' but then in the url we have:
/verify?ticket=${uuidv4()}&type=emailConfirmChange&redirectTo=${redirectTo}
and here type is emailConfirmChange.

It would be nice if we could have an interface where we could define the links of types allowed, something like this

enum EmailHandlerTypes {
  EMAIL_CONFIRM_CHANGE_TYPE = 'email-confirm-change',
  EMAIL_VERIFY_TYPE = 'email-verify',
}

enum EmailHandlerTemplates {
  EMAIL_CONFIRM_CHANGE_TEMPLATE = 'emailConfirmChange',
  EMAIL_VERIFY_TEMPLATE = 'emailVerify',
}

enum PasswordHandlerTypes {
  PASSWORD_RESET_TYPE = 'password-reset',
  PASSWORDLESS_TYPE = 'signin-passwordless',
}

enum PasswordHandlerTemplates {
  PASSWORD_RESET_TEMPLATE = 'signinPasswordless',
  PASSWORDLESS_TEMPLATE = 'signinPasswordless',
}

type HandlerType =
  | EmailHandlerTypes.EMAIL_CONFIRM_CHANGE_TYPE
  | EmailHandlerTypes.EMAIL_VERIFY_TYPE
  | PasswordHandlerTypes.PASSWORD_RESET_TYPE
  | PasswordHandlerTypes.PASSWORDLESS_TYPE;

type HandlerTemplates = 
  | EmailHandlerTemplates.EMAIL_CONFIRM_CHANGE_TEMPLATE
  | EmailHandlerTemplates.EMAIL_VERIFY_TEMPLATE
  | PasswordHandlerTemplates.PASSWORDLESS_TEMPLATE
  | PasswordHandlerTemplates.PASSWORD_RESET_TEMPLATE

Then in the verifyHandler function where we check if type is equal a string which is easy to misspell, we could simply use enum.
This would also allows us to use Exhaustiveness checking that would help us prevent bugs whenever a new type is added it would automatically warn us that this new type hasn't been handled.

verify.ts

  const type = req.query.type as HandlerType;
  ...
  function assertNever(value: never): never {
    throw Error(`Unexpected value '${value}'`);
  }

  switch (type) {
    case EmailHandlerTypes.EMAIL_VERIFY_TYPE: {
      ...your code here
      break;
    }
    case EmailHandlerTypes.EMAIL_CONFIRM_CHANGE_TYPE: {
      ...your code here
      break;
    }
    case PasswordHandlerTypes.PASSWORDLESS_TYPE: {
      ...your code here
      break;
    }
    case PasswordHandlerTypes.PASSWORD_RESET_TYPE: {
      ...your code here
      break;
    }
    default: {
      assertNever(type)
    }
  }

This could be used whenever we need to check what's the type or template, and would avoid any misspell mistakes.

Would gladly open a PR for this but would like to have your input first :)

Improve validation

Improve validation by taking the following steps:

  1. Remove the asyncWrapper function and use try-catch blocks on the route code
  2. Remove validation.ts and include the Joi validation objects in the route files
  3. Package often used validation code into middleware(e.g. the code checking the permission_variables)

Test migrations folder

Currently, test migrations are provided as a string to pg
Komninos Screenshot - i0BH0QOB
We need to have a separate migrations folder for tests and load them from there.

cc: @nunopato

Wait for Hasura endpoint to be available?

Since hasura-auth manages its own metadata, we should add retry logic on startup, specifically for tracking metadata.

  • We could have this done with exponential backoff and a timeout (or max number of retries).
  • Wait for hasura (/healthz) to be up-and-running.
  • We wouldn't have to rely on the order in which services get started.

Add metadata column for user

Add general purpose metadata column for users.

Name: metadata
type: JSONB
nullable: Yes

The metadata column should be used during signup to attach custom data to a user.

Add logging

Add logging to the routes code via express-winston.

The following env vars will also be added:

LOGGING_ENABLED=true
# debug, info, warn, error
LOGGING_LEVEL=info

Add redirectTo option

Add redirectTo option that should be used in email and in the /verify route to redirect user to a specific URL.

I think we should add the redirect_to column on the users table.

We must also update:

  • hasura-auth-js to take redirectTo as an optional parameter for some methods

Hasura Console data browser issue with id metadata

We set the id column to id using Hasura metadata here. This has no real impact. The field name will be id with and without the metadata.

There is a bug in the Haura Console with setting the id metadata, effectively making the Hausra Console unable to use with data in these tables.

So I'm thinking we can remove the id metadata for now.

Related issue:

nhost/nhost#121

Verify Password Request

User Story

As a user, when I update sensitive information on my account, I want to enter my password again for extra security.

Description

I'd like to add an endpoint that allows you to send a password and email, or user_id, and return a 200 if that password is correct. This can be used in the front-end for sensitive updates (ex: changing an email, adding a credit card, etc...).

GitHub does this when you make changes to SSH keys as another example.

Codegens

https://www.graphql-code-generator.com/docs/plugins/typescript-graphql-request

import { GraphQLClient } from "graphql-request";
import { getSdk } from "./__generated__/graphql-request";

const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
  headers: {
    "x-hasura-admin-secret": process.env.GRAPHQL_ADMIN_SECRET,
  },
});
export const gqlSDK = getSdk(client);
overwrite: true
schema: "http://localhost:8080/v1/graphql"
headers:
  x-hasura-admin-secret: hello123
documents: "nhost/utils/**/*.graphql"
generates:
  nhost/utils/__generated__/graphql-request.ts:
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-graphql-request"
     // package.json scripts:
    "codegen": "graphql-codegen --config codegen.yaml"

Error reporting in case of wrong AUTH_JWT_CUSTOM_CLAIMS definitions

Now when something is wrong with AUTH_JWT_CUSTOM_CLAIMS definition, eg. when it results in an erroneous Hasura graphql query, /signin/email-password doesn't report an error and simply doesn't generate the claims in the access token.

The only way to figure out what went wrong is to check the logs of the nhost-auth and nhost-hasura containers started by the nhost cli.

Either the authentication methods should return an error in this case or maybe generate an error message into the JWT token itself, since developers would probably check that while developing the custom claim definitions.

Construct email template links in Hasura Auth

Instead of constructing links in the email template like this:

href="${serverUrl}/verify?&ticket=${ticket}&type=emailConfirmChange&redirectTo=${redirectTo}"

We should construct the link in Hasura Auth and then just pass a single link variable for the template to use.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.