summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authormokha <mokha@cisco.com>2019-03-21 15:07:56 -0600
committermokha <mokha@cisco.com>2019-03-21 15:07:56 -0600
commite55ac29891ae9725918fb6dc738802dcc220d5df (patch)
tree20375157046c0e0d54e31282ed6ee14fd6abd145 /README.md
parentada04097e7475da88ef43ab04b8c2c4150cf1c21 (diff)
presentation.md -> README.md
Diffstat (limited to 'README.md')
-rw-r--r--README.md688
1 files changed, 688 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d27c32b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,688 @@
+ ,d 88
+ 88 88
+MM88MMM ,adPPYba, 88 ,d8 ,adPPYba, 8b,dPPYba, ,adPPYba,
+ 88 a8" "8a 88 ,a8" a8P_____88 88P' `"8a I8[ ""
+ 88 8b d8 8888[ 8PP""""""" 88 88 `"Y8ba,
+ 88, "8a, ,a8" 88`"Yba, "8b, ,aa 88 88 aa ]8I
+ "Y888 `"YbbdP"' 88 `Y8a `"Ybbd8"' 88 88 `"YbbdP"'
+
+OAuth2 - Token Exchange with mo
+
+
+# Agenda
+
+Why? Then How.
+
+* 1. Authn vs Authz
+* 2. Tokens
+* 3. Roles
+* 4. Protocol Flow
+* 5. Grant Types
+
+
+# Authn vs Authz
+
+* Authentication: to verify the identity of who you are.
+* Authorization: to verify that you should be granted access to a resource or action.
+
+
+# Authn vs Authz
+
+Example 1: Flying on a plane
+
+* passport: authentiation
+* plane ticket: authorization
+
+
+# Authn vs Authz
+
+Example 2: Riding the bus
+
+A transit token authorizes you to ride the bus for 90 minutes.
+Proof of identity is not required.
+
+```text
+ +------------------------------+
+ | transit ticket |
+ | |
+ | |
+ | |
+ | expires: 90 minutes |
+ +------------------------------+
+```
+
+
+# Authn vs Authz
+
+Transferring the token to someone else, authorizes them to ride the bus for 90 minutes.
+You're not supposed to transfer your transit token but detection is difficult.
+
+```text
+ +------------------------------+
+ | transit ticket |
+ | |
+ | |
+ | |
+ | expires: 90 minutes |
+ +------------------------------+
+```
+
+
+# Tokens - Types
+
+* Access Token: Used to access a resource.
+* Refresh Token: Exchanged for a new access/refresh token.
+
+
+# Tokens - Access Token
+
+The purpose of the access token is to allow clients to access a
+protected resource scoped to the privileges defined by the token and
+scope.
+
+The `access token` represents a subject, audience, issuer and expiration.
+
+```text
+ +------------------------------+
+ | transit ticket |
+ | |
+ | |
+ | |
+ | expires: 90 minutes |
+ +------------------------------+
+```
+
+
+# Tokens - Access Token
+
+Subject: Ticket bearer
+Audience: Bus Driver
+Issuer: Calgary Transit
+Expiration: 90 minutes from when the ticket was purchased.
+
+```text
+ +------------------------------+
+ | transit ticket |
+ | |
+ | |
+ | |
+ | expires: 90 minutes |
+ +------------------------------+
+```
+
+
+# Tokens - Stateful vs Stateless
+
+Stateful: A stateful token is one where the token
+needs to be looked up in a database to honour it.
+
+Stateless: A stateless token has all the information
+encoded in the token.
+
+
+# Tokens - Stateful
+
+Example: Concert ticket
+
+When you enter a concert venue and you are asked to present your ticket.
+They will likely scan your ticket to verify that the ticket is legit.
+The scan will need to verify that the ticket is in a database.
+
+```text
+ +------------------------------+
+ | KRS-ONE |
+ | |
+ | |
+ | |
+ | |
+ | |XXXX|XXXX|XXXX|XXXX| |
+ +------------------------------+
+```
+
+
+# Tokens - Stateless
+
+Example: Calgary Transit Ticket
+
+When you board a bus in Calgary, you must show the driver the ticket.
+All the data the driver needs to admit you is in the ticket itself.
+
+```text
+ +------------------------------+
+ | transit ticket |
+ | |
+ | |
+ | |
+ | expires: 90 minutes |
+ +------------------------------+
+```
+
+
+# Tokens - JWT
+
+JSON web tokens allow us to create stateless
+tokens that encode the necessary information into the token.
+
+```text
+{header}.{body}.{signature}
+```
+
+
+# Tokens - JWT
+
+Example Token
+
+```text
+{header}.{body}.{signature}
+```
+
+```text
+eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE1NTMyMDYx<snip>.BrWtDArYiut47Oo76UTD<snip>
+```
+
+
+# Tokens - JWT
+
+JSON Web Signature
+
+```json
+{
+ "alg": "RS256"
+}
+```
+
+JWT Claims
+```json
+{
+ "exp": 1553206143,
+ "iat": 1553119743,
+ "iss": "https://shiro.test/metadata",
+ "nbf": 1553119743,
+ "jti": "30ee4f06-3e2b-4ef4-961e-5a1dfd530ca5",
+ "sub": "d98ecc05-eab8-4683-8288-249312d3f592",
+}
+```
+
+
+# Tokens - Refresh Token
+
+An `access token` can expire. When an `access token` expires a
+client can exchange a `refresh token` to gain a new `access token`
+and `refresh token`.
+
+The purpose of the `refresh token` is to allow a client to get a new
+`access token` and `refresh token` pair. Once a `refresh token` is used
+it cannot be re-used.
+
+```text
+ +------------------------------+
+ | Credit Card |
+ | |
+ | XXXX-XXXX-XXXX-XXXX |
+ | |
+ | expires: 2024-01 |
+ +------------------------------+
+```
+
+
+# Roles - OAuth 2.0
+
+* Client: Your service, web app, SPA, mobile app.
+* Resource Owner: The HUMAN!
+* Resource Server: The Api
+* Authorization Server: The OAuth 2.0 server.
+
+
+# Protocol Flow
+
+OAuth 2 is a delegation protocol. The `client` does not know the
+credentials of the `resource owner` but can access resources on it's
+behalf.
+
+```text
+ +--------+ +---------------+
+ | |--(A)- Authorization Request ->| Resource |
+ | | | Owner |
+ | |<-(B)-- Authorization Grant ---| |
+ | | +---------------+
+ | |
+ | | +---------------+
+ | |--(C)-- Authorization Grant -->| Authorization |
+ | Client | | Server |
+ | |<-(D)----- Access Token -------| |
+ | | +---------------+
+ | |
+ | | +---------------+
+ | |--(E)----- Access Token ------>| Resource |
+ | | | Server |
+ | |<-(F)--- Protected Resource ---| |
+ +--------+ +---------------+
+```
+
+
+# Protocol Flow
+
+OAuth 2 is a delegation protocol. The `client` does not know the
+credentials of the `resource owner` but can access resources on it's
+behalf.
+
+```text
+ +--------+ +---------------+
+ | |--(A)- Authorization Request ->| |
+ | | | HUMAN |
+ | |<-(B)-- Authorization Grant ---| |
+ | | +---------------+
+ | |
+ | | +---------------+
+ | |--(C)-- Authorization Grant -->| |
+ | my app | | auth.amp.* |
+ | |<-(D)----- Access Token -------| |
+ | | +---------------+
+ | |
+ | | +---------------+
+ | |--(E)----- Access Token ------>| |
+ | | | api.amp.* |
+ | |<-(F)--- Protected Resource ---| |
+ +--------+ +---------------+
+```
+
+
+# Protocol Flow
+
+Short circuit for SAML service providers.
+
+```text
+ +--------+ +---------------+
+ | | | |
+ | | | HUMAN |
+ | | -- | |
+ | | | +---------------+
+ | | (A) SAML Authentication |
+ | | | +---------------+
+ | | -->| |
+ | my app | | auth.amp.* |
+ | |<-(B)----- Access Token -------| |
+ | | +---------------+
+ | |
+ | | +---------------+
+ | |--(C)----- Access Token ------>| |
+ | | | api.amp.* |
+ | |<-(D)--- Protected Resource ---| |
+ +--------+ +---------------+
+```
+
+
+# Protocol Flow
+
+```text
+ +--------+ +---------------+
+ | |--(A)------- Authorization Grant --------->| |
+ | | | |
+ | |<-(B)----------- Access Token -------------| |
+ | | & Refresh Token | |
+ | | | |
+ | | +----------+ | |
+ | |--(C)---- Access Token ---->| | | |
+ | | | | | |
+ | |<-(D)- Protected Resource --| Resource | | Authorization |
+ | Client | | Server | | Server |
+ | |--(E)---- Access Token ---->| | | |
+ | | | | | |
+ | |<-(F)- Invalid Token Error -| | | |
+ | | +----------+ | |
+ | | | |
+ | |--(G)----------- Refresh Token ----------->| |
+ | | | |
+ | |<-(H)----------- Access Token -------------| |
+ +--------+ & Optional Refresh Token +---------------+
+```
+
+
+# Grant Types
+
+* Authorization Code: for web apps
+* Implicit: for single page apps.
+* Password Credentials: for trusted clients.
+* Client Credentials: for service authentication.
+* Refresh: for exchanging a refresh token for an access token.
+* Extensions: saml bearer, jwt bearer
+
+
+# Grant Types - Authorization Code
+
+For server based applications where a `client id` and `client secret`
+can be stored securely.
+
+This uses a redirect flow that depends on the user agent having access
+to both the authorization server and the client web app.
+
+
+# Grant Types - Authorization Code
+
+```text
+ +----------+
+ | Resource |
+ | Owner |
+ | |
+ +----------+
+ ^
+ |
+ (B)
+ +----|-----+ Client Identifier +---------------+
+ | -+----(A)-- & Redirection URI ---->| |
+ | User- | | Authorization |
+ | Agent -+----(B)-- User authenticates --->| Server |
+ | | | |
+ | -+----(C)-- Authorization Code ---<| |
+ +-|----|---+ +---------------+
+ | | ^ v
+ (A) (C) | |
+ | | | |
+ ^ v | |
+ +---------+ | |
+ | |>---(D)-- Authorization Code ---------' |
+ | Client | & Redirection URI |
+ | | |
+ | |<---(E)----- Access Token -------------------'
+ +---------+ (w/ Optional Refresh Token)
+```
+
+
+# Grant Types - Authorization Code
+
+```text
+https://www.example.com/oauth/authorize
+ ?response_type=code
+ &client_id=client_id
+ &redirect_uri=https://www.example.org/oauth/callback
+ &scope='read:scim.me write:scim.me'
+```
+
+```text
+ -----------------
+ Login
+
+ username: xxxxxxx
+ password: xxxxxx
+
+ [login]
+ -----------------
+```
+
+
+# Grant Types - Authorization Code
+
+```text
+ ----------------------------------------------------
+`client X` would like the following scopes:
+
+ read your profile information (read:scim.me)
+ write your profile information (write:scim.me)
+
+ [okay]
+
+ ----------------------------------------------------
+```
+
+```text
+https://www.example.org/oauth/callback
+ ?grant_type=authorization_code
+ &code=secret
+```
+
+
+# Grant Types - Authorization Code
+
+```text
+ +--------+ +---------------+
+ | |--(A)------- Authorization Grant --------->| |
+ | | | |
+ | |<-(B)----------- Access Token -------------| |
+ | | & Refresh Token | |
+ | | | |
+ | | +----------+ | |
+ | | | | | |
+ | | | | | |
+ | | | Resource | | Authorization |
+ | Client | | Server | | Server |
+ | | | | | |
+ | | | | | |
+ | | | | | |
+ | | +----------+ | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ +--------+ +---------------+
+```
+
+
+# Grant Types - Authorization Code
+
+```bash
+$ curl https://www.example.com/oauth/tokens \
+ -X POST \
+ -d '{"grant_type":"authorization_code","code":"secret"}' \
+ -H "Accept: application/json" \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Basic base64(client_id:client_secret)"
+```
+
+```text
+200 OK
+
+Cache-Control: private, no-store
+Pragma: no-cache
+Content-Type: application/json; charset=utf-8
+```
+```json
+{
+ "access_token": "eyJhbGciOiJSUzI1NiJ9",
+ "token_type": "Bearer",
+ "expires_in": 3600,
+ "refresh_token": "eyJleHAiOjE1NDA5M"
+}
+```
+
+
+# Grant Types - Refresh Token
+
+This grant can be used by a client to exchange a
+`refresh token` for a new `access token` and `refresh token`.
+
+```text
+ +--------+ +---------------+
+ | |--(A)------- Authorization Grant --------->| |
+ | | | |
+ | |<-(B)----------- Access Token -------------| |
+ | | & Refresh Token | |
+ | | | |
+ | | +----------+ | |
+ | |--(C)---- Access Token ---->| | | |
+ | | | | | |
+ | |<-(D)- Protected Resource --| Resource | | Authorization |
+ | Client | | Server | | Server |
+ | |--(E)---- Access Token ---->| | | |
+ | | | | | |
+ | |<-(F)- Invalid Token Error -| | | |
+ | | +----------+ | |
+ | | | |
+ | |--(G)----------- Refresh Token ----------->| |
+ | | | |
+ | |<-(H)----------- Access Token -------------| |
+ +--------+ & Optional Refresh Token +---------------+
+```
+
+
+# Grant Types - Refresh Token
+```text
+POST /token HTTP/1.1
+Authorization: Basic base64(client_id:client_secret)
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
+```
+
+Response:
+
+```text
+HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Cache-Control: no-store
+Pragma: no-cache
+
+{
+ "access_token":"2YotnFZFEjr1zCsicMWpAA",
+ "token_type":"bearer",
+ "expires_in":3600,
+ "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
+}
+```
+
+
+# Protocol Flow - Accessing a Protected Resource
+
+```text
+GET /api/policies/
+Authorization: Bearer eyJhbGciOiJSUzI1NiJ9
+Accept: application/json
+Content-Type: application/json
+
+HTTP/1.1 200 OK
+Content-Type: application/json
+
+[
+ { "name": "Audit" },
+ { "name": "Protect" },
+]
+```
+
+
+# Moonwalk to this!
+
+```text
+ _,.-"T
+ _.--{~ :l
+ c" `. :I
+ | .-"~-.\ l .--.
+ | Y_r--. Y) ___I ,-"(~\ Y
+ |[__L__/ j"~=__]~_~\." _/
+ ___| \.__.r--<~__.T T/ "~/
+'--cl___/\ ( () ).,_L_]}--{
+ `--' `-^--^\ /___"(~\ Y
+ "~7/ \ " `/
+ // //]--[
+ /> oX |: L
+ // / `| o\
+ //. / I [
+ / \]/ l: |
+ Y.// `|_I
+ I_Z L :]
+ /".-7 [n]l
+ Y / / I //
+ |] / /]"/
+ L:/ //./
+ [_7 _ // /
+ _ ,-="_"^K_/
+ [ ][.-~" ~"-.]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+
+# Examples - Quick & Dirty
+
+```ruby
+namespace :token do
+ desc 'register a new service access/refresh token'
+ task :register, [:token] => [:environment] do |task, args|
+ require 'register_token'
+ puts RegisterToken.new.run(service: :shiro, token: args[:token]).inspect
+ end
+
+ desc 'exchange refresh token for a new access token'
+ task renew: [:environment] do
+ refresh_token = Token.refresh.active.order(created_at: :desc).first
+ refresh_token&.exchange!
+ end
+end
+```
+
+
+# Examples - Quick & Dirty
+
+```ruby
+class Token < ApplicationRecord
+ def exchange!(client: token_exchange_client)
+ response = client.exchange(value)
+ transaction do
+ destroy!
+ Token.create!(
+ service: service,
+ token_type: :access,
+ expires_at: response[:expires_in].to_i.seconds.from_now,
+ value: response[:access_token]
+ )
+ Token.create!(
+ service: service,
+ token_type: :refresh,
+ expires_at: response[:expires_in].to_i.seconds.from_now,
+ value: response[:refresh_token]
+ )
+ end
+ end
+end
+```
+
+
+# AWS Secrets Manager
+
+> You can customize Lambda functions to extend Secrets Manager rotation to
+> other secret types, such as API keys and OAuth tokens used to authenticate users to mobile applications.
+- https://aws.amazon.com/secrets-manager/
+
+
+# Conclusion
+
+An `access token` decouples a resource owners credentials from the
+authorization that it is delegating to a client to access protected
+resources from a resource server. A `refresh token` can be used by a
+client to gain a new `access token` and `refresh token`.
+
+The exchange process can be triggered when an `access token` expires or
+is revoked.
+
+```text
+ +--------+ +---------------+
+ | |--(A)------- Authorization Grant --------->| |
+ | | | |
+ | |<-(B)----------- Access Token -------------| |
+ | | & Refresh Token | |
+ | | | |
+ | | +----------+ | |
+ | |--(C)---- Access Token ---->| | | |
+ | | | | | |
+ | |<-(D)- Protected Resource --| Resource | | Authorization |
+ | Client | | Server | | Server |
+ | |--(E)---- Access Token ---->| | | |
+ | | | | | |
+ | |<-(F)- Invalid Token Error -| | | |
+ | | +----------+ | |
+ | | | |
+ | |--(G)----------- Refresh Token ----------->| |
+ | | | |
+ | |<-(H)----------- Access Token -------------| |
+ +--------+ & Optional Refresh Token +---------------+
+```
+
+
+# Thanks
+
+References:
+
+* https://auth.amp.cisco.com/doc
+* https://aws.amazon.com/secrets-manager/
+* https://jwt.io/
+* https://tools.ietf.org/html/rfc6749
+* https://tools.ietf.org/html/rfc7515
+* https://tools.ietf.org/html/rfc7519
+* https://tools.ietf.org/html/rfc7522