Back

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

Aug 16, 20247 minute read

Introduction

Hey there, fellow developers! Ready to dive into the world of Holded integrations? You're in the right place. Today, we're going to walk through building the authorization flow for a public Holded integration. This is crucial stuff – it's how your users will securely connect their Holded accounts to your awesome app. Let's get cracking!

Prerequisites

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

  • Your favorite JavaScript environment set up
  • A Holded developer account (if you don't have one, go grab it!)
  • Your Holded API credentials (client ID and secret)

Got all that? Great! Let's move on to the good stuff.

Understanding Holded's OAuth 2.0 Flow

Holded uses OAuth 2.0 for authorization. If you've worked with OAuth before, this will feel familiar. If not, don't sweat it – we'll break it down.

The key players in this dance are:

  • Your client ID
  • Your client secret (keep this safe!)
  • A redirect URI (where Holded will send the user after they authorize your app)

Setting Up the Authorization Request

First things first, we need to construct the authorization URL. It'll look something like this:

const authUrl = `https://app.holded.com/oauth/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&state=${state}`;

See that state parameter? It's your secret weapon against CSRF attacks. Generate a unique value for each request and store it. We'll check it later.

Implementing the Redirect Handler

After the user authorizes your app, Holded will redirect them back to your redirect_uri with a code parameter. Here's where you'll capture that code:

app.get('/callback', (req, res) => { const { code, state } = req.query; // Verify the state matches what you stored earlier if (state !== storedState) { return res.status(400).send('State mismatch. Possible CSRF attack.'); } // Use the code to get an access token (we'll do this next) });

Exchanging the Authorization Code for Access Token

Now for the fun part – trading that code for an access token:

const tokenResponse = await fetch('https://api.holded.com/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', code, client_id: clientId, client_secret: clientSecret, redirect_uri: redirectUri }) }); const { access_token, refresh_token } = await tokenResponse.json();

Storing and Managing Access Tokens

You've got the tokens – now keep 'em safe! Store them securely (think encryption, secure databases). And remember, access tokens expire, so be ready to use that refresh token when needed.

Making Authenticated Requests to Holded API

With your shiny new access token, you can start making API calls:

const response = await fetch('https://api.holded.com/api/invoices', { headers: { 'Authorization': `Bearer ${access_token}` } });

Error Handling and Edge Cases

Things don't always go smoothly, so be prepared. Handle common errors like expired tokens, network issues, or API limits gracefully. Your users will thank you!

Best Practices and Security Considerations

Remember:

  • Never expose your client secret
  • Always use HTTPS
  • Implement token rotation
  • Be prepared for token revocation

Testing the Authorization Flow

Before you ship it, test thoroughly! Set up a sandbox environment and simulate the entire flow. Try happy paths, sad paths, and everything in between.

Conclusion

And there you have it! You've just built a robust authorization flow for your Holded integration. Pat yourself on the back – you're well on your way to creating something awesome.

Next steps? Start building out the rest of your integration. The sky's the limit!

Remember, the Holded community is here if you need help. Don't hesitate to reach out if you get stuck. Now go forth and code brilliantly!