class: center, middle # Introduction to OAuth 2.0
and OpenID Connect
Presented By
Michael Herman
@mikeherman
--- ### Day 1 -- ##### (1) Intro (~ 10 minutes) - About Me - Objectives -- ##### (2) Theory (~ 2 hours) - Authentication vs Authorization - OAuth - What is OAuth? - Terminology - Authorization Code flow - Grant types - History of OAuth -- ##### (3) Practice (~ 5 hours) - Developing an OAuth 2.0 Authorization Server with Node --- ### Day 2 -- ##### (1) Theory (~ 1 hour) - Day 1 Review - OpenID Connect - What is OpenID Connect? - How does OpenID Connect work with OAuth 2.0? - JSON Web Tokens (JWT) -- ##### (2) Practice (~ 5 hours) - Adding OpenID Connect to the OAuth 2.0 Server - Developing a Client application with Node and Express -- ##### (3) Theory (~ 1 hour) - Final Review - Next Steps --- class: center, middle ## Intro --- ### About Michael ``` $ whoami michael.herman ```
-- #### Senior Software Engineer from Denver, CO 1. Full-stack + DevOps Contractor 1. [TestDriven.io](https://testdriven.io)
-- #### Also 1. Founder and Organizer of [Denver Node.js Meetup Group](https://www.meetup.com/Node-js-Denver-Boulder/) 1. Former Lead Instructor at [Galvanize](https://www.galvanize.com/) 1. Co-founder/author of [Real Python](https://realpython.com) 1. 😍 - [tech writing/education](http://mherman.org), [open source](http://github.com/mjhea0), [financial models](http://www.starterfinancialmodel.com/), [radiohead](http://radiohead.com/) --- ### Objectives -- By the end of this training, you will be able to: -- 1. Describe the difference between authentication and authorization -- 1. Explain what OAuth 2.0 is and how it differs from OAuth 1.0 -- 1. Describe the various OAuth 2.0 grant types and when it's appropriate to use each -- 1. Implement an OAuth 2.0 server with Node -- 1. Explain what OpenID Connect is and how it works with OAuth 2.0 -- 1. Implement OpenID Connect with Node -- 1. Develop a Client app to interact with an OAuth 2.0 and OpenID Connect server --- class: center, middle ## Theory --- ### Authentication vs Authorization -- *"Who are you and what are you allowed to do?"* -- #### Authentication - Verifying that someone is who they claim to be. - *Who are you?* -- #### Authorization - Verifying which resources a user can access and what they are allowed to do with those resources. - *What are you allowed to do?* -- #### Single Sign-On (SSO) - Allows a user to enter one set of credentials in order to access multiple applications.
--- ### What is OAuth? -- [Oauth](http://oauth.net) is an open standard for authorization. *"An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications."* -- It's all about delegation: -- 1. The *Client* application accesses resources, from a *Resource Server*, on behalf of the *User*. 1. The *User* does not have to share their credentials with the *Client*. --
**Compared to OAuth 1.0, OAuth 2.0:** - Is slightly simpler to implement - Adds time to live (TTL) to the Access Tokens - Supports mobile and desktop apps - No longer requires Client applications to have cryptography --- ### Terminology -- | Term | Definition | |----------------------|---------------------------------------------------------------------------------------------------------------------------------| | Resource Owner (aka User) | End user who authorizes an application to access their account | | Client (aka Consumer) | Application that accesses protected resources on behalf of the user | | Authorization Server | Server which grants Access Tokens after the user authorizes the application | | Resource Server | Restricted resource / API | | Access Token | Token used to access restricted resources | | Authorization Code | Intermediate token returned to the client, after the user authorization step, which the client exchanges it for an Access Token | | Grant | Method of acquiring an Access Token | --- ### Grant Types -- | Grant Type | Use Case | Link | |----------------------------|-----------------------------|----------------------------------------------------------------| | Authorization Code | Server-side web apps | [4.1](https://tools.ietf.org/html/rfc6749#section-4.1) | | Implicit | Single Page Apps (SPAs) | [4.2](https://tools.ietf.org/html/rfc6749#section-4.2) | | Resource Owner Credentials (Password) | Trusted first party clients | [4.3](https://tools.ietf.org/html/rfc6749#section-4.3) | | Client Credentials | Machine-to-machine | [4.4](https://tools.ietf.org/html/rfc6749#section-4.4) | -- #### Questions -- - **Which grant should you use?** [Decision tree](images/oauth-grants.svg) -- - **First vs third party client?** - First party clients are clients that you trust. For example, Twitter *probably* trusts the Twitter iPhone app since they own it. - Third party clients are clients that you don't trust. -- - **Access Token Owner?** Do you not need the user's permission to access the restricted resources? --
Source:
A Guide to OAuth 2.0 Grants
--- ### Authorization Code Flow --
**[Step 1]** *Client* redirects the *Resource Owner* to the *Authorization Server*
--
**[Step 2]** *Resource Owner* grants authorization **[Step 3]** *Authorization Server* redirects the *Resource Owner* back to the *Client* with an *Authorization Code*
--- ### Authorization Code Flow (continued...) -- **[Step 4]** *Client* exchanges *Authorization Code* for *Access Token*
--
**[Step 5]** *Authorization Server* grants *Access Token*
--- ### Authorization Code Flow (continued...) --
**[Step 6]** *Client* uses the *Access Token* to access protected resources, from the *Resource Server*, on behalf of the *Resource Owner*
--
What's different about this flow for the other grant types—Implicit, Resource Owner Credentials, Client Credentials? [Understanding OAuth2](http://www.bubblecode.net/en/2016/01/22/understanding-oauth2/) --- ### History of OAuth -- #### Before OAuth -- The User would provide their credentials directly to the Client app. -- ##### Problems 1. Client stores User's password (one more application with your password) 1. Client gets complete access to the User's account (scope) 1. User cannot revoke access to the Client unless they reset their password -- #### [Oauth 1.0](https://oauth.net/core/1.0/) -- Introduced in December 2007 to prevent the Client application from having to directly handle the User's credentials. -- ##### Problems 1. Difficult to implement 1. Complex cryptographic requirements 1. Poor support for native desktop and mobile apps --- ### History of OAuth (continued...) -- #### [OAuth 2.0](https://oauth.net/2/) First came out in April 2010. -- ##### Problems 1. Still difficult to implement 1. Difficult for the User to update the scope 1. Security concerns --
##### Recommended reads - [OAuth 2.0 and the Road to Hell](https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529) - [OAuth 2 Simplified](https://aaronparecki.com/oauth-2-simplified/) - [Introducing TAuth: Why OAuth 2.0 is bad for banking APIs and how we're fixing it](https://blog.teller.io/2016/04/26/tauth.html) --- ### Check for Understanding -- - What's the difference between authentication and authorization? -- - What is OAuth? -- - Describe the various OAuth 2.0 grant types -- - How does the grant type affect the OAuth 2.0 authorization flow?
🤔 --- class: center, middle ## Practice --- ### What are we building? -- #### Day 1 - We'll build an OAuth 2.0 Authorization Server with Node, Express, and Postgres that uses the Authorization Code grant type.
-- #### Day 2 - We'll add OpenID Connect to the existing server. - Then, we'll create a separate Client application that can authorize against the Authorization Server. -- #### Prerequisites You should: 1. Have [Node](https://nodejs.org/) (v11.12.0), [NPM](https://www.npmjs.com/) (v6.7.0), [Postgres](https://www.postgresql.org/) (v9.6+), and [git](https://git-scm.com/) installed. 1. Be familiar with Javascript syntax and fundamentals. 1. Have a basic understanding of the Unix command line. 1. Be able to build a RESTful API with Node, Express, and Postgres. --- ### Getting Started -- Clone down the [node-oauth-openid](https://github.com/mjhea0/node-oauth-openid) repo and check out the [base](https://github.com/mjhea0/node-oauth-openid-server/releases/tag/base) tag: ```sh $ git clone https://github.com/mjhea0/node-oauth-openid $ git checkout -b base ``` -- Install the dependencies: ```sh $ npm install ``` -- Run the server: ```sh $ npm start ``` Ensure the server is up and running at [http://localhost:3001/](http://localhost:3001/) and [http://localhost:3001/ping](http://localhost:3001/ping). --
Let's review *app.js* together... --- ### Structure -- #### Authorize Endpoints -- `/oauth/authorize` - GET 1. Query params - Grant type, client ID, redirect URI, state 1. Force the user to log in 1. Ensure the client exists 1. Redirect user to the dialog endpoint -- `/oauth/authorize/dialog` - GET 1. Display authorize dialog -- `/oauth/authorize/dialog` - POST 1. If authorized, generate Authorization Code and redirect user to the redirect URI with the Authorization Code and state 1. If not authorized, send back an error --- ### Structure (continued...) -- #### Token Endpoint -- `/oauth/token` - POST 1. Payload - Authorization Code 1. Ensure the Authorization Code has not expired or been consumed 1. Mark Authorization Code as consumed 1. Generate an Access Token (and an optional Refresh Token) 1. Respond via JSON with the Access Token, optional Refresh Token, and how long the Access Token is good for #### User Info Endpoint -- `/oauth/userinfo` - GET 1. Header - Access Token (`Authorization: Bearer
`) 1. Ensure the Authorization Code is valid 1. If valid, send back `true` 1. If not valid, send back `false` --- ### Structure (continued...) -- #### Models -- 1. `user` - user ID, email, client ID 1. `client` - client ID, name, redirect URI 1. `authCode` - code, created at, consumed, user ID 1. `accessToken` - token, created at, expires in, token type (e.g., bearer), user ID, refresh token (optional) -- ### Bearer Token -- [Bearer Tokens](https://oauth.net/2/bearer-tokens/) are *probably* the most popular type of Access Token. They must be unique, nonsequential, and nonguessable. -- [Using Bearer Tokens](https://tools.ietf.org/html/rfc6750#section-2): 1. Authorization Request Header Field: `Authorization: Bearer 4ae6ce68-4c59-4313-94e2-fcc2932cf5ca` 1. Form-Encoded Body Parameter: `Content-Type: application/x-www-form-urlencoded`, `access_token=mF_9.B5f-4.1JqM` 1. URI Query Parameter: `resource?access_token=mF_9.B5f-4.1JqM` --- ### Implementation -- So, we need to implement the following: 1. Models: `user`, `client`, `authCode`, `accessToken` 1. Routes: `/oauth/authorize` (GET), `/oauth/authorize/dialog` (GET and POST), `/oauth/token` (POST), `/oauth/userinfo` (GET) -- >
Let's skip user log in for now and get something working. What else can we punt in order to get a working prototype up and running?
-- Where do we begin? --- ### Homework 1. Finish the Node Authentication Server 1. Read [User Authentication with OAuth 2.0](https://oauth.net/articles/authentication/) and [Understanding OAuth 2.0 and OpenID Connect](https://blog.runscope.com/posts/understanding-oauth-2-and-openid-connect) --- class: center, middle ## Theory --- ### Day 1 Review -- - What's the difference between authentication and authorization? -- - What is OAuth? -- - Describe the various OAuth 2.0 grant types -- - How does the grant type affect the OAuth 2.0 authorization flow?
🤔 --- ### What is OpenID Connect? -- [OpenID Connect](https://openid.net/2014/02/26/the-openid-foundation-launches-the-openid-connect-standard/) (or OIDC), the latest version of OpenID, is a standard for authentication, issued by the [OpenID Foundation](https://openid.net/foundation/) in February 2014. -- #### How does OpenID Connect work with OAuth 2.0? -- - OpenID Connect extends OAuth 2.0, adding an extra layer for handling user authentication. It's a superset of OAuth 2.0. -- - With OpenID Connect, the `token` endpoint returns an ID Token instead of an Access Token. -- - The ID Token is a [JSON Web Token](https://tools.ietf.org/html/rfc7519) that contains information about the authenticated user. --- ### JSON Web Tokens (JWT) -- A JSON Web Token (or JWT) is a JSON-based standard for securely transmitting information. They can signed (JWS) or encrypted (JWE). -- ##### Benefits - **Stateless**: Since tokens contain the required info to verify a user's identity, scaling is easier as you do not have to maintain a session store. - **Single Sign On**: After a token is generated, you can have your users access a variety of resources without having to re-authenticate them. -- ##### Drawbacks - **Cross-site Scripting (XSS) attacks**: Storing tokens in either local or session storage can lead to XSS attacks. Because of this, it's a good idea to store them in a cookie with `httpOnly` and secure flags. -- ##### Recommended reads - [JSON Web Token (JWT)](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html) - [Introduction to JSON Web Tokens](https://jwt.io/introduction/) - [What is the difference between encrypting and signing?](https://stackoverflow.com/questions/454048/what-is-the-difference-between-encrypting-and-signing-in-asymmetric-encryption) --- class: center, middle ## Practice --- ### Adding OpenID #### Steps - Add `scope` to the `/authorize` endpoint -- - Create (via [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken)) then return an ID Token in the `/token` endpoint -- - Modify the `/userinfo` to decode the ID Token and return user info -- #### Questions -- - What are [JWT Claims](https://en.wikipedia.org/wiki/JSON_Web_Token)? -- - Which claims are [required](https://openid.net/specs/openid-connect-core-1_0.html#IDToken)? Which claims should we use? -- #### Security Recommendations - Always use HTTPS! -- - Issue short lived bearer tokens -- - Don't pass bearer token in page URLs --- ### Client Application -- Let's spin up a new Express application to serve as the Client. -- #### Functionality - Display "Authorize" button on page load to `/` -- - On button click, redirect User (with Grant type, client ID, redirect URI, Scope, and State) to the Authorization Server's `/oauth/authorize` endpoint -- - If the User authorization is successful, the User is redirect back to the Client, to the redirect URI, with the Authorization Code and State -- - With the Authorization Code in hand, request Access Token -- - If the Authorization Code is valid, an ID Token is sent back -- - Store the ID token -- - On requests to restricted resources, send the ID Token in the request header --- class: center, middle ## Theory --- ### Final Review -- - What's the difference between authentication and authorization? -- - What is OAuth? -- - Describe the various OAuth 2.0 grant types -- - How does the grant type affect the OAuth 2.0 authorization flow? -- - What is OpenID Connect? -- - How does OpenID connect work with OAuth 2.0? --
🤔 --- ### Next Steps -- ##### Finish the OpenID Connect + OAuth 2.0 server 1. Add Refresh Tokens (since Access Tokens are short-lived) 1. Incorporate Postgres 1. Address any other `TODO`s 1. Review the final code at [node-oauth-openid](https://github.com/mjhea0/node-oauth-openid)
Anything else?
-- ##### Additional Resources 1. [Authentication and Authorization: OpenID vs OAuth2 vs SAML](https://spin.atomicobject.com/2016/05/30/openid-oauth-saml/) 1. [SAML2 vs JWT: Understanding OpenID Connect Part 1](https://medium.com/@robert.broeckelmann/saml2-vs-jwt-understanding-openid-connect-part-1-fffe0d50f953) 1. Libraries: [oauth2orize](https://github.com/jaredhanson/oauth2orize), [oauth2-server](https://www.npmjs.com/package/oauth2-server) -- ##### Contact Info 1. [michael@mherman.org](mailto:michael@mherman.org) 1. [mherman.org](https://mherman.org) 1. [@mikeherman](https://twitter.com/mikeherman) -- ##### Final Questions? ✌️