Skip to content

Commit

Permalink
docs: add section on oauth2 limitations at beginning
Browse files Browse the repository at this point in the history
  • Loading branch information
aeneasr committed Aug 2, 2020
1 parent 1208827 commit 4254363
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 27 deletions.
133 changes: 133 additions & 0 deletions docs/docs/concepts/before-oauth2.mdx
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.
30 changes: 3 additions & 27 deletions docs/docs/concepts/oauth2.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -108,24 +108,10 @@ A typical OAuth 2.0 flow looks as follows:

### OAuth 2.0 Scope

:::info

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.
:::note

:::
Please read the section about OAuth2 Scope in
[Read this before learning OAuth2 / OpenID Connect](./before-oauth2.mdx).

A second important concept is the OAuth 2.0 Scope. Many people confuse OAuth 2.0
Scope with internal Access Control like for example Role Based Access Control
Expand All @@ -147,16 +133,6 @@ documents"). The OAuth Access Token with those scopes wouldn't help the external
application read those documents because it can only act in the name of the
user, and that user doesn't have these access privileges.

To recap, ORY Hydra's primary feature is implementing the OAuth 2.0 and OpenID
Connect spec, as well as related specs by the IETF and OpenID Foundation.

The next sections explain how to connect your existing user management (user
login, registration, logout, ...) with ORY Hydra in order to become an OAuth 2.0
and OpenID Connect provider like Google, Dropbox, or Facebook.

Again, please be aware that you must know how OAuth 2.0 and OpenID Connect work.
This documentation will not teach you how these protocols work.

The scope of an OAuth 2.0 scope defines the permission the token was granted by
the end-user. For example, a specific token might be allowed to access public
pictures, but not private ones. The granted permissions are established during
Expand Down
1 change: 1 addition & 0 deletions docs/sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
"install",
],
Concepts: [
"concepts/before-oauth2",
"concepts/oauth2",
"concepts/openid-connect-oidc",
"concepts/login",
Expand Down

0 comments on commit 4254363

Please sign in to comment.