Back

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

Aug 15, 20246 minute read

Hey there, fellow JavaScript aficionado! Ready to dive into the world of ServiceM8 integrations? Let's roll up our sleeves and build a rock-solid auth flow that'll make your integration shine. We'll keep things concise and focused, so you can get up and running in no time.

Introduction

ServiceM8 is a powerhouse for field service businesses, and building a secure integration is key to unlocking its potential. Today, we're zeroing in on the authorization flow – the gatekeeper of your integration. Get this right, and you're golden.

Prerequisites

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

  • Your favorite JavaScript environment set up
  • A ServiceM8 developer account with API credentials
  • A basic understanding of OAuth 2.0 (but don't sweat it if you're a bit rusty)

OAuth 2.0 Flow Overview

We're using the OAuth 2.0 authorization code grant. It's like a secret handshake between your app and ServiceM8. User approves, you get a code, swap it for tokens, and voilà – you're in!

Setting up the Authorization Request

First things first, let's craft that authorization URL:

const authUrl = new URL('https://api.servicem8.com/oauth/authorize'); authUrl.searchParams.append('response_type', 'code'); authUrl.searchParams.append('client_id', YOUR_CLIENT_ID); authUrl.searchParams.append('redirect_uri', YOUR_REDIRECT_URI); authUrl.searchParams.append('state', generateRandomState());

That state parameter? It's your CSRF shield. Keep it safe, you'll need it later.

Implementing the Authorization Callback

When ServiceM8 redirects back, you'll need to catch that callback:

app.get('/callback', (req, res) => { if (req.query.state !== savedState) { return res.status(400).send('State mismatch. Possible CSRF attack.'); } const authCode = req.query.code; // Time to exchange this code for tokens! });

Exchanging the Authorization Code for Access Token

Now for the good stuff – let's get those tokens:

const tokenResponse = await fetch('https://api.servicem8.com/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', code: authCode, client_id: YOUR_CLIENT_ID, client_secret: YOUR_CLIENT_SECRET, redirect_uri: YOUR_REDIRECT_URI }) }); const { access_token, refresh_token } = await tokenResponse.json(); // Store these securely - they're your keys to the kingdom!

Refreshing Access Tokens

Access tokens don't last forever. When they expire, it's refresh time:

async function refreshAccessToken(refreshToken) { const response = await fetch('https://api.servicem8.com/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'refresh_token', refresh_token: refreshToken, client_id: YOUR_CLIENT_ID, client_secret: YOUR_CLIENT_SECRET }) }); return response.json(); }

If the refresh token is expired, time to send the user through the auth flow again.

Making Authenticated Requests to ServiceM8 API

You've got the token, now use it:

const apiResponse = await fetch('https://api.servicem8.com/api_1.0/company.json', { headers: { 'Authorization': `Bearer ${accessToken}`, 'Accept': 'application/json' } }); if (apiResponse.status === 401) { // Time to refresh that token! }

Best Practices and Security Considerations

  • Never store tokens in local storage. Use secure, HTTP-only cookies or server-side storage.
  • Always use HTTPS. Always.
  • Log auth errors, but be careful not to expose sensitive info.
  • Implement token rotation for added security.

Conclusion

And there you have it! You've just built a robust auth flow for your ServiceM8 integration. Pat yourself on the back – you've laid the foundation for something great.

Next up? Start exploring the ServiceM8 API and build out those awesome features you've been dreaming of. The sky's the limit!

Remember, the best integrations are built on a solid auth foundation. You've got this. Now go forth and code something amazing!