Organization-Required SSO

Fly.io organizations can now require members to authenticate with Single Sign On (SSO).

A lot of times, when you want SSO, you really want SSO, all the time. This is especially the case if you’re working on SOC2 compliance. Your security team wants to be able to look at your SSO IdP configuration and know that’s the last word in access control.

Here’s how this works: organization members can be required to authenticate with a Google account with a specific Google Workspace Hosted Domain (HD). Alternatively, members can be required to authenticate with a GitHub account belonging to a specific GitHub organization. Both can be configured on the organization settings page (https://fly.io/dashboard/<ORG>/settings).

In either case, members can still log into their account using whatever method they prefer (username/password or SSO). When they attempt to access organization-owned resources though, they will be prompted to re-authenticate with the organization-configured SSO method. This workflow might seem atypical, but it preserves the autonomy of individual users’ accounts while allowing organizations to enforce their preferred security policies.

The Nitty Gritty

We could have built this feature in a boring way, but that would have been… boring. Instead, we leveraged our macaroon tokens. We’ve written about those before and recently open-sourced the code that powers them. To let organizations to enforce security policies on their members, we’re adding third-party caveats to organizations’ tokens. Those caveats say that the token can’t be used until the API client obtains proof that the user has done the requisite SSO dance.

A bit more concretely, we add a third-party caveat to the your token like this

yourToken.Add3P(
    sharedAuthDotFlyIoKey,
    "https://auth.fly.io",
    NewCaveatSet(auth.ConfineGoogleHD("big-corp.biz")),
)

This third-party caveat will prevent the your token from being used unless it’s accompanied with a “discharge” token from auth.fly.io. The ConfineGoogleHD bit is instructing auth.fly.io to check that you have an @big-corp.biz Google account before issuing the discharge token.

So, now your token is unusable until you go and do some arcane token exchange. To facilitate that, we taught flyctl and the web-frontend for https://fly.io perform this token exchange for the you. The client (flyctl or fly.io) bounces you over to auth.fly.io, which in turn bounces you into Google’s OAuth flow. When this dance concludes, the client gets the discharge token and is able to use that previously useless API token.

This is all weird, proprietary crypto-token nonsense, but it’s also pretty interesting if you’re into that kind of thing. You can read a bit more about what third-party caveats are and how they work here.

The really cool thing, and something we’ll write more about soon, is that you can run your own service for issuing discharge tokens. We’ve built this all with the intent of allowing organizations to configure their own third-party caveats to be added to their tokens. That means you’ll be able to require your users to jump through whatever hoops you want before accessing fly.io or using flyctl. Here’s a demo discharge service that requires someone to give a :+1: in Slack before a macaroon can be used.

7 Likes

Will any other SSOs or generic OAuth2/OIDC be available in the future? We don’t use Google or GitHub.

Possibly, but that’s not something that’s being worked on currently.