Neoclassical Programming Multitude

    This package has been deprecated

    Author message:

    Prisma Auth is now non-Prisma specific! Switch to graphql-authentication with graphql-authentication-prisma.

    @volst/prisma-auth
    TypeScript icon, indicating that this package has built-in type declarations

    0.4.1 • Public • Published

    Prisma Auth

    A very opinionated authorization package for Prisma, a GraphQL database API. It uses old-school email/password authentication.

    Features:

    • Signup with good ol' email/password and confirmation email
    • Login
    • Invite another user (sends email)
    • Password reset
    • Change password of current user
    • Update current user info
    • Support for graphql-shield to deal with permissions

    Motivation

    The examples in the Prisma repo have a very basic example on how to do auth, but after that you’re on your own. You still need to build features like password reset and signup. That’s a lot of boilerplate!

    The intention with this package is to let you write as less authentication-related code as possible, while being flexible enough to support different use cases like open sign up, invitation-only signup, extra fields on the User model etc.

    If this package is too opinionated for you, you could still copy/paste parts of it in your application!

    Install

    Node v8+ should be used. Install with Yarn or npm:

    yarn add @volst/prisma-auth email-templates
    npm i @volst/prisma-auth email-templates
    

    Usage

    Step 1

    In your Prisma datamodel.graphql file, add this User model.

    Step 2

    In your schema.graphql for your own server, add something like the following (you can also import specific endpoints only):

    # import Query.*, Mutation.* from "node_modules/@volst/prisma-auth/schema.graphql"

    Step 3

    In your server we now need to map these types to resolvers and pass in some options. The following example uses graphql-yoga, but it should also work with Apollo Server.

    import { authQueries, authMutations, prismaAuthConfig } from '@volst/prisma-auth';
    import * as Email from 'email-templates';
    
    const resolvers = {
      Query: {
        ...authQueries
      },
      Mutation: {
        ...authMutations
      }
    };
    
    const server = new GraphQLServer({
      typeDefs: './schema.graphql',
      resolvers,
      context: req => ({
        ...req,
        db: new Prisma({...}),
        prismaAuth: prismaAuthConfig({
          // Required, used for signing JWT tokens
          secret: 'wheredidthesodago',
          // Optional, for sending emails with email-templates (https://www.npmjs.com/package/email-templates)
          mailer: new Email(),
          // Optional, the URL to your frontend which is used in emails
          mailAppUrl: 'http://example.com',
        })
      })
    });

    Step 4

    Lastly, if you want to send emails, you should copy the email templates to your own project. Checkout the example email templates.

    Documentation

    GraphQL endpoints

    Mutations:

    • signUpByInvite
    • signup
    • confirmEmail
    • inviteUser
    • login
    • changePassword
    • updateCurrentUser
    • trigerPasswordReset
    • passwordReset

    Queries:

    • currentUser

    For more details take a look at schema.graphql.

    Authentication on endpoints

    On some of your endpoints you might want to require that the user is logged in, or only allow the user to see the data if they have a specific role. A very powerful package exists for this, graphql-shield:

    import { shield, rule } from 'graphql-shield';
    import { isAuthResolver } from '@volst/prisma-auth';
    
    const isAuth = rule()(isAuthResolver);
    
    const permissions = shield({
      Mutation: {
        publish: isAuth
      }
    });
    
    const server = new GraphQLServer({
      typeDefs: './schema.graphql',
      resolvers,
      middlewares: [permissions]
    });

    Take a look at the graphql-shield README to find out more.

    Helper utilities

    Get the current user in a resolver (performs a request to Prisma):

    import { getUser } from '@volst/prisma-auth';
    
    const Mutation = {
      async publish(parent, data, ctx) {
        const user = await getUser(ctx);
        console.log('User', user.email);
      }
    };

    Get only the current user ID in a resolver (without request to Prisma):

    import { getUserId } from '@volst/prisma-auth';
    
    const Mutation = {
      async publish(parent, data, ctx) {
        const userId = await getUser(ctx);
        console.log('User', userId);
      }
    };

    Login and session handling

    JWT tokens are used to handle sessions. In the frontend you can perform a login like this:

    mutation login($email: String!, $password: String!) {
      login(email: $email, password: $password) {
        token
        user {
          # optional
          name
        }
      }
    }

    And then save the token to localStorage. Now you need to send the token with every request. If you are using Apollo, the documentation has a great example on how to do this.

    Adding custom fields to the User type

    If you wish to expose some fields on the User type that are not exposed in our schema.graphql, you can provide your own User. In your own schema.graphql, do something like the following:

    # import Mutation.* from "node_modules/@volst/prisma-auth/schema.graphql"
    
    type Query {
      currentUser: User
    }
    
    type User {
      id: ID!
      email: String!
      name: String!
      inviteAccepted: Boolean!
      emailConfirmed: Boolean!
      deletedAt: DateTime
      lastLogin: DateTime
      joinedAt: DateTime!
      isSuper: Boolean!
      # And finally, our custom field:
      isWillingToDance: Boolean!
    }

    If for example you do not want the joinedAt field to be exposed, you can simply remove it from your schema.

    extend type User would save some copy/pasta here, but unfortunately that doesn't work yet in graphql-js. More info.

    Signup only by invite

    By default everyone can signup for your project. But what if you want to only allow invite by signup? In this case you need to leave out the Mutation.signup import. Example:

    # import Mutation.signupByInvite, Mutation.inviteUser, Mutation.login, Mutation.changePassword, Mutation.updateCurrentUser, Mutation.triggerPasswordReset, Mutation.passwordReset, from "node_modules/@volst/prisma-auth/schema.graphql"

    Making email confirmation required before login

    After a user signups via the signup endpoint, they will get an email with a link in it to confirm their email. Meanwhile they can still login in the app. This is done to not disturb the users flow too much (e.g. services like Twitter do this too). It is left open to the project to block the user after a while. With the fields emailConfirmed and joinedAt on the User you can perhaps display a warning in your frontend or disallow certain features.

    However, you might want to block the user from logging in at all when their email is not yet confirmed. In this case you need to pass this option:

    prismaAuth: prismaAuthConfig({
      requiredConfirmedEmailForLogin: true
    });

    Keywords

    none

    Install

    npm i @volst/prisma-auth

    DownloadsWeekly Downloads

    2

    Version

    0.4.1

    License

    ISC

    Unpacked Size

    57.1 kB

    Total Files

    22

    Last publish

    Collaborators

    • amees_me
    • rutgerschimmel