-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add section on oauth2 limitations at beginning
- Loading branch information
Showing
3 changed files
with
137 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
--- | ||
id: before-oauth2 | ||
title: Read This Before Learning OAuth2 or OpenID Connect! | ||
--- | ||
|
||
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! | ||
|
||
## OAuth2 and OpenID Connect do not solve Registration, Password Reset, ... | ||
|
||
OAuth2 and OpenID Connect are so-called delegation protocols which are not concerned with user registration, | ||
password recovery, changing a password or email address and so on. | ||
|
||
Actually, OAuth2 and OpenID Connect do not 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](https://www.ory.sh/kratos/) | ||
a spin, which aims to solve exactly that. | ||
|
||
## Access and Refresh Tokens are not 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 (e.g. 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 do not.** | ||
|
||
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: | ||
|
||
1. CircleCI still has access to your repositories; | ||
2. You are still logged into CircleCI. | ||
|
||
If you instead sing out of CircleCI: | ||
|
||
1. CircleCI still has access to your repositories; | ||
2. You are still logged into GitHub. | ||
|
||
That is because both applications are built by different people and different companies, and the user behavior on | ||
one site does not reflect user intent on another. It would be crazy if some app acould 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 do not 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 does not change any of that. | ||
|
||
If you want to read up on this more, check out [OAuth 2.0 vs Session Management](https://dzone.com/articles/oauth-20-vs-session-management). | ||
|
||
Now you should be at a point where | ||
|
||
1. 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](https://www.ory.sh/kratos/) which does solve all of that; | ||
2. 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 does not open a browser window or use an embedded WebView? | ||
- your browser doesn't perform tons of redirects? | ||
|
||
The answer is quite simple - they do not use OAuth2 or OpenID Connect for login and session management in first-party | ||
scenarios. It goes even farther than that - for example YouTube, which runs on a separate domain - does not 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 e.g. [Auth0 Session Layers](https://auth0.com/docs/sessions/concepts/session-layers)); | ||
- Multi-stage logout flows (see e.g. [Auth0 Logout on NodeJS](https://auth0.com/docs/quickstart/webapp/nodejs), [Revoke Tokens on Auth0](https://auth0.com/docs/tokens/guides/revoke-tokens)); | ||
- Logout does not invalidate access tokens (see e.g. [Auth0 Logout](https://auth0.com/docs/logout)); | ||
- Complex integration with Social Sign In (e.g. Twitter, Facebook, ...) on native mobile apps (see e.g. | ||
[iOS Swift - Facebook Login](https://auth0.com/docs/quickstart/native/ios-swift-facebook-login#before-you-start)). | ||
|
||
We picked Auth0 docs a lot because they explain the caveats of using OAuth2 and OpenID Connect well. These | ||
limitations apply to all software (e.g. 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](https://www.ory.sh/kratos/)! | ||
|
||
## You must Ensure Secure Storage of Access and Refresh Tokens | ||
|
||
Storing access and refresh tokens involves tradeoffs: | ||
|
||
- Storing tokens in the Browser's `localStorage` or JavaScript cookies is easy, but | ||
you become highly vulnerable to XSS Attacks; | ||
- Storing tokens in a `httpOnly` cookie 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 especially true for systems that have refresh | ||
tokens which are valid for one use only (e.g. ORY Hydra, Auth0, ...). | ||
|
||
## Access Token Scope is not an Access Control Permission | ||
|
||
The OAuth 2.0 Scope **is not 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 is not 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 is not | ||
an administrator, that permission ("access control") is not actually granted to | ||
Bob. Therefore any request by the OAuth 2.0 Client that tries to delete users on | ||
behalf of Bob should fail. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters