Back

How to build a public SignRequest integration: Building the Auth Flow

Aug 15, 20248 minute read

Introduction

Hey there, fellow JavaScript enthusiasts! Ready to dive into the world of SignRequest integrations? Today, we're going to tackle one of the most crucial aspects of building a public integration: the authorization flow. Trust me, getting this right is key to creating a secure and user-friendly experience. So, let's roll up our sleeves and get to work!

Prerequisites

Before we jump in, make sure you've got:

  • Your SignRequest API credentials (if you don't have them yet, hop over to the SignRequest developer portal and grab 'em)
  • Node.js installed on your machine
  • Your favorite web framework (we'll be using Express in our examples, but feel free to adapt)

Setting up the project

Let's kick things off by setting up our project:

mkdir signrequest-integration cd signrequest-integration npm init -y npm install express axios dotenv

Create a basic server.js file:

require('dotenv').config(); const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

Understanding OAuth 2.0 flow for SignRequest

SignRequest uses OAuth 2.0 with the authorization code grant type. In a nutshell, it goes like this:

  1. We redirect the user to SignRequest's auth page
  2. User grants permission
  3. SignRequest sends us an authorization code
  4. We exchange that code for an access token
  5. We use the access token to make API requests

Simple, right? Let's implement it!

Implementing the authorization flow

Initiating the auth request

First, let's create a route to start the auth process:

const SIGNREQUEST_AUTH_URL = 'https://signrequest.com/api/v1/oauth2/authorize/'; app.get('/auth', (req, res) => { const authUrl = new URL(SIGNREQUEST_AUTH_URL); authUrl.searchParams.append('client_id', process.env.SIGNREQUEST_CLIENT_ID); authUrl.searchParams.append('redirect_uri', process.env.REDIRECT_URI); authUrl.searchParams.append('response_type', 'code'); res.redirect(authUrl.toString()); });

Handling the callback

Now, let's set up our redirect URI to handle the callback:

app.get('/callback', async (req, res) => { const { code } = req.query; if (!code) { return res.status(400).send('Authorization code missing'); } // We'll exchange the code for a token in the next step });

Exchanging the code for access token

Let's add the token exchange logic to our callback route:

const axios = require('axios'); app.get('/callback', async (req, res) => { const { code } = req.query; if (!code) { return res.status(400).send('Authorization code missing'); } try { const response = await axios.post('https://signrequest.com/api/v1/oauth2/token/', { grant_type: 'authorization_code', code, redirect_uri: process.env.REDIRECT_URI, client_id: process.env.SIGNREQUEST_CLIENT_ID, client_secret: process.env.SIGNREQUEST_CLIENT_SECRET, }); const { access_token, refresh_token } = response.data; // Store these tokens securely (e.g., in a database) // For this example, we'll just send them in the response res.json({ access_token, refresh_token }); } catch (error) { console.error('Error exchanging code for token:', error.response?.data || error.message); res.status(500).send('Error obtaining access token'); } });

Managing token refresh

To keep your integration running smoothly, you'll need to refresh the access token when it expires. Here's a simple function to do that:

async function refreshAccessToken(refresh_token) { try { const response = await axios.post('https://signrequest.com/api/v1/oauth2/token/', { grant_type: 'refresh_token', refresh_token, client_id: process.env.SIGNREQUEST_CLIENT_ID, client_secret: process.env.SIGNREQUEST_CLIENT_SECRET, }); return response.data.access_token; } catch (error) { console.error('Error refreshing token:', error.response?.data || error.message); throw error; } }

Using the access token

Now that we have our access token, we can make authenticated requests to the SignRequest API. Here's an example of how to use it:

async function createSignRequest(access_token, documentData) { try { const response = await axios.post('https://signrequest.com/api/v1/signrequests/', documentData, { headers: { 'Authorization': `Bearer ${access_token}`, 'Content-Type': 'application/json', }, }); return response.data; } catch (error) { console.error('Error creating sign request:', error.response?.data || error.message); throw error; } }

Error handling and edge cases

Always be prepared for things to go wrong. Here are some tips:

  • Implement proper error handling for all API calls
  • Handle token expiration gracefully by refreshing when needed
  • Validate and sanitize all user inputs
  • Use HTTPS for all communications
  • Store tokens securely (never in client-side storage)

Testing the integration

Before you ship it, make sure to thoroughly test your integration:

  1. Test the full auth flow manually
  2. Create unit tests for individual functions
  3. Set up integration tests to simulate the entire process
  4. Test error scenarios (e.g., invalid tokens, network errors)

Conclusion

And there you have it! You've just built a robust authorization flow for your SignRequest integration. Remember, this is just the beginning. From here, you can expand your integration to leverage all the awesome features SignRequest has to offer.

Keep coding, keep learning, and most importantly, keep having fun with it!

Additional resources

Happy integrating!