How The Big Cloud Providers Fail at IDaaS: Heuristics
I started looking for an Identity as a Service (IDaaS) offering recently for my hobby project Tower Scouter. When I’m thinking of IDaaS I’m thinking of a service that handles all of the authentication, authorization and user management for my application so that I can spend less time on these well-solved problems and more time on what makes my application unique.
Identity is something that literally every SaaS startup is going to need to provide a solution for. Surely IDaaS would be a commodity offering in all the big cloud providers given the generally accepted standards of OAuth2 and OpedID Connect (OIDC). Right?
Nope. It turns out that all the cloud providers have significant gaps in providing a spec-compliant IDaaS offering.
Don’t get me wrong, there are IDaaS offerings by the big three: Google Identity Platform, AWS Cognito, and Azure Active Directory B2C. They all have simple getting started guides, tons of usage and SDKs to quickly integrate the service into an application. But if you look under the hood it turns out they all have major disconnects with how the protocol should work as defined in the official OAuth2/OIDC specs.
Overview on OAuth2 and OIDC
OAuth2 specification was published in 2012 and has been a cornerstone for providing a standard mechanism to securely handle the communication paths between the multiple parties involved during an authorization handshake. The parties are described in detail within the official spec, which is quite readable. To summarize:
OAuth2 Parties
- The Resource Owner (e.g. an end-user)
- Client (Requests access to a protected resource on behalf of the Resource Owner, e.g. a Single Page App, a mobile app)
- Authorization Server (Issues access tokens to Client after authenticating and authorizing the Resource Owner, e.g. Login with Google/Facebook, AWS Cognito, Auth0)
- Resource Server (e.g. a Protected API)
Although this provided a standard way of authorization (can they get in?), the OAuth2 spec intentionally left out any specifics on how to perform the authentication (who is this user?). OpenID Connect (OIDC) came into the picture two years later as a layer on top of OAuth2 as the standard authentication layer. This provided a standard way for describing a user via claims (e.g. name, email, etc) through a JSON Web Token (JWT). The JWT is a specific implementation of the generic OAuth2 ‘access token’.
Just to make things confusing, the OIDC spec also renamed a couple of the OAuth2 parties:
- Resource Owner is now just referred to as just ‘End-User`
- Authorization Server is now referred to as an ‘OIDC Provider’ (OP)
A typical flow may look something like this:
In this case, the user chose to authenticate directly with OP via username and password. It would also be possible for the user (via an account chooser) to select one of the federated identity providers and login directly via that channel.
Heuristics for Evaluating IDaaS
There are some rule of thumb heuristics that I have defined for evaluating each of the IDaaS offerings. Note that these heuristics are based on the context of a lean startup mentality of wanting to rapidly spin up an identity solution to focus in on the real business logic. A large enterprise mentality would appropriately have different heuristics when looking at identity management (e.g. SAML integrations, auditability, compliance, pricing at scale, etc).
This is what I’m looking for in IDaaS offering:
- Choice of Social Federation: I’d like to offer my users their choice of logging in with their preferred social login. This reduces barriers for my users to signup by allowing them to use an existing login. It also protects my users in that they can avoid creating another custom username/password for my service.
- Choice of Custom Login: For the users that prefer not to use a social provider as a login, I still want to provide them the ability to create a custom username and password. In this case, I want the entire signup flow provided to me by the identity service. The signup flow UI, the enforcement of password requirements, the email confirmation, and the forgot password flow are all well-solved flows I’d rather not build myself.
- Account Linking: One problem with multiple options for social login is that the user is now burdened with remembering which social login they used for that specific site. I’d like to be able to have a single identity across social logins and username/password so that a user can log in in several different ways and I can have a single identity for that user.
- Fully Managed Service: Fully managed in the sense that I don’t want my application to have to deal with any sign-in/sign up logic. I want to redirect the users to a fully managed authorization endpoint that provides a UI for all the sign-in and signup flow. This provides increased security for my users as I never have to see the user’s password, even if they are creating a custom username/password for my site. I expect all these sign-in/signup flow are easily configurable from a pleasant to use management portal to quickly and easily make changes to the login experience and to manually administer users.
-
Brand Control: Although the custom login flow should ideally work out of the box, I would like the ability to customize the styling to match my brand. Beyond custom logos/colors I’d also like to be able to provide a custom domain so the user isn’t confused by seeing a different domain in the browser URL or the ‘from address’ during email signup flows.
⚠️Warning: These next 3 points get pretty nitty-gritty in the OAuth2/OIDC spec specifics, feel free to gloss over!
- OIDC Discovery Endpoint: The OpenID Connect Discovery Spec requires providers to expose the needed information for clients to interact with the provider in a standard way. This is done by exposing the endpoint of
/.well-known/openid-configuration
that details the authorization endpoint, the public certificate endpoint, and other supported features of the Authorization Server. This is important as having spec-compliant OIDC Discovery Endpoint in my IDaaS offering means I can easily reuse generic client-side libraries implementing the OIDC spec to securely implement the desired flows. - Authorization Code Flow w/ PKCE: Recently the Internet Engineering Taskforce (IETF) has published a draft recommending to NOT use Implicit flow for increased security. Their recommendation is to replace the implicit flow with the Authorization Code Flow with PKCE for Single Page Apps. The migration path from Implicit Flow to Authorization Code Flow w/ PKCE isn’t too difficult. Namely, the client will not receive an access token directly in the callback URL but rather an authorization code which can then be exchanged with the Authorization Server for the desired access token. This helps to limit exposure of the sensitive access token.
- Silent Refresh: A common practice for keeping a user logged in using the Implicit Flow or Authorization Code Flow w/ PKCE is to perform a Silent Refresh by opening an invisible iframe and attempting to get a new access token with a fresh expiration timestamp. This is outlined in the spec by providing the
prompt
parameter to the authorization endpoint with the value ofnone
. This provides a seamless way to keep users logged in without requiring long-lived access tokens.
That’s my criteria. In the next post, I’ll dive into how each of the cloud providers stacks up to these heuristics. What heuristics are important to you in an IDaaS offering? Is spec-compliance worth sweating about if it ‘just works’?