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

2.0.3 • Public • Published

This package has moved to @taylorgrinn/auth-server

Tygr Auth Server Middleware

This is an express middleware and router to be used with the @tygr/auth react component.

Installation

npm i --save @tygr/auth-server
yarn add @tygr/auth-server

Add the middleware and router to your app

import bodyParser from 'body-parser';
import express from 'express';
import useAuth from '@tygr/auth-server';

const [authMiddleware, authRouter] = useAuth({
  // Provide a secret key or list of keys to use for creating sessions.
  secret: 'ssshhh',
  // In order to implement the reset password form, use this option to send
  // an email using nodemailer or another email solution. Must return a promise
  async sendCode(email, code) {
    console.log(`Emailing code: ${code} to ${email}`);
    /* Implementation not shown */
  },
  delay: 1000, // Add an optional delay to all authentication requests. Useful for preventing brute force attacks from a single IP or just letting users appreciate your loading screens.
});

const app = express();
export default app;

app.use(
  bodyParser.json(), // JSON necessary to parse requests from the @tygr/auth react component
  authMiddleware
);

app.use('/auth', authRouter);

This is all the setup you need for a minimal working example with local login, register, and reset password functionality.

Setup the external providers (Google, Github, Facebook)

Create API keys for each or any of the services:

Add the keys, as well as the external location of your authentication server, to the useAuth options:

const [authMiddleware, authRouter] = useAuth({
  ...,
  authBaseUrl: 'https://tygr.info/api/auth', // Used for callbacks after authentication
  google: {
    clientId: 'blahblahblah',
    clientSecret: 'blahblahblah',
    scope: [], // Optional: scopes allow you to get more user information
  },
  github: {
    clientId: 'blahblahblah',
    clientSecret: 'blahblahblah',
    scope: [], // Optional: scopes allow you to get more user information
  },
  facebook: {
    clientId: 'blahblahblah',
    clientSecret: 'blahblahblah',
    scope: [], // Optional: scopes allow you to get more user information
    profileFields: [] // Optional: profile fields need to be specified for user object
  }
});

...

/**
 * Make sure to include the pathname you decide to use here ('/auth')
 * in the `authBaseUrl` option above.
 */
app.use('/auth', authRouter)

For the scope options, the email scope is already included in all authentication requests by default for both github and google.

When creating the keys for each provider, you'll also have to specify the callback urls in this format:

  • Google: `${authBaseUrl}/google/callback`
  • Github: `${authBaseUrl}/github/callback`
  • Facebook: `${authBaseUrl}/facebook/callback`

Setup better storage options

By default, the sessions and user data are stored in-memory. This is volatile and not recommended for production use. You may pass in a store for the sessions and a Users model for storing users.

The store interface is described here in the express-session library.

The Users interface defines what will probably be static methods on your Users' model class. I designed it specifically to work with sequelize right out of the gate, but it can be adapted for any storage mechanism you'd like. There are five methods to implement and four required fields on the User object.


BaseUser (You may add any other properties you'd like)

property type description
id string Unique identifier generated by uuid. This should be the 'primary key'
email string Unique email address for each user.
password string (or undefined) Hashed password for the user if they signed in locally
provider string The authentication method (either 'local', 'google', or 'github')

BaseUsers

method param returns description
create User Promise<User> Create a new user. No need to check if the user already exists. For sequelize, no setup is necessary as the base model includes this method with the correct signature, given that the model extends the BaseUser interface correctly
findByEmail string Promise<User | null> Find a user account by an email address
findAndUpdate User Promise<any> Find a user using the id, which will not change, and update the rest of the user properties
findAndDestroy User Promise<any> Find a user using either the id or email then delete them
sanitize User Partial<User> Synchronously create a user object that is safe to be sent back to the user. The password hash should be removed at least

All Options

Order of precedence: env var > option > default
Array environment variables are comma separated: MY_VAR=thing1,thing2

option required env var type description
secret required AUTH_SECRET string | string[] Provide a secret key or list of keys to use for creating sessions
sendCode required (emailAddress: string, code: string) => Promise<any> Send a reset code to a specified email address. The user can then copy this code into the reset password form to recover access to their account
store recommended See here Provide a store to use for session data. Defaults to an in memory store which is not recommended for a production environment
Users recommended See above Provide a Users model to store user data. Defaults to an in memory Users model which is not recommended for a production environment
delay optional AUTH_DELAY number Milliseconds to delay each request to the auth server.
cors optional CORS boolean (string[] if using env var) Set the cookie properties: sameSite: true, secure: true. This will allow cookies to be loaded from any domain and requires the authentication server to be served over https. See the demo folder for an example of serving https://localhost using custom certificates. See below for more info
httpOnly optional HTTP_ONLY boolean Whether the cookie willl have the httpOnly flag. True, by default.
authBaseUrl optional AUTH_BASE_URL string The external address of your authentication server. This option is required for an identity provider like google or github to redirect users back after signing in but not for local sign in, register or reset password
google.clientID required for google GOOGLE_CLIENT_ID string Client ID given by Google.
google.clientSecret required for google GOOGLE_CLIENT_SECRET string Client secret given by Google.
google.scope optional GOOGLE_SCOPE string[] Scope of information or abilities to be requested by you to the user for their Google account. The 'email' scope is added to all requests in addition to any you specify here
github.clientID required for github GITHUB_CLIENT_ID string Client ID given by Github.
github.clientSecret required for github GITHUB_CLIENT_SECRET string Client secret given by Github.
github.scope optional GITHUB_SCOPE string[] Scope of information or abilities to be requested by you to the user for their Github account. The 'user:email' scope is added to all requests in addition to any you specify here
facebook.clientID required for facebook FACEBOOK_CLIENT_ID string Client ID given by Facebook.
facebook.clientSecret required for facebook FACEBOOK_CLIENT_SECRET string Client secret given by Facebook.
facebook.scope optional FACEBOOK_SCOPE string[] Scope of information or abilities to be requested by you to the user for their Facebook account. The 'email' scope is added to all requests in addition to any you specify here
facebook.profileFields optional FACEBOOK_PROFILE_FIELDS string[] Profile fields to include when authenticating. The 'email' field is added to all requests in addition to any you specify here

Setup cors for cross-domain authentication

If your authentication server is on a different domain than your client, or you have multiple clients logging in to the same authentication server, you can use the cors middleware and the cors option:

import useAuth, { cors } from '@tygr/auth-server';


const [authMiddleware, authRouter] = useAuth({
  ...,
  cors: true,
});

app.use(cors('https://tygr.info', 'http://localhost:8081'));

The cors middleware takes in any number of whitelisted domains and adds the relevant headers to all requests from each of them.

The cors option changes the way cookies are set. Specifically, it makes them available on any domain and makes them secure, only available when the authentication server is served over https. Check out the demo folder to see an example of serving https://localhost with a self-signed certificate.

If the CORS environment variable is set, the cors options will be set to true and the whitelist will be set to the comma-separated list value of the CORS environment variable:

# .env file (or however you set env vars)
CORS=https://tygr.info,http://localhost:8081
/**
 * You still have to use the cors middleware but the whitelist
 * will be supplied by the environment variable
 */
app.use(cors());

Readme

Keywords

Package Sidebar

Install

npm i @tygr/auth-server

Weekly Downloads

0

Version

2.0.3

License

ISC

Unpacked Size

44 kB

Total Files

30

Last publish

Collaborators

  • tygrinn
  • jg83