Back

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

Aug 11, 20246 minute read

Hey there, fellow JavaScript developer! Ready to dive into the world of Xero integrations? You're in the right place. Today, we're going to walk through building the authorization flow for a public Xero integration. Don't worry, I'll keep things concise and to the point – I know you've got code to write!

Introduction

Xero's API is a powerful tool for building financial applications, and it uses OAuth 2.0 for authentication. We'll be focusing on implementing this auth flow to get your integration up and running smoothly.

Prerequisites

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

  • A Xero developer account (if you don't have one, go grab it!)
  • An app registered in the Xero developer portal
  • A Node.js environment set up and ready to go

Setting up the project

Let's get our project off the ground:

mkdir xero-integration && cd xero-integration npm init -y npm install express axios oauth-pkce

Great! Now we've got the basics in place.

Implementing the OAuth 2.0 flow

Here's where the magic happens. We'll use the PKCE (Proof Key for Code Exchange) flow for added security.

First, let's generate our PKCE code verifier and challenge:

const { generators } = require('oauth-pkce'); const codeVerifier = generators.codeVerifier(); const codeChallenge = generators.codeChallenge(codeVerifier);

Now, let's create our authorization URL:

const authUrl = `https://login.xero.com/identity/connect/authorize? response_type=code& client_id=YOUR_CLIENT_ID& redirect_uri=YOUR_REDIRECT_URI& scope=YOUR_SCOPES& state=YOUR_STATE& code_challenge=${codeChallenge}& code_challenge_method=S256`;

When the user authorizes your app, they'll be redirected back to your redirect_uri. Handle this callback like so:

app.get('/callback', async (req, res) => { const { code } = req.query; // Exchange the code for tokens const tokenResponse = await axios.post('https://identity.xero.com/connect/token', { grant_type: 'authorization_code', code, redirect_uri: YOUR_REDIRECT_URI, code_verifier: codeVerifier }); // Store these tokens securely! const { access_token, refresh_token } = tokenResponse.data; });

Token management

Storing tokens securely is crucial. Consider using environment variables or a secure database. Here's a quick refresh function:

async function refreshToken(refresh_token) { const response = await axios.post('https://identity.xero.com/connect/token', { grant_type: 'refresh_token', refresh_token, client_id: YOUR_CLIENT_ID, client_secret: YOUR_CLIENT_SECRET }); return response.data; }

Making authenticated API requests

Now that you've got your access token, you can start making API calls:

const response = await axios.get('https://api.xero.com/api.xro/2.0/Organisation', { headers: { 'Authorization': `Bearer ${access_token}`, 'Accept': 'application/json' } });

Error handling and edge cases

Always be prepared for token expiration or revoked access. Implement proper error handling:

try { // Make API call } catch (error) { if (error.response && error.response.status === 401) { // Token expired, refresh and retry const newTokens = await refreshToken(refresh_token); // Update stored tokens and retry the request } }

Best practices and security considerations

Remember to:

  • Never expose your client secret in client-side code
  • Use the state parameter to prevent CSRF attacks
  • Store tokens securely, preferably encrypted

Conclusion

And there you have it! You've now got the basics of a Xero integration auth flow. From here, you can start building out more features and really make your integration shine.

Resources

For more info, check out:

Happy coding, and may your integration be bug-free and your coffee strong!