July 26, 2022
min read

There and Back Again: An OAuth Story

Keith Casey

In my five years at Okta, I lived and breathed OAuth 2.0 almost by accident.

The first week I joined, they were sketching out the beta program of API Access Management which was effectively “OAuth as a Service.” As the new guy, I had few set responsibilities yet but I was already “the API guy” so the Chief Product Officer looked around the room and said “this is yours.”

At that point, I thought I knew what OAuth was and how to use it. I thought I understood scopes and grant types. I thought I understood JWT. But just to double check, I printed a few of the main RFCs, put them in a binder and spent every moment of the next 4 days reading, highlighting, and googling for all I was worth. By the end of that, I knew more about OAuth but another dozen RFCs lurked in the shadows with their bizarre combinations of SHOULD, MAY, MUST, MUST NOT, and the occasional YOU SHALL NOT PASS.

Fast forward a few years and friends at ngrok said how “easily” you could implement OAuth. Skeptical but open minded, our CEO Alan Shreve set up a demo.

Using ngrok with OAuth 2.0

Alan started with the basics that everyone does with ngrok:

ngrok http 80

When I loaded his url, I saw his app. Although it was working deep magic behind the scenes, it was exactly what I expected. Then Alan made one small change:

ngrok http 80 --oauth=google

When I refreshed his url, I was presented with a new prompt:

Google login screen in front of ngrok

And that blew my mind. Without changing his application or even restarting it, he’d just deployed OAuth 2.0. I’d known organizations that spent months trying to do the same. Later, I discovered you can also use Facebook, Github, or Microsoft as your OAuth provider.

Using ngrok to protect your apps

Digging into the mechanics of this flow, the ngrok edge is acting as a lightweight policy enforcement point ensuring that any traffic attempting to enter the tunnel has an access token created by the corresponding OAuth provider. Because this enforcement is performed on the edge as opposed to the application itself, the application never receives and therefore does not have to process these requests.

As we dig deeper into the traffic in the tunnel, we find ngrok injects select fields from the OAuth provider into request headers for the application. If your application doesn’t or can’t use these fields, you can ignore them. At minimum, now we have a user identity attached to every request for logging and audits but we can do more. But more importantly, because now we have the user’s email - in the ngrok-auth-user-email header - from our trusted OAuth provider, we could use it to bootstrap a user session.

ngrok Headers from OAuth provider

Again, the simple power and flexibility of that was mind blowing. We could strip away legacy authentication systems and bring them under the same authentication policies and practices as our modern systems.

Unfortunately, this was just for public OAuth providers, right?

Using ngrok with a Custom OAuth Provider

Then Alan took the next step. Here’s my version of his command:

ngrok http 80 \
    --oidc=https://tenant.oktapreview.com/oauth2/j98123ue928ue \
    --oidc-client-id=myclientid \

First, our starting point hasn’t changed. We’re still tunneling http and connecting to local port 80.

The next options - oidc, oidc-client-id, and oidc-client-secret - specify an Okta authorization server from my former product API Access Management. By setting those parameters, we’ve switched from a public OAuth provider which everyone has (google) to one only available to our employees which enforces our specific authentication and authorization policies.

We’ve just brought our custom applications, legacy apps, and even our IoT device under the same security policy without changing the underlying system.

And unlike with the public OAuth providers, the entire access token is passed as a header called ngrok-auth-oauth-access-token so we have every field from the authorization server. Here is the decoded and slightly obfuscated payload of my resulting access token:

Okta access token passed to ngrok

At that moment, Alan convinced me ~~he was a wizard~~ ngrok was doing great things and planning more.

ngrok implements OAuth 2.0 in front of any application in seconds without modifying the application. If we do need to integrate OAuth, we can start small with the user’s email address and expand into using the entire access token.

ngrok and OAuth 2.0: What’s next?

As we get deeper into specifications, use cases, and what our customers need, we’re faced with nearly endless options so we’d love to hear from you:

What other public OAuth providers should we implement? Should the ID token be available also? What private OAuth providers should we validate? How should we handle refresh tokens?

Join us in the ngrok Community Slack and share your ideas, questions, concerns, and successes.

Share this post
Keith Casey
Keith Casey serves on the Product/GTM Team at ngrok helping teams launch their systems faster and easier than ever before. Previously, he served on the Product Team at Okta working on Identity and Authentication APIs, as an early Developer Evangelist at Twilio, and worked to answer the Ultimate Geek Question at the Library of Congress. His underlying goal is to get good technology into the hands of good people to do great things. In his spare time, he writes at CaseySoftware.com and lives in the woods. He is also a co-author of A Practical Approach to API Design.