OAuth is everywhere. The ubiquitous “Login with Facebook, Twitter, Github, etc.” can be seen in almost every web app we come across. Tools like Auth0, Netlify Identity, Firebase and Okta make it pretty simple to add these login buttons to most apps.
But, what if we need some custom functionality for our app these identity tools don’t provide out of the box?
What if we need an third party OAuth provider that they don’t currently support? (Login with friendster anyone?)
Like every answer I will give, you can write a serverless function to handle that!
We’ve previously explored how to building serverless CRUD apps with FaunaDB, and how serverless functions work together with Identity on Netlify, but today we’re going a step further and discuss serverless OAuth flows.
This post will focus on how to use simple serverless functions to handle OAuth login flows for your application. We will be using Intercom in this post, but the same pattern applies to any OAuth provider you might need for your application.
Let’s see how we can use Intercom alongside Netlify Functions to build a “Connect with intercom” button for our application.
All the code used in the post can be found here in the repo.
Without further ado, let’s dive in.
Netlify + Intercom OAuth
Add ‘login with Intercom’ via Netlify Functions & OAuth!
- About the project
- How to install and setup
- Running the project locally
- Deploying
- How it works with Netlify Functions
About the project
This project sets up a “login with Intercom” OAuth flow using Netlify Functions.
Here is a quick demo of the login flow, and the OAuth Access data you get back:
You can leverage this project to wire up Intercom (or other OAuth providers) login with your application.
TLDR; Watch the 11 minute video explaining everything
Let’s get started with how to get setup with the repo and with Intercom.
How to install and setup
-
Clone down the repository
git clone git@github.com:DavidWells/intercom-netlify-oauth.git
-
Install the dependencies
npm install
-
Create an Intercom OAuth app
Lets go ahead and setup the Intercom app we will need!
Create an Intercom OAuth app here
You need to enable a ‘test’ app in your account. It’s a tricky to find but you can create a TEST app in your Intercom account under
Settings > General
https://app.intercom.com/a/apps/your-app-id/settings/general
After enabling the test app, you can find it listed in your intercom developer portal.
We now need to configure the test app.
Input the live “WEBSITE URL” and “REDIRECT URLS” in the app edit screen.
You will want to have your live Netlify site URL and
localhost:3000
setup to handle the redirects for local development.If you haven’t deployed to Netlify yet, just insert a placeholder URL like
http://my-temp-site.com
but remember to change this once your Netlify site is live with the correct URLOur demo app has these
REDIRECT URLS
values that are comma separatedhttps://intercom-login-example.netlify.com/.netlify/functions/auth-callback, http://localhost:3000/.netlify/functions/auth-callback
Great we are all configured over here.
-
Grab your the required config values
We need our Intercom app values to configure our function environment variables.
Navigate back to the main OAuth screen and grab the App ID, Client ID, and Client Secret values. We will need these to run the app locally and when deploying to Netlify.
Running the project locally
Because we are using netlify-lambda
to build & serve functions locally, we can work on this project without needing to redeploy to reflect changes!
We need to set an Intercom app id and OAuth client id + secret in your terminal environment for the functions to connect to your Intercom app.
After creating and configuring your Intercom OAuth app, it’s time to plugin the required environment variables into your local terminal session.
On linux/MacOS, run the following command in your terminal:
export INTERCOM_APP_ID=INTERCOM_APP_ID
export INTERCOM_CLIENT_ID=INTERCOM_CLIENT_ID
export INTERCOM_CLIENT_SECRET=INTERCOM_CLIENT_SECRET
If you are on a window machine, set the environment variable like so:
set INTERCOM_APP_ID=INTERCOM_APP_ID
set INTERCOM_CLIENT_ID=INTERCOM_CLIENT_ID
set INTERCOM_CLIENT_SECRET=INTERCOM_CLIENT_SECRET
Then run the start command
npm start
This will boot up our serverless functions to run locally for development. You can now login via your Intercom application and see the token data returned.
Making edits to the functions in the /functions
will hot reload the server and you can iterate on building your custom logic.
Deploying
Use the one click “deploy to Netlify” button to launch this!
Alternatively, you can connect this repo with your Netlify account and add in your values.
In https://app.netlify.com/sites/YOUR-SITE-SLUG/settings/deploys
add the INTERCOM_APP_ID
, INTERCOM_CLIENT_ID
, and INTERCOM_CLIENT_SECRET
values to the “Build environment variables” section of settings
After your site is deployed, you should be able to test your Intercom login flow.
How it works with Netlify Functions
Once again, serverless functions come to the rescue!
We will be using 2 functions to handle the entire OAuth flow with Intercom.
Here is a diagram of what is happening:
- First the
auth.js
function is triggered & redirects the user to Intercom - The user logs in via Intercom and is redirected back to
auth-callback.js
function with an auth grant code auth-callback.js
takes the auth grant code and calls back into Intercom’s API to exchange it for an AccessTokenauth-callback.js
now has the AccessToken to make any API calls it would like back into the Intercom App.
This flow uses the Authorization Code Grant flow. For more information on OAuth 2.0, Watch this video
Let’s dive into the individual functions and how they work.
auth.js function
The auth.js
function creates an authorizationURI
using the simple-oauth2
npm module and redirects the user to the Intercom login screen.
Inside of the auth.js
function, we set the header.Location
in the lambda response and that will redirect the user to the authorizationURI
, a.k.a the Intercom oauth login screen.
/* code from /functions/auth.js */
import oauth2, { config } from './utils/oauth'
/* Do initial auth redirect */
exports.handler = (event, context, callback) => {
/* Generate authorizationURI */
const authorizationURI = oauth2.authorizationCode.authorizeURL({
redirect_uri: config.redirect_uri,
/* Specify how your app needs to access the user’s account. http://bit.ly/intercom-scopes */
scope: '',
/* State helps mitigate CSRF attacks & Restore the previous state of your app */
state: '',
})
/* Redirect user to authorizationURI */
const response = {
statusCode: 302,
headers: {
Location: authorizationURI,
'Cache-Control': 'no-cache' // Disable caching of this response
},
body: '' // return body for local dev
}
return callback(null, response)
}
auth-callback.js function
The auth-callback.js
function handles the authorization grant code returned from the successful Intercom login.
It then calls oauth2.authorizationCode.getToken
to get a valid accessToken
from Intercom.
Once you have the valid accessToken, you can store it and make authenticated calls on behalf of the user to the Intercom API.
/* code from /functions/auth-callback.js */
import getUserData from './utils/getUserData'
import oauth2, { config } from './utils/oauth'
/* Function to handle intercom auth callback */
exports.handler = (event, context, callback) => {
const code = event.queryStringParameters.code
/* state helps mitigate CSRF attacks & Restore the previous state of your app */
const state = event.queryStringParameters.state
/* Take the grant code and exchange for an accessToken */
oauth2.authorizationCode.getToken({
code: code,
redirect_uri: config.redirect_uri,
client_id: config.clientId,
client_secret: config.clientSecret
})
.then((result) => {
const token = oauth2.accessToken.create(result)
console.log('accessToken', token)
return token
})
// Get more info about intercom user
.then(getUserData)
// Do stuff with user data & token
.then((result) => {
console.log('auth token', result.token)
// Do stuff with user data
console.log('user data', result.data)
// Do other custom stuff
console.log('state', state)
// return results to browser
return callback(null, {
statusCode: 200,
body: JSON.stringify(result)
})
})
.catch((error) => {
console.log('Access Token Error', error.message)
console.log(error)
return callback(null, {
statusCode: error.statusCode || 500,
body: JSON.stringify({
error: error.message,
})
})
})
}
Using two simple serverless Lambda functions, we can now handle logins via Intercom or any other third party OAuth provider.
That’s pretty nifty!
Wrapping Up
This pattern can be used to connect with any number of third party OAuth providers that you might need for your next application.
We hope you give Netlify Functions a spin and see all the cool things you can build.