Back

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

Sep 14, 20248 minute read

Hey there, fellow developer! Ready to dive into the world of Shippo integrations? Today, we're going to walk through building a rock-solid authorization flow for your public Shippo integration. Buckle up, because we're about to make your shipping dreams come true!

Introduction

Shippo's API is a powerhouse for all things shipping, but to harness its full potential, we need to nail the authorization process. After all, we want our users to feel safe and secure when using our integration, right? Let's make it happen!

Prerequisites

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

  • A Shippo developer account (if you don't have one, go grab it!)
  • A basic understanding of OAuth 2.0 (don't worry, we'll refresh your memory)
  • Node.js and Express.js set up and ready to go

Got all that? Awesome! Let's build something cool.

Setting up the project

First things first, let's get our project off the ground:

mkdir shippo-integration cd shippo-integration npm init -y npm install express axios dotenv

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

Configuring Shippo OAuth

Head over to Shippo's developer portal and register your application. You'll need to:

  1. Get your client ID and client secret (treat these like your firstborn)
  2. Set up a redirect URI (this is where Shippo will send your users after they authorize your app)

Once you've got those, create a .env file in your project root and add:

SHIPPO_CLIENT_ID=your_client_id
SHIPPO_CLIENT_SECRET=your_client_secret
REDIRECT_URI=http://localhost:3000/callback

Implementing the authorization flow

Now for the fun part! Let's create a route to kick off the OAuth flow:

const express = require('express'); const axios = require('axios'); require('dotenv').config(); const app = express(); app.get('/auth', (req, res) => { const authUrl = `https://goshippo.com/oauth/authorize?client_id=${process.env.SHIPPO_CLIENT_ID}&redirect_uri=${encodeURIComponent(process.env.REDIRECT_URI)}&response_type=code`; res.redirect(authUrl); });

When a user hits this route, they'll be whisked away to Shippo's authorization page. Magic!

Handling the callback

After the user grants permission, Shippo will redirect them back to your app. Let's be ready for them:

app.get('/callback', async (req, res) => { const { code } = req.query; try { const response = await axios.post('https://goshippo.com/oauth/token', { grant_type: 'authorization_code', code, client_id: process.env.SHIPPO_CLIENT_ID, client_secret: process.env.SHIPPO_CLIENT_SECRET, redirect_uri: process.env.REDIRECT_URI }); const { access_token, refresh_token } = response.data; // Store these tokens securely (more on this later) res.send('Authorization successful!'); } catch (error) { console.error('Error exchanging code for token:', error); res.status(500).send('Authorization failed'); } });

Token management

Now that we've got our precious tokens, we need to keep them safe and sound. In a real-world scenario, you'd want to encrypt these and store them in a secure database. For now, let's keep it simple:

let accessToken = null; let refreshToken = null; // Function to refresh the token async function refreshAccessToken() { try { const response = await axios.post('https://goshippo.com/oauth/token', { grant_type: 'refresh_token', refresh_token: refreshToken, client_id: process.env.SHIPPO_CLIENT_ID, client_secret: process.env.SHIPPO_CLIENT_SECRET }); accessToken = response.data.access_token; refreshToken = response.data.refresh_token; } catch (error) { console.error('Error refreshing token:', error); } }

Making authenticated requests

Time to put our shiny new access token to work:

app.get('/shipping-info', async (req, res) => { try { const response = await axios.get('https://api.goshippo.com/user/', { headers: { 'Authorization': `Bearer ${accessToken}` } }); res.json(response.data); } catch (error) { if (error.response && error.response.status === 401) { await refreshAccessToken(); // Retry the request } else { console.error('Error fetching shipping info:', error); res.status(500).send('Error fetching shipping info'); } } });

Error handling and edge cases

Always be prepared for the unexpected:

app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('Something broke!'); });

Security considerations

Remember, with great power comes great responsibility:

  • Never expose your client secret
  • Always use HTTPS in production
  • Implement CSRF protection (consider using the csurf package)

Testing the integration

Before you ship it (pun intended), give it a thorough test:

  1. Start your server and navigate to /auth
  2. Authorize the app on Shippo's page
  3. Check if you're redirected back successfully
  4. Try fetching shipping info to ensure the token works

Conclusion

And there you have it! You've just built a secure, user-friendly authorization flow for your Shippo integration. Pat yourself on the back – you've earned it!

Remember, this is just the beginning. From here, you can expand your integration to leverage all the awesome features Shippo has to offer. The shipping world is your oyster!

Happy coding, and may your packages always arrive on time! 📦🚚💨