OAuth2 and OpenID Connect is all the rage with big platforms (Google, Facebook, GitHub) and identity SaaS products (Okta, Auth0) which is why you probably ended up at Ory Hydra. But before you start hacking away, the best use of your time right now is to re-evaluate if you really need OAuth2 and OpenID Connect.
To do so, we will cover common misunderstandings and misconceptions about OAuth2 in this document and guidance on what to do instead!
If you are looking for a system that implements registration, login, password reset, social sign in, profile management, 2fa, and more, check out Ory Kratos first!
What it's Good for
If you are like GitHub and you want to enable people not associated with your company like CircleCi or TravisCI to have access to your user's data, Ory Hydra is the right tool for you.
If you want apps and websites you don't own to use your application as a potential sign in (for example be listed alongside "Sign in with Google", "Sign in with Apple"), Ory Hydra is the right tool for you.
If you use an API that works with OAuth2 or OpenID Connect, then of course you need to use that API - but then you are on the OAuth2 / OpenID Connect client side!
If you want a system for user registration, password recovery, login form, session management and user settings, then don't start with OAuth2 right away. It's recommended to use Ory Kratos for your basic user management needs and then figure out if you still need OAuth2.
OAuth2 and OpenID Connect don't Solve Registration, Password Reset, ...
OAuth2 and OpenID Connect are so-called delegation protocols which aren't concerned with user registration, password recovery, changing a password or email address and so on.
Actually, OAuth2 and OpenID Connect don't even specify how your users sign in (email and password? username and password? passwordless? sms 2fa?), they only establish that you need a method for users to sign in.
If you are wondering what password hashing algorithm to use, or how your users sign up for your platform, then you don't need OAuth2 or OpenID Connect right now. Instead, you should give Ory Kratos a spin, which aims to solve that.
Access and Refresh Tokens aren't Sessions!
With OAuth2 and OpenID Connect you end up with three session layers:
- Your Application's Session Manager keeps track of the user within your application. You will use OpenID Connect to initiate and complete the login, but your application needs to store and track and invalidate the session.
- Ory Hydra maintains a session cookie. When a user signs in, the cookie will be set for that user. This allows the next OAuth2 request to complete without requesting the user to sign in again.
- Optionally - If your application connects to a third-party identity provider (such as Sign in with Google, GitHub, Facebook, ...) that third party provider also maintains a session of the user.
A common misconception is that access and refresh tokens represent a user session. They don't.
Let's take a look at a common example: CircleCI/TravisCI/... and GitHub. To use CircleCI or TravisCI or similar products, they usually prompt you to sign into GitHub because they need access to your repositories. Once access is granted, CircleCI creates a new user account in their database and generates a session cookie (see Application Session Manager above). If you now sign out of GitHub, you will make two observations:
- CircleCI still has access to your repositories;
- You are still logged into CircleCI.
If you instead sign out of CircleCI:
- CircleCI still has access to your repositories;
- You are still logged into GitHub.
That's because both applications are built by different people and different companies, and the user behavior on one site doesn't reflect user intent on another. It would be crazy if some app could just log you out of GitHub, or if signing out of Google would invalidate your sessions on all the websites where you used "Sign in with Google".
Access and refresh tokens allow developers you don't know to do things in your application in the name of your users over a prolonged period of time. CircleCI uses access tokens to watch your repositories for changes, update status checks on pull requests, using access and refresh tokens. These tokens are valid for as long as you don't remove CircleCI from your GitHub account. Logout doesn't change any of that.
If you want to read up on this more, check out OAuth 2.0 vs Session Management.
Now you should be at a point where
- you realize that you only want to solve sign up, login, session management and that you don't need OAuth2 - your next step in this case should be to check out Ory Kratos which does solve all of that;
- you are reaffirmed that you need OAuth2 and OpenID connect because you want developers you don't know to interact with your users and your users' data - in which case Ory Hydra is a great fit for you!
"But Google/Facebook/... use OAuth2 and OpenID Connect"
Have you ever wondered why, when signing into Google/Facebook/Twitter/...
- you don't see a screen asking you to grant permission ("Do you want to allow ... to access your ...?")?
- their mobile app doesn't open a browser window or use an embedded WebView?
- your browser doesn't perform tons of redirects?
The answer is quite simple - they don't use OAuth2 or OpenID Connect for login and session management in first-party scenarios. It goes even further than that - for example YouTube, which runs on a separate domain - doesn't use OAuth2 to sign into your Google account. They use a proprietary flow that includes HTTP Cookies.
However, OAuth2 and OpenID Connect do get used in certain scenarios at these companies:
- The Google Cloud SDK CLI uses OAuth2 to sign into your Google Cloud account;
- FireStick uses the OAuth2 Device Authorization grant to log you into your Amazon account;
- GitHub does offer an API to third-party developers that involves OAuth2.
"But SaaS Identity Products use OAuth2 and OpenID Connect"
They do, and they have great SDKs to help you avoid a lot of the OAuth2 and OpenID Complexity until you hit the very core limitations of OAuth2 which are amongst others:
- Up to three different session states (see for example Auth0 Session Layers);
- Multi-stage logout flows (see for example Auth0 Logout on NodeJS, Revoke Tokens on Auth0);
- Logout doesn't invalidate access tokens (see for example Auth0 Logout);
- Complex integration with Social Sign In (for example Twitter, Facebook, ...) on native mobile apps (see for example iOS Swift - Facebook Login).
We picked Auth0 docs a lot because they explain the caveats of using OAuth2 and OpenID Connect well. These limitations apply to all software (for example Ory Hydra, Okta, Keycloak, ...) that use OAuth2 and OpenID Connect as their primary protocols.
If all you need is user registration, log in, user settings, and similar flows - check out Ory Kratos!
You must Ensure Secure Storage of Access and Refresh Tokens
Storing access and refresh tokens involves tradeoffs:
- Storing tokens in the Browser's
- Storing tokens in a
httpOnlycookie is more secure but means that you need a server-side component which performs the OAuth2 flows and then stores the tokens in an encrypted cookie;
- Storing tokens in a database is secure but implies a lot of overhead.
On top of that, you need to refresh tokens when they expire which may become very complex in scenarios where you have more than one HTTP request using the access token. This is mainly true for systems that have refresh tokens which are valid for one use only (such as Ory Hydra, Auth0, ...).
Cookies are great and a common misconception is that cookies are less secure than tokens or less usable. For 95% of web applications it's enough to work with cookies, if they only run in the browser and not in a native mobile app. And that's great, because the browser takes care of:
- Bound to one top-level-domain only;
- Anti-XSS with
- TLS enforcement with
- Smaller CSRF attack surface with the new
- The domain model (cookies are isolated per domain);
Ory Kratos works both with tokens and cookies. Implementing login doesn't involve any manual token handling - just log in and you're done!
Access Token Scope isn't an Access Control Permission
The OAuth 2.0 Scope isn't an internal RBAC/ACL permission:
- A permission allows an actor to perform a certain action in a system: Bob is allowed to delete his own photos.
- OAuth 2.0 Scope implies that an end-user granted certain privileges to a client: Bob allowed the OAuth 2.0 Client to delete all users. But Bob might not be allowed to delete all users because Bob isn't an admin.
The OAuth 2.0 Scope can be granted without the end-user actually having the right permissions. In the examples above, Bob granted an OAuth 2.0 Client the permission ("scope") to delete all users in his name. However, since Bob isn't an administrator, that permission ("access control") isn't actually granted to Bob. Therefore any request by the OAuth 2.0 Client that tries to delete users on behalf of Bob should fail.