A detailed intro to OAuth
Originally posted as part of Node workshop
A lot of the services and social media apps we love and use (Google, Facebook, Twitter, Spotify, ...) uses some form of OAuth.
💡 While OAuth1 is still used by some, the current industry standard is OAuth2. Even though some mechanisms, features, and standards changed from OAuth1 to 2, the underlying goal remains, which is to allow an app to integrate with a 3rd party authentication provider on user's behalf
Why the switch from OAuth1 to OAuth2? ↔️
-
OAuth1 has a complicated signature system that required some cryptography:
- a shared secret to ensure only the registered client can use the tokens
- each request has to be signed with the secret
- complex state management for temporary and long-lasting tokens
-
OAuth2 doesn't require signatures:
- no more signatures, but relies on HTTPS to handle authenticity
- more stateless than OAuth1, thanks to bearer tokens
- less secure, since anyone with the token can use it
- mitigate by: short-lived access tokens and long-lived refresh tokens
OAuth - the Authorization part 🔐
OAuth is really an Authorization framework but is often used to build an authentication system. Here are the use cases for each group.
As a user
OAuth allows you to "Login with Facebook", "Sign in with Google", and continue to the app you wanted to use.
As an app developer
OAuth allows apps to rely on 3rd party providers (Facebook, Google, Twitter, etc) for authentication, so devs:
- don't have to implement their own Authentication system
- can integrate all the goodies that the Provider has
As a 3rd party Authentication Provider
Facebook, Google, Twitter implements their own authentication system (username+password auth, etc). They provide API for apps to:
- have a way for user to sign-in via their auth
- access user data in their platform; apps can CRUD user's profile, friends, likes, playlists, apps, tweets, etc
How does it look like in practice? 🔧
An app (as an Auth Client), can get access to all user's stuff on Provider, as long as the user "authorizes" the app
Here, you see a prompt asking a user, to authorize an app to use their account information, log-in to the app with user's info, and make requests (read, write) to Auth Provider on user's behalf.
Definition of terms 📒
Let's get the authentication-specific language out of the way first!
app
As a dev, you are writing this app to integrate with a Provider
Auth / Identity Provider (aka Provider)
The service that you want to integrate in your app, aka the 3rd party auth provider: Google, Facebook, Spotify, Twitter, etc
App can make requests to the provider either with or without a user:
- on user's behalf - (e.g. see user's friends, play user's playlist) as long as app gained authorization
- without a user - (e.g. search a song, see latest tweets on a topic) that are not really tied to a user
The different flows accommodate either of these two scenarios in different ways
access token
- aka "Bearer token"
- You need this to send requests to the provider
- All flows result to the app getting an
access token
but they all have different ways to get there
scopes
- What operations does the app have permission to do on behalf of user
- e.g. in Spotify, there are
user-library-read
,user-read-playback-state
Implementing OAuth2
Creating an app on Provider's dev site
For any of these flows, you need to register an account on the Provider's developer site and Create an App.
You usually supply:
- App name
- App description
- Redirect uri, aka callback: you must whitelist your URL here, which should be the same URL that you'll give to the first step of Auth Code Flow. Provider redirects to this URL after successful user auth.
You usually get these app credentials to connect with Provider and get an access token
- Client ID
- Client secret
OAuth2 flows
A Provider usually offers one or more of these flows:
- Authorization Code
- Client credentials
- Password Grant
- Implicit grant
- others...
Authorization Code
- aka 3-legged (app + provider + user = 3)
- A user is needed. Authentication and authorization in the context of the user
- TL;DR: App directs user to Provider login. Provider redirects to app passing an authorization code, which app exchanges for an access token
-
App provides a link/button with an authorization URL that directs user's browser to the Provider's authentication and authorization page
- scope can be provided here
- In some providers, there is a separate request to get this authorization URL
-
User successfully logs in and authorizes your app to access their data (see authorization prompt screenshots aboce)
- Provider redirects to the redirect uri you supplied when you created the app, giving your app an authorization code specific to that user
-
App sends a request to exchange the authorization code for an access token. Response payload usually contains:
access token
- app sends this along every request to providerrefresh token
- used to "renew" token- scope - reflects scope passed before
- expiry - of access token
- type: usually "Bearer"
-
App sends requests to Provider, attaching the
access token
in an Authorization headerAuthorization: Bearer my_access_token
- When access token expires, app sends a refresh request, sending the
refresh token
to get a newaccess token
. Same response payload as in #3
Client Credentials
- aka 2-legged (app + provider = 2)
- No user involved. Authentication and authorization in the context of the app
- TL;DR: App exchanges app credentials (
client id
andclient secret
) with anaccess token
- This is what we used in Chapter 7 when we searched songs
Password Grant
- TL; DR: app collects user's credentials (username, password) e.g. by a form, then exchanges them with an
access token
Implicit grant
- TL;DR: App directs user to Provider to login. Provider redirects to app giving
access token
Example app with Spotify API and Authorization code flow
Create app in Provider
Log in to Spotify for Developers and create an app.
Code
https://github.com/lenmorld/node_workshop/compare/appendix_baseline...appendix_oauth
This example is based off a Node-express server developed as part of Node workshop
Make sure to add these to your .env
file
(or alternatively, hard-code it on the routes/auth2/index.js
for less hassle) 😅
# OAuth2 Auth Code flow
SPOTIFY_CLIENT_ID=your_spotify_app_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_app_client_secret
To try code:
$ npm start
- on your browser go to http://localhost:4000/auth2