the state of oauth2

84
The State of OAuth 2 Aaron Parecki @aaronpk aaronparecki.com State of the Auth January 2013

Upload: aaron-parecki

Post on 06-May-2015

5.736 views

Category:

Technology


0 download

DESCRIPTION

Slides from my talk at State of the Auth in Portland

TRANSCRIPT

Page 1: The State of OAuth2

The State of OAuth 2Aaron Parecki • @aaronpk • aaronparecki.comState of the Auth • January 2013

Page 2: The State of OAuth2

aaron.pk/oauth2

Before OAuthApps stored the user’s password

Apps got complete access to a user’s account

Users couldn’t revoke access to an app except by changing their password

Compromised apps exposed the user’s password

@aaronpk

Page 3: The State of OAuth2

aaron.pk/oauth2

Before OAuthServices recognized the problems with

password authentication

Many services implemented things similar to OAuth 1.0

Each implementation was slightly different, certainly not compatible with each other

@aaronpk

Page 4: The State of OAuth2

aaron.pk/oauth2

Before OAuth 1.0Flickr: “FlickrAuth” frobs and tokens

Google: “AuthSub”

Facebook: requests signed with MD5 hashes

Yahoo: BBAuth (“Browser-Based Auth”)

@aaronpk

Page 5: The State of OAuth2

Some Current Implementers

Page 6: The State of OAuth2

The OAuth 2 Spechttp://oauth.net/2/

Page 7: The State of OAuth2

aaron.pk/oauth2

Definitions

Resource Owner: The User

Resource Server: The API

Authorization Server: Often the same as the API server

Client: The Third-Party Application

@aaronpk

Page 8: The State of OAuth2

aaron.pk/oauth2

Use CasesWeb-server apps

Browser-based apps

Username/password access

Application access

Mobile apps

@aaronpk

Page 9: The State of OAuth2

aaron.pk/oauth2

Use Cases – Grant TypesWeb-server apps – authorization_code

Browser-based apps – implicit

Username/password access – password

Application access – client_credentials

Mobile apps – implicit

@aaronpk

Page 10: The State of OAuth2

aaron.pk/oauth2

Web Server AppsAuthorization Code Grant

@aaronpk

Page 11: The State of OAuth2

aaron.pk/oauth2

Create a “Log In” link

Link to:

https://facebook.com/dialog/oauth?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=REDIRECT_URI&scope=email

@aaronpk

Page 12: The State of OAuth2

aaron.pk/oauth2

Create a “Log In” link

Link to:

https://facebook.com/dialog/oauth?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=REDIRECT_URI&scope=email

@aaronpk

Page 13: The State of OAuth2

aaron.pk/oauth2

Create a “Log In” link

Link to:

https://facebook.com/dialog/oauth?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=REDIRECT_URI&scope=email

@aaronpk

Page 14: The State of OAuth2

aaron.pk/oauth2

Create a “Log In” link

Link to:

https://facebook.com/dialog/oauth?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=REDIRECT_URI&scope=email

@aaronpk

Page 15: The State of OAuth2

aaron.pk/oauth2

Create a “Log In” link

Link to:

https://facebook.com/dialog/oauth?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=REDIRECT_URI&scope=email

@aaronpk

Page 16: The State of OAuth2

aaron.pk/oauth2

User visits the authorization page

https://facebook.com/dialog/oauth?response_type=code&client_id=28653682475872&redirect_uri=everydaycity.com&scope=email

@aaronpk

Page 17: The State of OAuth2

aaron.pk/oauth2

On success, user is redirected back to your site with auth code

https://example.com/auth?code=AUTH_CODE_HERE

On error, user is redirected back to your site with error code

https://example.com/auth?error=access_denied

@aaronpk

Page 18: The State of OAuth2

aaron.pk/oauth2

Server exchanges auth code for an access token

Your server makes the following request

POST https://graph.facebook.com/oauth/access_token

Post Body: grant_type=authorization_code&code=CODE_FROM_QUERY_STRING&redirect_uri=REDIRECT_URI &client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET

@aaronpk

Page 19: The State of OAuth2

aaron.pk/oauth2

Server exchanges auth code for an access token

Your server gets a response like the following

{ "access_token":"RsT5OjbzRn430zqMLgV3Ia", "token_type":"bearer", "expires_in":3600, "refresh_token":"e1qoXg7Ik2RRua48lXIV" }

or if there was an error

{ "error":"invalid_request"}

@aaronpk

Page 20: The State of OAuth2

aaron.pk/oauth2

Browser-Based Apps

Implicit Grant

@aaronpk

Page 21: The State of OAuth2

aaron.pk/oauth2

Create a “Log In” link

Link to:

https://facebook.com/dialog/oauth?response_type=token&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=email

@aaronpk

Page 22: The State of OAuth2

aaron.pk/oauth2

User visits the authorization page

https://facebook.com/dialog/oauth?response_type=token&client_id=2865368247587&redirect_uri=everydaycity.com&scope=email

@aaronpk

Page 23: The State of OAuth2

aaron.pk/oauth2

On success, user is redirected back to your site with the access token in the fragment

https://example.com/auth#token=ACCESS_TOKEN

On error, user is redirected back to your site with error code

https://example.com/auth#error=access_denied

@aaronpk

Page 24: The State of OAuth2

aaron.pk/oauth2

Browser-Based Apps

Use the “Implicit” grant type

No server-side code needed

Client secret not used

Browser makes API requests directly

@aaronpk

Page 25: The State of OAuth2

aaron.pk/oauth2

Username/Password

Password Grant

@aaronpk

Page 26: The State of OAuth2

aaron.pk/oauth2

Password Grant

Password grant is only appropriate for trusted clients, most likely first-party apps only.

If you build your own website as a client of your API, then this is a great way to handle logging in.

@aaronpk

Page 27: The State of OAuth2

aaron.pk/oauth2

Password Grant Type

Only appropriate for your service’s website or your service’s mobile apps.

Page 28: The State of OAuth2

aaron.pk/oauth2

Password Grant

POST https://api.example.com/oauth/token

Post Body: grant_type=password&username=USERNAME&password=PASSWORD&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET

Response:

{ "access_token":"RsT5OjbzRn430zqMLgV3Ia", "token_type":"bearer", "expires_in":3600, "refresh_token":"e1qoXg7Ik2RRua48lXIV" }

@aaronpk

Page 29: The State of OAuth2

aaron.pk/oauth2

Password Grant

User exchanges username and password for a token

No server-side code needed

Client secret only used from confidential clients (Don’t send client secret from a mobile app!)

Useful for developing a first-party login system

@aaronpk

Page 30: The State of OAuth2

aaron.pk/oauth2

Application AccessClient Credentials Grant

@aaronpk

Page 31: The State of OAuth2

aaron.pk/oauth2

Client Credentials Grant

POST https://api.example.com/1/oauth/token

Post Body: grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET

Response:

{ "access_token":"RsT5OjbzRn430zqMLgV3Ia", "token_type":"bearer", "expires_in":3600, "refresh_token":"e1qoXg7Ik2RRua48lXIV" }

@aaronpk

Page 32: The State of OAuth2

aaron.pk/oauth2

Grant Type Summaryauthorization_code:

Web-server apps

implicit: Mobile and browser-based apps

password: Username/password access

client_credentials: Application access

@aaronpk

Page 33: The State of OAuth2

aaron.pk/oauth2

Grant Types & Response Typesauthorization_code:

response_type=code

implicit: response_type=token

@aaronpk

Page 34: The State of OAuth2

aaron.pk/oauth2

Grant Type Review

@aaronpk

Page 35: The State of OAuth2

aaron.pk/oauth2

Authorization CodeUser visits auth page

response_type=code

User is redirected to your site with auth code http://example.com/?code=xxxxxxx

Your server exchanges auth code for access tokenPOST /tokencode=xxxxxxx&grant_type=authorization_code

@aaronpk

Page 36: The State of OAuth2

aaron.pk/oauth2

ImplicitUser visits auth page

response_type=token

User is redirected to your site with access token http://example.com/#token=xxxxxxx

Token is only available to the browser since it’s in the fragment

@aaronpk

Page 37: The State of OAuth2

aaron.pk/oauth2

PasswordYour server exchanges username/password for access token

POST /tokenusername=xxxxxxx&password=yyyyyyy&grant_type=password

@aaronpk

Page 38: The State of OAuth2

aaron.pk/oauth2

Client CredentialsYour server exchanges client ID/secret for access token

POST /tokenclient_id=xxxxxxx&client_secret=yyyyyyy&grant_type=client_credentials

@aaronpk

Page 39: The State of OAuth2

aaron.pk/oauth2

Mobile AppsImplicit Grant

@aaronpk

Page 40: The State of OAuth2

aaron.pk/oauth2 @aaronpk

Page 41: The State of OAuth2

aaron.pk/oauth2 @aaronpk

Page 42: The State of OAuth2

aaron.pk/oauth2

Redirect back to your app

fb2865://authorize/#access_token=BAAEEmo2nocQBAFFOeRTd

@aaronpk

Facebook app redirects back to your app using a custom URI scheme.

Access token is included in the redirect, just like browser-based apps.

Page 43: The State of OAuth2

aaron.pk/oauth2 @aaronpk

Page 44: The State of OAuth2

aaron.pk/oauth2

Mobile Applications

Use the “Implicit” grant type

No server-side code needed

Client secret not used

Mobile app makes API requests directly

@aaronpk

Page 45: The State of OAuth2

aaron.pk/oauth2

Mobile ApplicationsExternal user agents are best

Use the service’s primary app for authentication, like Facebook – provides a superior user experience

Or open native Safari on iPhone, still better than using an embedded browser

Auth code or implicit grant type In both cases, the client secret should never be

used, since it is possible to decompile the app which would reveal the secret

@aaronpk

Page 46: The State of OAuth2

aaron.pk/oauth2

Accessing ResourcesSo you have an access token.

Now what?

@aaronpk

Page 47: The State of OAuth2

aaron.pk/oauth2

Use the access token to make requests

Now you can make requests using the access token.

GET https://api.example.com/me Authorization: Bearer RsT5OjbzRn430zqMLgV3Ia

Access token can be in an HTTP header or a query string parameter

https://api.example.com/me?access_token=RsT5OjbzRn430zqMLgV3Ia

@aaronpk

Page 48: The State of OAuth2

aaron.pk/oauth2

Eventually the access token may expire

When you make a request with an expired token, you will get this response

{ "error":"expired_token"}

Now you need to get a new access token!

@aaronpk

Page 49: The State of OAuth2

aaron.pk/oauth2

Get a new access token using a refresh tokenYour server makes the following request

POST https://api.example.com/oauth/token

grant_type=refresh_token&reresh_token=e1qoXg7Ik2RRua48lXIV&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET

Your server gets a similar response as the original call to oauth/token with new tokens.

{ "access_token":"RsT5OjbzRn430zqMLgV3Ia", "expires_in":3600, "refresh_token":"e1qoXg7Ik2RRua48lXIV" }

@aaronpk

Page 50: The State of OAuth2

aaron.pk/oauth2

ScopeLimiting access to resouces

@aaronpk

Page 51: The State of OAuth2

aaron.pk/oauth2

Limiting Access to Third Parties

@aaronpk

Page 52: The State of OAuth2

aaron.pk/oauth2

Limiting Access to Third Parties

@aaronpk

Page 53: The State of OAuth2

aaron.pk/oauth2

Limiting Access to Third Parties

@aaronpk

Page 54: The State of OAuth2

aaron.pk/oauth2

OAuth 2 scopeCreated to limit access to the third party.

The scope of the access request expressed as a list of space-delimited strings. In practice, many people use comma-separators instead.

The spec does not define any values, it’s left up to the implementor.

If the value contains multiple strings, their order does not matter, and each string adds an additional access range to the requested scope.

@aaronpk

Page 55: The State of OAuth2

aaron.pk/oauth2

OAuth 2 scope on Facebookhttps://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&scope=email,read_stream

@aaronpk

Page 56: The State of OAuth2

aaron.pk/oauth2

OAuth 2 scope on Facebook

@aaronpk

Page 57: The State of OAuth2

aaron.pk/oauth2

OAuth 2 scope on Githubhttps://github.com/login/oauth/authorize? client_id=...&scope=user,public_repo

@aaronpk

user

• Read/write access to profile info only.

public_repo

• Read/write access to public repos and organizations.

repo

• Read/write access to public and private repos and organizations.

delete_repo

• Delete access to adminable repositories.

gist

• write access to gists.

Page 58: The State of OAuth2

aaron.pk/oauth2

OAuth 2 scopeThe challenge is displaying this to the user succinctly in a way

they will actually understand

If you over-complicate it for users, they will just click “ok” until the app works, and ignore any warnings

Read vs write is a good start for basic services

@aaronpk

Page 59: The State of OAuth2

aaron.pk/oauth2

So what’s wrong?

@aaronpk

Page 60: The State of OAuth2

aaron.pk/oauth2

What I just described is one possible

implementation of an OAuth 2 server

@aaronpk

Page 61: The State of OAuth2

aaron.pk/oauth2

IndecisionNo required token type

No agreement on the goals of an HMAC-enabled token type

No requirement to implement token expiration

No guidance on token string size, or any value for that matter

No strict requirement for registration

Loose client type definition

@aaronpk

Page 62: The State of OAuth2

Indecision (continued)Lack of clear client security properties

No required grant types

No guidance on the suitability or applicability of grant types

No useful support for native applications (but lots of lip service)

No required client authentication method

No limits on extensions

@aaronpkaaron.pk/oauth2 Source: http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/

Page 63: The State of OAuth2

aaron.pk/oauth2

The result: the OAuth RFC is a

framework, not a protocol

@aaronpk

Page 64: The State of OAuth2

aaron.pk/oauth2 @aaronpk

Page 65: The State of OAuth2

aaron.pk/oauth2 @aaronpk

Page 66: The State of OAuth2

OAuth 2 ServersImplementing an OAuth 2

Server

@aaronpkaaron.pk/oauth2

Page 67: The State of OAuth2

Implementing an OAuth 2 Server

Page 68: The State of OAuth2

aaron.pk/oauth2

Implementing an OAuth 2 ServerFind a server library already written:

A short list available here: http://oauth.net/2/

Read the OAuth spec in its entirety

Study other implementations like Google

Make decisions based on the security requirements of your application. In many cases the spec says SHOULD and leaves the choice up to the implementer.

Understand the security implications of the implementation choices you make.

@aaronpk

Page 69: The State of OAuth2

aaron.pk/oauth2

Implementing an OAuth 2 ServerChoose which grant types you want to support

Authorization Code – for traditional web apps Implicit – for browser-based apps and mobile appsPassword – for your own website or mobile appsClient Credentials – if applications can access resources on

their own

Choose whether to support Bearer tokens, MAC or both

If using Bearer tokens, choose whether to use a DB lookup or use self-container tokens

Define appropriate scopes for your service@aaronpk

Page 70: The State of OAuth2

Access TokensBearer tokens vs

MAC tokens

@aaronpkaaron.pk/oauth2

Page 71: The State of OAuth2

Bearer Tokens

GET /1/profile HTTP/1.1 Host: api.example.com Authorization: Bearer B2mpLsHWhuVFw3YeLFW3f2

@aaronpk

Bearer tokens are a cryptography-free way to access protected resources.

Relies on the security present in the HTTPS connection, since the request itself is not signed.

Application developers do not need to do any cryptography, they just pass the token string in the header.

aaron.pk/oauth2

Page 72: The State of OAuth2

aaron.pk/oauth2

Dangers of Using Bearer TokensRequests are not signed, so are vulnerable to

reply attacks if someone intercepts the token.

When storing tokens in cookies, must ensure the cookie is only sent via an https connection.

If a token is leaked, there is a large potential for abuse.

@aaronpk

Page 73: The State of OAuth2

aaron.pk/oauth2

Security Recommendationsfor Clients Using Bearer TokensSafeguard bearer tokens

Validate SSL certificates

Always use https

Don’t store bearer tokens in plaintext cookies

Issue short-lived bearer tokens

Don’t pass bearer tokens in page URLs

@aaronpk

Page 74: The State of OAuth2

MAC TokensGET /1/profile HTTP/1.1 Host: api.example.com Authorization: MAC id="jd93dh9dh39D", nonce="273156:di3hvdf8”, mac="W7bdMZbv9UWOTadASIQHagZyirA="

@aaronpk

MAC tokens provide a way to make authenticated requests with cryptographic verification of the request.

Similar to the original OAuth 1.0 method of using signatures.

Application developers must sign each request, preventing forgery and replay even when requests are sent in the clear.

Page 75: The State of OAuth2

aaron.pk/oauth2

Bearer, MAC, or Both?Should you support Bearer tokens, MAC tokens or

both?

MAC tokens are technically safer and more secure

Application developers will prefer working with Bearer tokens since it is easier

@aaronpk

Page 76: The State of OAuth2

aaron.pk/oauth2

Scalability ConcernsToken lookups from a database can become a

bottleneck.

Can be addressed by heavy use of caching to avoid DB lookups

Can be addressed by a good master/slave database architecture

An alternative is to use “self-encoded” tokens where all the needed information is contained within the token string itself, avoiding the need to do a database lookup

@aaronpk

Page 77: The State of OAuth2

aaron.pk/oauth2

Self-Encoded TokensThe token is a string which is encrypted or

signed

The string contains all necessary information to avoid doing a database lookup

These tokens cannot be revoked, so must expire frequently (requires heavy use of the refresh_token grant type)

Can be implemented with either Bearer or MAC tokens

@aaronpk

Page 78: The State of OAuth2

aaron.pk/oauth2

DB Token Lookups vs Self-Encoded TokensToken table probably looks like

Token User ID Expiration Date Scopes

Instead, encode that into a JSON payload which *is* the token:

{“user_id”:1000,”exp”:1355429676,”scopes”:[“email”,”payment”]}

See JSON Web Signature for example of signing this token

@aaronpk

Page 79: The State of OAuth2

aaron.pk/oauth2

JSON Web Signaturehttp://tools.ietf.org/html/draft-ietf-jose-json-web-signature-07

@aaronpk

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

{ "usr":"username", "exp":1300819380, "scope":["profile"]}

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9

Data Base64 Encoded

eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ

Signature dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOE

Page 80: The State of OAuth2

aaron.pk/oauth2

JSON Web Signature

@aaronpk

Complete Token Example:

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

Header, data, signature are base64 encoded and concatenated with a “period” between each.

Page 81: The State of OAuth2

aaron.pk/oauth2 @aaronpk

oauth.net

Page 82: The State of OAuth2

aaron.pk/oauth2

oauth.net Websitehttp://oauth.net

Source code available on Github github.com/aaronpk/oauth.net

Please feel free to contribute to the website

Contribute new lists of libraries, or help update information

@aaronpk

Page 83: The State of OAuth2

aaron.pk/oauth2 @aaronpk

github.com/aaronpk/oauth.net

Page 84: The State of OAuth2

Thanks.

Aaron Parecki

@aaronpk

aaronparecki.com

github.com/aaronpk