Back

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

Aug 15, 2024 β€’ 6 minute read

Hey there, fellow JavaScript enthusiast! Ready to dive into the world of Harvest integrations? Today, we're going to focus on the most crucial part of any integration: the authorization flow. Buckle up, because we're about to make your Harvest integration dreams come true!

Introduction

Harvest's API is a powerful tool for time tracking and project management. But before we can tap into all that goodness, we need to set up a secure authorization flow. This is where the magic happens, folks!

Prerequisites

I'm assuming you're already a JavaScript wizard, but just to make sure we're on the same page:

  • You've got Node.js and npm installed
  • You're familiar with OAuth 2.0 (if not, don't sweat it, we'll cover the basics)

Setting up the project

Let's get this party started:

mkdir harvest-integration && cd harvest-integration npm init -y npm install express axios dotenv

Registering your application with Harvest

First things first, head over to Harvest Developers and create an account if you haven't already. Once you're in, create a new OAuth2 application to get your client ID and client secret. These are your golden tickets, so keep them safe!

Implementing the authorization flow

Now for the main event! Let's break this down into three key steps:

Creating the authorization URL

const authUrl = `https://id.getharvest.com/oauth2/authorize?client_id=${clientId}&response_type=code&redirect_uri=${redirectUri}`;

Handling the redirect and token exchange

app.get('/callback', async (req, res) => { const { code } = req.query; const tokenResponse = await axios.post('https://id.getharvest.com/api/v2/oauth2/token', { code, client_id: process.env.CLIENT_ID, client_secret: process.env.CLIENT_SECRET, grant_type: 'authorization_code', redirect_uri: process.env.REDIRECT_URI }); // Store tokenResponse.data.access_token and tokenResponse.data.refresh_token });

Storing and refreshing access tokens

Pro tip: Use a secure storage solution for your tokens. As for refreshing:

async function refreshToken(refreshToken) { const response = await axios.post('https://id.getharvest.com/api/v2/oauth2/token', { refresh_token: refreshToken, client_id: process.env.CLIENT_ID, client_secret: process.env.CLIENT_SECRET, grant_type: 'refresh_token' }); return response.data.access_token; }

Building the main application routes

Here's a quick rundown of the routes you'll need:

app.get('/auth', (req, res) => { res.redirect(authUrl); }); app.get('/callback', /* ... */); app.get('/protected', authenticateToken, (req, res) => { // Your protected route logic here });

Error handling and edge cases

Always be prepared! Handle expired tokens by refreshing them, and don't forget to gracefully handle user denials and other potential errors.

Testing the integration

Time to put on your testing hat! Use Postman or cURL to send requests to your API. Make sure those tokens are being stored and refreshed correctly.

Best practices and security considerations

Security first, am I right? Here are some quick tips:

  • Use environment variables for sensitive data
  • Always use HTTPS in production
  • Implement PKCE for added security (especially for mobile or single-page apps)

Conclusion

And there you have it! You've just built a rock-solid authorization flow for your Harvest integration. Pat yourself on the back, you've earned it!

Remember, this is just the beginning. Now that you've got the auth flow down, the sky's the limit for what you can do with the Harvest API. Go forth and integrate!

Happy coding, and may your harvest be bountiful! πŸŒΎπŸ‘¨β€πŸ’»