Back

How to build a public ConnectWise Manage integration: Building the Auth Flow

Aug 16, 20249 minute read

Hey there, fellow developer! Ready to dive into the world of ConnectWise Manage integrations? Today, we're going to focus on one of the most crucial aspects of building a public integration: the authorization flow. Don't worry, I've got your back – we'll walk through this together, step by step.

Introduction

ConnectWise Manage is a powerful tool for managing business operations, and building an integration with it can open up a world of possibilities. But before we can start pulling data or pushing updates, we need to tackle the authorization process. It's like getting a VIP pass to the coolest club in town – without it, you're not getting in!

Prerequisites

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

  • A ConnectWise developer account (if you don't have one, go grab it!)
  • An application registered in the ConnectWise Developer Portal
  • A basic Node.js and Express.js setup ready to go

Got all that? Great! Let's get this party started.

Understanding ConnectWise Manage OAuth 2.0 Flow

ConnectWise Manage uses OAuth 2.0 for authorization, specifically the Authorization Code Grant Type. It's like a secret handshake between your app and ConnectWise. Here's what you need to know:

  • You'll need a client ID and client secret (think of them as your app's username and password)
  • You'll also need a redirect URI (the place where ConnectWise will send the user after they've logged in)

Implementing the Authorization Flow

Alright, let's roll up our sleeves and get coding!

Setting up environment variables

First things first, let's keep our secrets... well, secret. Create a .env file and add your client ID and secret:

CW_CLIENT_ID=your_client_id_here
CW_CLIENT_SECRET=your_client_secret_here
CW_REDIRECT_URI=http://localhost:3000/callback

Creating the authorization URL

Now, let's create a function to build our authorization URL:

const authUrl = new URL('https://auth.connectwise.com/oauth/authorize'); authUrl.searchParams.append('client_id', process.env.CW_CLIENT_ID); authUrl.searchParams.append('response_type', 'code'); authUrl.searchParams.append('redirect_uri', process.env.CW_REDIRECT_URI);

Handling the redirect and exchanging the code for tokens

When the user comes back from ConnectWise, they'll bring a special code with them. We need to trade this code for access tokens:

const axios = require('axios'); async function getTokens(code) { const response = await axios.post('https://auth.connectwise.com/oauth/token', { grant_type: 'authorization_code', client_id: process.env.CW_CLIENT_ID, client_secret: process.env.CW_CLIENT_SECRET, code: code, redirect_uri: process.env.CW_REDIRECT_URI }); return response.data; }

Storing and refreshing access tokens

Don't forget to store these tokens securely and set up a mechanism to refresh them when they expire. You could use a database or a secure in-memory store for this.

Building the Express.js Routes

Let's set up some routes to handle our auth flow:

const express = require('express'); const app = express(); app.get('/login', (req, res) => { res.redirect(authUrl.toString()); }); app.get('/callback', async (req, res) => { const { code } = req.query; const tokens = await getTokens(code); // Store tokens securely here res.send('Logged in successfully!'); }); app.get('/logout', (req, res) => { // Implement token revocation here res.send('Logged out successfully!'); });

Securing the Integration

Security is crucial, so let's add some extra layers of protection:

Implementing PKCE

PKCE (Proof Key for Code Exchange) adds an extra layer of security. Here's a quick implementation:

const crypto = require('crypto'); function generateCodeVerifier() { return crypto.randomBytes(32).toString('hex'); } function generateCodeChallenge(verifier) { return crypto.createHash('sha256').update(verifier).digest('base64') .replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); }

Securely storing client secrets and tokens

Never, ever store these in plain text. Use environment variables for secrets and consider using a secure database or key management service for tokens.

Handling token expiration and refresh

Set up a mechanism to check token expiration and refresh when necessary:

async function refreshToken(refreshToken) { // Implement token refresh logic here }

Testing the Authorization Flow

Time to put our code to the test! Fire up your server and try logging in. Watch the network tab in your browser's dev tools to see the OAuth dance in action.

Best Practices and Considerations

  • Always handle errors gracefully and provide clear feedback to users
  • Implement rate limiting to avoid hitting API usage limits
  • Keep an eye on the ConnectWise API changelog and update your integration accordingly

Conclusion

And there you have it! You've just built a solid foundation for your ConnectWise Manage integration. The authorization flow is the gatekeeper to all the amazing things you can do with the API. From here, you can start building out the rest of your integration, whether that's pulling in ticket data, updating company information, or whatever cool idea you've got up your sleeve.

Resources

Want to dive deeper? Check out these resources:

Remember, building integrations is as much about problem-solving as it is about coding. Don't be afraid to experiment, and most importantly, have fun with it! Happy coding!