Dev

Authenticating with 3rd Party Services

Jun 16, 2015

I’ll be honest—authentication is not an exciting topic. I thought about skipping this post, but then I realized that this subject is often left out of blog posts. Either the post is about everything after authentication or the author realizes that authentication is an entire post on its own, so they write a quick paragraph and link to another article. After all I’ve been through with integrations, it would be a disservice to myself and others to skip this post—I’ve learned too much, and I need to share this knowledge!


The first thing to know about authenticating with a 3rd party service is that there are multiple methods for doing so, and it’s up to the service to decide which method you must use. Newer services will often start by providing a simpler method of authentication, like BasicAuth with an API key, while more veteran services will offer more user-friendly authorization flows, like OAuth. Both serve the purpose of authenticating with the service, but one is easier on the dev while the other is easier on the user.

authorizing-integrations-oauth

If a service looks appealing enough to integrate with, there’s a good chance it’s using one of the more serious methods of authentication. I say this because integrations are a real commitment, and if the service really wants you to tie your app so closely to theirs, they’ve probably gone the extra mile to support one of the open standards of authentication.

In my own experience, BasicAuth often means “Yes, we have an API. You can play with it if you want,” while OAuth2 means “Our business relies on integrations as a selling point. Here’s our documentation, support center, and IRC channel.” Occasionally, you’ll find a neglected service with forced support for OAuth or a solid service that doesn’t need anything more than BasicAuth, but the authentication method is often a good indicator of how smooth this ride will be.

authorizing-integrations-documentation

With Cushion, I started out by integrating with the heavy hitters of the freelance industry—Harvest and FreshBooks. Both support OAuth, which is great, but each supports a different version of the standard, which is not great. Harvest offers authentication through OAuth2, which directs the user through an authorization flow and provides the dev with an access token and a refresh token. The access token expires after 18 hours, so the dev will eventually need to request a new access token using the refresh token. This is a bit of extra work, but it keeps the token somewhat fresh, in case the access token lands in the wrong hands.

FreshBooks, the older of the two services, offers authentication through OAuth1, the older standard. To the user, the authorization flow is the same, but to the dev, there’s no expiration on the access token. Once the dev receives the token, they’re good to go indefinitely, until the user deauthorizes the integration. OAuth1 is definitely easier on the dev, but not as secure. Then again, an 18-hour expiration period sort of defeats the purpose of an expiring token.

authorizing-integrations-custom

At first, I built an authorization system from scratch using the OAuth and OAuth2 gems. After authorizing, Cushion would show a sleek progress screen as it moved through each step before retrieving the tokens. For anyone using Cushion, it looked seamless, but under the hood, it was a mess. I could easily imagine this system becoming a headache with each new service I added—especially if it introduced a new authorization method. After wrapping up Harvest, it finally dawned on me that another solution existed—a much easier one. I still kick myself for forgetting the OmniAuth gem, but in a single afternoon, I was able to replicate the same system I spent weeks implementing. I can’t get those weeks back, but at least I caught myself before I wasted even more time.

For those unfamiliar with OmniAuth, it abstracts the authorization process through the use of “strategies”. The strategy tells OmniAuth which authentication method the service uses and then formats the service’s response into standardized payloads. The user payload includes the user’s ID, name, email, etc., while the credentials include the access token and optional refresh token. With OmniAuth, authorizing with a new service is as easy as installing its strategy. Though OmniAuth is more commonly used during the sign up process, it works surprisingly well with integrations, too.

Now that I had OmniAuth handling the authorization flow, I needed to safely store the access tokens. Access tokens don’t seem as precious as passwords, but considering they grant access to users’ account, they should be protected just the same. I store access tokens in an encrypted column on the authorization model, which bridges the gap between the user and the 3rd party service. To enable an integration, I simply need to pass it the authorization model—nothing more.

authorizing-integrations-authorizations

Currently, Cushion only allows one authorization per service, but I quickly learned that many users have multiple accounts for a single service. Since services like Harvest are used by both freelancers and companies, clients will often invite freelancers to be a guest on their account to streamline the delivery of hours and invoices. Some freelancers also invite their subcontractors to use their account for the same reason.

authorizing-integrations-multiple-authorizations

Luckily, the changes required to make multiple authorizations happen are minimal. I built the integration system in a way that allows for multiple authorizations from the start—I just need to design the front-end to handle them. This will entail asking the user which account to use whenever enabling an integration and providing the ability to delete authorizations from the table view. If I end up including any additional details with authorizations, like activity, I might be able to justify a new page for an individual authorization. At the moment, though, the table view will suffice.

Share this on Twitter or Facebook

Archive

  1. Funding Cushion
    Story
  2. Hiring a Team of Freelancers
    Story
  3. Taking a Real Break From Work
    Story
  4. Slack as a Notification Center
    Dev
  5. Document Your Features
    Story
  6. 300
    Story
  7. Vacations
    Design
  8. Offering Discounts
    Design
  9. Waves of Traffic
    Story
  10. Less Blogging, More Journaling
    Story
  11. Retention Through Useful Features
    Design
  12. The Onboarding Checklist
    Design
  13. Spreading the Word
    Story
  14. From Beta to Launch - The Subdomain
    Dev
  15. From Beta to Launch - Sign up
    Design
  16. From Beta to Launch - Messaging
    Design
  17. Launch
    Story
  18. Authenticating with 3rd Party Services
    Dev
  19. Intro to Integrations
    Design
  20. Inspiration vs Imitation
    Story
  21. The Emotional Rollercoaster
    Story
  22. Designing Project Blocks
    Design
  23. Everything in Increments
    Story
  24. Deleting Your Account
    Design
  25. Designing the Subscription Page
    Design
  26. Rewriting the Timeline
    Dev
  27. Restructuring the Individual Project Page
    Design
  28. Project Blocks
    Story
  29. Redesigning the Homepage
    Design
  30. Multiple Timelines
    Design
  31. Archiving and Estimate Differences
    Design
  32. Multiple Financial Goals
    Design
  33. Zooming in on the Timeline
    Design
  34. Currency
    Dev
  35. Preferences, Accounts, and a Typeface Change
    Design
  36. Sending Out the First Email
    Story
  37. Currency Inputs, Notifications, and Invoice Nets
    Design
  38. Dots and Lines
    Design
  39. Calculating in the Database and Revealing Tendencies
    Dev
  40. Improved Form UX
    Design
  41. Cushion is Online
    Story
  42. Schedule Timeline Patterns
    Design
  43. A Slimmer Schedule Timeline
    Design
  44. The Schedule Timeline
    Design
  45. Plugging in Real Data for the First Time
    Design
  46. Transitions and Project Lists
    Design
  47. Death to Modals
    Design
  48. The Individual Project Page
    Design
  49. Estimated Incomes and Talks with Other Freelancers
    Story
  50. Statuses to Lists and the Paid Beta
    Story
  51. The Timeline
    Story
  52. Invoice Terminology
    Dev
  53. Modal Forms
    Dev
  54. Wiring the Backend to the Frontend
    Dev
  55. Balancing Design and Dev
    Story
  56. Timecop, Monocle, and Vagrant
    Dev
  57. Going with Ruby and Sinatra
    Dev
  58. Ditching local-first and trying out Node.js
    Dev
  59. Switching to AngularJS
    Dev
  60. Building the Table with Vue.js
    Dev
  61. Clients, Projects, and Invoices
    Dev
  62. Introduction
    Story

Ask a Freelancer

A podcast series where experienced freelancers answer questions about freelancing.

Listen to the Podcast

Talking Shop

An interview series where we talk to freelancers about important topics in the freelance world.

Read the Interviews

Running Costs

Take a close look at the costs that go into running a web app and why we use specific services.

View the Costs

How It’s Made

Follow along with the journal for insight into the overall experience of building an app.

Read the Journal