Skip to content

GitHub ​

To set up GitHub OAuth for your app, you'll need to get your clientId and clientSecret credentials from GitHub. See Creating an OAuth App for instructions.

Configuration ​

Add your GitHub provider in config/wish.js:

js
// config/wish.js
module.exports.wish = {
  provider: 'github',
  providers: {
    github: {
      clientId: 'your-client-id',
      clientSecret: 'your-client-secret',
      redirect: 'http://localhost:1337/auth/callback'
    }
  }
}

Or use environment variables (Wish automatically detects these):

VariableDescription
GITHUB_CLIENT_IDYour GitHub OAuth App Client ID
GITHUB_CLIENT_SECRETYour GitHub OAuth App Client Secret
GITHUB_CALLBACK_URLThe callback URL registered with GitHub
js
// config/wish.js - credentials loaded from env vars
module.exports.wish = {
  provider: 'github',
  providers: {
    github: {}
  }
}

Customizing Scopes ​

To request additional permissions from GitHub:

js
// config/wish.js
module.exports.wish = {
  provider: 'github',
  providers: {
    github: {
      scopes: ['user:email', 'read:user', 'repo']
    }
  }
}

See GitHub OAuth Scopes for available scopes.

Defaults ​

Wish provides these defaults for GitHub (override only what you need):

OptionDefault
scopes['user:email']
scopeSeparator,
tokenUrlhttps://github.com/login/oauth/access_token
userUrlhttps://api.github.com/user

The Redirect ​

A typical flow is to have a button on your website like "Sign in with GitHub". A good example can be found here.

Clicking that button should call a redirect route you've set in routes.js:

js
'GET /auth/redirect': 'auth/redirect',

Now let's author this auth/redirect action:

js
module.exports = {
  friendlyName: 'Redirect',

  description: 'Redirect auth.',

  inputs: {},

  exits: {
    success: {
      responseType: 'redirect'
    }
  },

  fn: async function () {
    return sails.wish.redirect()
  }
}

INFO

Notice the redirect is a one-line of code and when this action is called, it will redirect to GitHub to begin the OAuth process.

The Callback ​

Note the callback URL we set above that Wish will callback? Let's also implement that starting from the route in routes.js:

js
'GET /auth/callback': 'auth/callback',
js
module.exports = {
  friendlyName: 'Callback',

  description: 'Callback auth.',

  inputs: {
    code: {
      type: 'string',
      required: true
    }
  },

  exits: {
    success: {
      responseType: 'redirect'
    }
  },

  fn: async function ({ code }, exits) {
    const req = this.req

    // Get the GitHub user info
    const githubUser = await sails.wish.user(code)

    User.findOrCreate(
      { githubId: githubUser.id },
      {
        id: sails.helpers.getUuid(),
        githubId: githubUser.id,
        email: githubUser.email,
        name: githubUser.name,
        githubAvatarUrl: githubUser.avatar_url,
        githubAccessToken: githubUser.accessToken
      }
    ).exec(async (error, user, wasCreated) => {
      if (error) throw error

      // Checks if the user email has changed since last log in
      if (!wasCreated && user.email !== githubUser.email) {
        await User.updateOne({ id: user.id }).set({
          emailChangeCandidate: githubUser.email
        })
      }

      // Checks if the user name has changed since last log in
      if (!wasCreated && user.name !== githubUser.name) {
        await User.updateOne({ id: user.id }).set({
          name: githubUser.name
        })
      }

      if (!wasCreated && user.githubAvatarUrl !== githubUser.avatar_url) {
        await User.updateOne({ id: user.id }).set({
          githubAvatarUrl: githubUser.avatar_url
        })
      }

      if (!wasCreated && user.githubAccessToken !== githubUser.accessToken) {
        await User.updateOne({ id: user.id }).set({
          githubAccessToken: githubUser.accessToken
        })
      }

      // Modify the active session instance.
      req.session.userId = user.id
      return exits.success('/')
    })
  }
}

The above is an actual real world use case of Wish in https://sailscasts.com. You can perform any business logic you want.

There you have it, a GitHub OAuth flow with just two routes!

All open source projects are released under the MIT License.