REST API Security: OAuth 2.0, JWTs, and More!

69
REST API Security Les Hazlewood @lhazlewood PMC Chair, Apache Shiro Expert Group Member, JEE Application Security (JSR-375) Founder & CTO, Stormpath

Transcript of REST API Security: OAuth 2.0, JWTs, and More!

Page 1: REST API Security: OAuth 2.0, JWTs, and More!

REST API Security

Les Hazlewood @lhazlewoodPMC Chair, Apache ShiroExpert Group Member, JEE Application Security (JSR-375)Founder & CTO, Stormpath

Page 2: REST API Security: OAuth 2.0, JWTs, and More!

About Stormpath• User Management API for Developers• Password security • Authentication and Authorization• Multi Tenancy• MFA, SAML, OAuth2• LDAP & Active Directory Cloud Sync• Instant-on, scalable, and highly available• Free for developers

...

Page 3: REST API Security: OAuth 2.0, JWTs, and More!

Overview

• HTTP Authentication

• HTTP Authentication Schemes Comparison

• API Key Authentication

• Token Authentication

• Authorization

Page 4: REST API Security: OAuth 2.0, JWTs, and More!

REST API Focus

• Eliminate server state

• Secure user credentials

• Secure server endpoints

• Expose access control rules

• SPAs and Mobile: ‘Untrusted Clients’

Page 5: REST API Security: OAuth 2.0, JWTs, and More!

HTTP(S) Authentication & Authorization

Page 6: REST API Security: OAuth 2.0, JWTs, and More!

Authentication

Proving you are who you say you are.

Page 7: REST API Security: OAuth 2.0, JWTs, and More!

Authorization

Ensuring someone is allowed to do what they are trying to do.

Page 8: REST API Security: OAuth 2.0, JWTs, and More!

HTTP Authentication & Authorization

• Authorization header

• No Custom Headers!• Stay spec-standard• No pre-flight CORS requests (browsers) req’d• Custom schemes easily supported

Page 9: REST API Security: OAuth 2.0, JWTs, and More!

Authorization header

How does it work?

Page 10: REST API Security: OAuth 2.0, JWTs, and More!

Authorization header

How does it work?

Challenge Response protocol

Page 11: REST API Security: OAuth 2.0, JWTs, and More!

1. Request

GET /admin HTTP/1.1

Page 12: REST API Security: OAuth 2.0, JWTs, and More!

2. Challenge

HTTP/1.1 401 UnauthorizedWWW-Authenticate: scheme-name <stuff>

*multiple schemes allowed, typically set as multiple WWW-Authenticate headers

Page 13: REST API Security: OAuth 2.0, JWTs, and More!

3. Re-Request

GET /admin HTTP/1.1Authorization: scheme-name <stuff>

Page 14: REST API Security: OAuth 2.0, JWTs, and More!

Example: HTTP Basic Authentication

Page 15: REST API Security: OAuth 2.0, JWTs, and More!

1. Request (Basic)

GET /admin HTTP/1.1

Page 16: REST API Security: OAuth 2.0, JWTs, and More!

2. Challenge (Basic)

HTTP/1.1 401 UnauthorizedWWW-Authenticate: Basic realm=“MyApp”

Page 17: REST API Security: OAuth 2.0, JWTs, and More!

3. Re-Request (Basic)

GET /admin HTTP/1.1Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Page 18: REST API Security: OAuth 2.0, JWTs, and More!

Schemes

• Basic• Digest Schemes (OAuth 1.0a)• Bearer Token Schemes (OAuth2)• Custom

Page 19: REST API Security: OAuth 2.0, JWTs, and More!

HTTP Basic

Page 20: REST API Security: OAuth 2.0, JWTs, and More!

HTTP Basic

String value = username + ‘:’ + raw_passwordString schemeValue = base64_encode(value)

...

GET /admin HTTP/1.1Authorization: Basic schemeValue

Page 21: REST API Security: OAuth 2.0, JWTs, and More!

HTTP Basic

Pros:• Very easy to use• Supported by everything

Cons:• Raw password always transmitted• Easy to leak raw password if not careful (logging)• Susceptible to Man-In-The-Middle attacks• HTTPS *always* required• Client must constantly retain/reference the raw password (server clients

usually ok, browser clients not ok)

Page 22: REST API Security: OAuth 2.0, JWTs, and More!

Digest Schemes

Page 23: REST API Security: OAuth 2.0, JWTs, and More!

Digest Schemes: Client

request.headers[‘Client-Id’] = getMyId()

String digest = hmacSha256(request, password)

request.headers[‘Authorization’] = ‘Foo ‘ + digest

send(request)

Page 24: REST API Security: OAuth 2.0, JWTs, and More!

Digest Schemes: Server

String clientId = request.headers[‘Client-Id’]byte[] password = lookupPassword(clientId);

String serverComputedDigest = hmacSha256(request, password)

String val = request.headers[‘Authorization’]String clientSpecifiedDigest = val.remove(‘Foo ‘)

if (clientSpecifiedDigest != serverComputedDigest) { sendError(401, response) return}

//otherwise request is authenticated

Page 25: REST API Security: OAuth 2.0, JWTs, and More!

Digest Schemes: OAuth 1.0a example

Authorization: OAuth realm="http://sp.example.com/", oauth_consumer_key="0685bd9184jfhq22”, oauth_token="ad180jjd733klru7", oauth_signature_method="HMAC-SHA1", oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D", oauth_timestamp="137131200", oauth_nonce="4572616e48616d6d65724c61686176”

Page 26: REST API Security: OAuth 2.0, JWTs, and More!

Digest Schemes

Pros:• Probably most secure• Password never sent over the wire• HTTPS not required (but your data may still require HTTPS)• Can guarantee end-to-end HTTP message authenticity

(HTTPS cannot do this)• Not susceptible to Man-In-The-Middle attacks

Cons:• Very difficult to design safely• Difficult to understand and use• Difficult to implement libraries• Client needs to retain a constant reference to the password

(server clients usually ok, browser clients maybe not?)

Page 27: REST API Security: OAuth 2.0, JWTs, and More!

Bearer Token Schemes

Page 28: REST API Security: OAuth 2.0, JWTs, and More!

Bearer Token Schemes

Authorization: Bearer opaque-token

Page 29: REST API Security: OAuth 2.0, JWTs, and More!

Bearer Token Schemes

opaque-token can be whatever you want*

Page 30: REST API Security: OAuth 2.0, JWTs, and More!

Bearer Token Schemes

opaque-token can be whatever you want*

*should always be cryptographically-signed and expire

Page 31: REST API Security: OAuth 2.0, JWTs, and More!

Bearer Token Schemes: OAuth 2 Example

Authorization: Bearer eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-92K27uhbUJU1p1r_wW1gFWFOEjXk

Page 32: REST API Security: OAuth 2.0, JWTs, and More!

Bearer Token Schemes

Pros:• Easier to use than digest• De-facto standard token format (JWT)• Can contain state – no server sessions needed• Does not require constant access to the user password

Cons:• HTTPS always required, during and always after login (not a big deal nowadays)• Cannot guarantee end-to-end HTTP message authenticity (like digest schemes can)• Susceptible to Man-In-The-Middle attacks• Token creation and renewal workflows can be very complicated and confusing depending on use case

(OAuth2 confuses many people).• When used for Browser or Mobile, additional security still required (Origin checks, CSRF-protection, etc)• Token content is not standard – applications can open themselves to attack

Page 33: REST API Security: OAuth 2.0, JWTs, and More!

Custom Scheme

Page 34: REST API Security: OAuth 2.0, JWTs, and More!

Custom Scheme

• Only if you really, Really, REALLY know what you’re doing.

Seriously.

No, rly. Srsly.

• Non-standard, so you essentially must provide your own client libraries.

Page 35: REST API Security: OAuth 2.0, JWTs, and More!

Custom Scheme

• Stormpath has a custom SAUTHC1 digest scheme• Authenticates the entire HTTP Message, including the Body (OAuth 1.0a does not)• Uses nonces to prevent replay attacks• Uses key derivation algorithms and HMAC-SHA-256• We use it for our own SDKs*• If you’re curious:

https://github.com/stormpath

(search for ‘sauthc1’ in any stormpath-sdk-* project)

*Basic still supported for non-SDK clients or ‘weird’ environments

Page 36: REST API Security: OAuth 2.0, JWTs, and More!

API Key Authentication

Page 37: REST API Security: OAuth 2.0, JWTs, and More!

API Key Example

ID : YLNVXG091ZO1BSANZ5U6DCTIXSecret: ZediwUeDCNl13ldjaFKFQzz0eD13PO931DLAopdeywixaeUAhsip+92iaY

Page 38: REST API Security: OAuth 2.0, JWTs, and More!

API Keys

• Entropy• Password Independent• Scope• Speed• Limited Exposure• Traceability

Page 39: REST API Security: OAuth 2.0, JWTs, and More!

API Keys

• Can be thought of as a really long username and password pair.

• Can be used with any HTTP Authentication Scheme that accepts a username and password: Basic, Digest, OAuth2, etc.

• Almost exclusively used for server-to-server communication.

• Never embed API Key secrets in untrusted clients like JavaScript or mobile applications.

Page 40: REST API Security: OAuth 2.0, JWTs, and More!

HTTP Basic with API Key

String value = apiKeyId + ‘:’ + apiKeySecretString schemeValue = base64_encode(value)

...

GET /admin HTTP/1.1Authorization: Basic schemeValue

Page 41: REST API Security: OAuth 2.0, JWTs, and More!

Token Authentication

Page 42: REST API Security: OAuth 2.0, JWTs, and More!

Why not just use Session IDs?

Page 43: REST API Security: OAuth 2.0, JWTs, and More!

Session ID Problems

• They’re opaque and have no meaning themselves (they’re just ‘pointers’).

• Service-oriented architectures might need a centralized ID de-referencing service

Page 44: REST API Security: OAuth 2.0, JWTs, and More!

Session ID Problems

• Opaque IDs mean clients can’t inspect them and find out what it is allowed to do or not - it needs to make more requests for this information.

• Susceptible to CSRF attacks

Page 45: REST API Security: OAuth 2.0, JWTs, and More!

Session ID Problems

• Sessions = Server State!• You need to store that state somewhere• Session ID look up server state on *every request*.• Really not good for distributed/clustered apps• Really not good for scale

Page 46: REST API Security: OAuth 2.0, JWTs, and More!

Token Authentication to the rescue!

Page 47: REST API Security: OAuth 2.0, JWTs, and More!

How do you get a Token?

Page 48: REST API Security: OAuth 2.0, JWTs, and More!

Example: your SPA, your server

Page 49: REST API Security: OAuth 2.0, JWTs, and More!

1. Token Request

POST /token HTTP/1.1Origin: https://foo.comContent-Type: application/x-www-form-urlencoded

grant_type=password&username=username&password=password

*Assert allowed origin for browser-based apps

Page 50: REST API Security: OAuth 2.0, JWTs, and More!

2. Token Response

HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8Cache-Control: no-storePragma: no-cache

{ "access_token":"2YotnFZFEjr1zCsicMWpAA", “token_type":"example", “expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter":"example_value”}

Page 51: REST API Security: OAuth 2.0, JWTs, and More!

3. Resource Request

GET /admin HTTP/1.1Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA

Page 52: REST API Security: OAuth 2.0, JWTs, and More!

Example: Token Request using an API Key

POST /token HTTP/1.1Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=apiKeyId&client_secret=apiKeySecret

*Assert allowed origin for browser-based apps

Page 53: REST API Security: OAuth 2.0, JWTs, and More!

How does the server create a Token?

Page 54: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)

• A URL-safe, compact, self-contained string with meaningful information that is usually digitally signed or encrypted.

• The string is ‘opaque’ and can be used as a ‘token’.

• Many OAuth2 implementations use JWTs as OAuth2 Access Tokens.

Page 55: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)

• You can store them in cookies! But all those cookie security rules still apply (CSRF protection, etc).

• You can entirely replace your session ID with a JWT.

Page 56: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)

In the wild they look like just another ugly string:

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVPmB92K27uhbUJU1p1r_wW1gFWFOEjXk

Page 57: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)

But they do have a three part structure. Each part is a Base64Url-encoded string:

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVPmB92K27uhbUJU1p1r_wW1gFWFOEjXk

Header

Body (‘Claims’)

Cryptographic Signature

Page 58: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)Base64Url-decode the parts to find the juicy bits:

{ "typ":"JWT", "alg":"HS256"}

{ "iss”:”http://trustyapp.com/”, "exp": 1300819380, “sub”: ”users/8983462”, “scope”: “self api/buy”}

tß´—™à%O˜v+nî…SZu¯µ€U…8H×

Header

Body (‘Claims’)

Cryptographic Signature

Page 59: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)The claims body is the best part! It can tell:{

"iss”:”http://trustyapp.com/”,

"exp": 1300819380,

“sub”: ”users/8983462”,

“scope”: “self api/buy”

}

Who issued the token

Page 60: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)The claims body is the best part! It can tell:{

"iss”:”http://trustyapp.com/”,

"exp": 1300819380,

“sub”: ”users/8983462”,

“scope”: “self api/buy”

}

Who issued the token

When it expires

Page 61: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)The claims body is the best part! It can tell:{

"iss”:”http://trustyapp.com/”,

"exp": 1300819380,

“sub”: ”users/8983462”,

“scope”: “self api/buy”

}

Who issued the token

When it expires

Who it represents

Page 62: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)The claims body is the best part! It can tell:{

"iss”:”http://trustyapp.com/”,

"exp": 1300819380,

“sub”: ”users/8983462”,

“scope”: “self api/buy”

}

Who issued the token

When it expires

Who it represents

What they can do

Page 63: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)Great! Why is this useful?

• Implicitly trusted because it is cryptographically signed (verified not tampered).

• It is structured, enabling inter-op between services

• It can inform your client about basic access control rules (permissions)*

• And the big one: statelessness!*servers must always enforce access control policies

Page 64: REST API Security: OAuth 2.0, JWTs, and More!

JSON Web Tokens (JWT)So, what’s the catch?

• Implicit trust is a tradeoff – how long should the token be good for? how will you revoke it? (Another talk: refresh tokens)

• You still have to secure your cookies!• You have to be mindful of what you

store in the JWT if they are not encrypted. No sensitive info!

Page 65: REST API Security: OAuth 2.0, JWTs, and More!

Authorization

Page 66: REST API Security: OAuth 2.0, JWTs, and More!

Authorization

• JWT Claims can have whatever you want

• Use a scope field that contains a list of permissions for that user

• Client can inspect the claims and scope and turn on or off features based on permissions*

• *Server must always assert permissions

Page 67: REST API Security: OAuth 2.0, JWTs, and More!

Authorization Failed: 403

HTTP/1.1 403 Forbidden

Page 68: REST API Security: OAuth 2.0, JWTs, and More!

In addition to user authentication and data security, Stormpath can handle authentication and authorization for your API, SPA or mobile app.

• API Authentication• API Key Management• Authorization• Token Based Authentication• OAuth• JWTs• MFA, SAML, OAuth2• Multi-Tenancy

http://docs.stormpath.com/guides/api-key-management/

Implementations in your Library of choice: https://docs.stormpath.com/home/

Use Stormpath for API Authentication & Security

Page 69: REST API Security: OAuth 2.0, JWTs, and More!

Follow Us on Twitter

@lhazlewood

@goStormpath