An Introduction To Oauth2
An Introduction To Oauth2
to OAuth 2
Aaron Parecki • @aaronpk
O’Reilly Webcast • July 2012
A Brief History
aaron.pk/oauth2 @aaronpk
Before OAuth
aka the Dark Ages
If a third party wanted access to an account,
you’d give them your password.
aaron.pk/oauth2 @aaronpk
Several Problems and
Limitations
¡ Apps store the user’s password
aaron.pk/oauth2 @aaronpk
Before OAuth 1.0
¡ Services recognized the problems with password
authentication
aaron.pk/oauth2 @aaronpk
Before OAuth 1.0
¡ Flickr: “FlickrAuth” frobs and tokens
aaron.pk/oauth2 @aaronpk
“We want something like Flickr Auth /
Google AuthSub / Yahoo! BBAuth, but
published as an open standard, with
common server and client libraries.”
Blaine Cook, April 5th, 2007
aaron.pk/oauth2 @aaronpk
OAuth 1.0
aaron.pk/oauth2 @aaronpk
aaron.pk/oauth2 @aaronpk
aaron.pk/oauth2 @aaronpk
OAuth 1.0 Signatures
The signature base string is often the most difficult part of
OAuth for newcomers to construct. The signature base string
is composed of the HTTP method being used, followed by
an ampersand ("&") and then the URL-encoded base URL
being accessed, complete with path (but not query
parameters), followed by an ampersand ("&"). Then, you
take all query parameters and POST body parameters
(when the POST body is of the URL-encoded type, otherwise
the POST body is ignored), including the OAuth parameters
necessary for negotiation with the request at hand, and sort
them in lexicographical order by first parameter name and
then parameter value (for duplicate oauth_nonce="QP70eNmVz8jvdPevU3oJD2AfF7R7o
parameters), all the
while ensuring that both the key and the value for oauth_callback="http%3A%2F
dC2XJcn4XlZJqk", each
%2Flocalhost%3A3005%2Fthe_dance
parameter are URL encoded in isolation. Instead of using the
%2Fprocess_callback%3Fservice_provider_id
equals ("=") sign to mark the key/value relationship, you use
the URL-encoded form of "%3D". Each parameter
%3D11", is then
oauth_signature_method="HMAC-SHA1",
joined by the URL-escaped ampersand sign, "%26".
oauth_timestamp="1272323042",
oauth_consumer_key="GDdmIQH6jhtmLUypg82g",
oauth_signature="8wUi7m5HFQy76nowoCThusfgB
%2BQ%3D", oauth_version="1.0"
aaron.pk/oauth2 @aaronpk
aaron.pk/oauth2 @aaronpk
OAuth 2:
signatures replaced by https
HMAC
aaron.pk/oauth2 @aaronpk
Some Current Implementers
The OAuth 2 Spec
http://oauth.net/2/
OAuth 2?!
aaron.pk/oauth2 @aaronpk
Currently Implemented Drafts
Provider Draft Reference
Foursquare -10 http://aaron.pk/2YS
http://code.google.com/apis/accounts/
Google -10
docs/OAuth2.html
https://developers.facebook.com/docs/
Facebook -10 (ish)
authentication/oauth2_updates/
Windows
-10 http://aaron.pk/2YV
Live
Salesforce -10 http://aaron.pk/2YW
Github -07 http://develop.github.com/p/oauth.html
Geoloqi -10 http://developers.geoloqi.com/api
@aaronpk
So how does it work?
aaron.pk/oauth2 @aaronpk
Definitions
¡ Resource Owner: The User
¡ Resource Server: The API
¡ Authorization Server: Often the same
as the API server
¡ Client: The Third-Party Application
aaron.pk/oauth2 @aaronpk
Use Cases
¡ Web-server apps
¡ Browser-based apps
¡ Username/password access
¡ Application access
¡ Mobile apps
aaron.pk/oauth2 @aaronpk
Facebook’s OAuth Flow
aaron.pk/oauth2 @aaronpk
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
aaron.pk/oauth2 @aaronpk
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
aaron.pk/oauth2 @aaronpk
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
aaron.pk/oauth2 @aaronpk
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
aaron.pk/oauth2 @aaronpk
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
aaron.pk/oauth2 @aaronpk
User visits the authorization page
https://facebook.com/dialog/oauth?
response_type=code&client_id=28653682475872
&redirect_uri=everydaycity.com&scope=email
aaron.pk/oauth2 @aaronpk
On success, user is redirected
back to your site with auth code
https://example.com/auth?code=AUTH_CODE_HERE
aaron.pk/oauth2 @aaronpk
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
aaron.pk/oauth2 @aaronpk
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"
}
{
"error":"invalid_request"
}
aaron.pk/oauth2 @aaronpk
Browser-Based Apps
Implicit Grant
aaron.pk/oauth2 @aaronpk
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
aaron.pk/oauth2 @aaronpk
User visits the authorization page
https://facebook.com/dialog/oauth?
response_type=token&client_id=2865368247587
&redirect_uri=everydaycity.com&scope=email
aaron.pk/oauth2 @aaronpk
On success, user is redirected
back to your site with the access
token in the fragment
https://example.com/auth#token=ACCESS_TOKEN
aaron.pk/oauth2 @aaronpk
Browser-Based Apps
¡ Use the “Implicit” grant type
aaron.pk/oauth2 @aaronpk
Username/Password
Password Grant
aaron.pk/oauth2 @aaronpk
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.
aaron.pk/oauth2 @aaronpk
Password Grant Type
Only appropriate for your
service’s website or your
service’s mobile apps.
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"
}
aaron.pk/oauth2 @aaronpk
Application Access
Client Credentials Grant
aaron.pk/oauth2 @aaronpk
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"
}
aaron.pk/oauth2 @aaronpk
Mobile Apps
Implicit Grant
aaron.pk/oauth2 @aaronpk
aaron.pk/oauth2 @aaronpk
aaron.pk/oauth2 @aaronpk
Redirect back to your app
Facebook app redirects back to your app
using a custom URI scheme.
Access token is included in the redirect, just
like browser-based apps.
fb2865://authorize/#access_token=BAAEEmo2nocQBAFFOeRTd
aaron.pk/oauth2 @aaronpk
aaron.pk/oauth2 @aaronpk
Mobile Apps
¡ Use the “Implicit” grant type
aaron.pk/oauth2 @aaronpk
Accessing Resources
So you have an access token.
Now what?
aaron.pk/oauth2 @aaronpk
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
https://api.example.com/me?
access_token=RsT5OjbzRn430zqMLgV3Ia
aaron.pk/oauth2 @aaronpk
Eventually the access token
will expire
When you make a request with an expired token,
you will get this response
{
"error":"expired_token"
}
aaron.pk/oauth2 @aaronpk
Get a new access token
using a refresh token
Your 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
{
"access_token":"RsT5OjbzRn430zqMLgV3Ia",
"expires_in":3600,
"refresh_token":"e1qoXg7Ik2RRua48lXIV"
}
aaron.pk/oauth2 @aaronpk
Moving access into
separate specs
Bearer tokens vs MAC
authentication
aaron.pk/oauth2 @aaronpk
Bearer Tokens
GET /1/profile HTTP/1.1
Host: api.example.com
Authorization: Bearer B2mpLsHWhuVFw3YeLFW3f2
aaron.pk/oauth2 @aaronpk
Security Recommendations
for Clients Using Bearer Tokens
¡ Safeguard bearer tokens
aaron.pk/oauth2 @aaronpk
MAC Tokens
GET /1/profile HTTP/1.1
Host: api.example.com
Authorization: MAC id="jd93dh9dh39D",
nonce="273156:di3hvdf8",
bodyhash="k9kbtCIyI3/FEfpS/oIDjk6k=",
mac="W7bdMZbv9UWOTadASIQHagZyirA="
@aaronpk
OAuth 2 Clients
Client libraries should handle refreshing the token
automatically behind the scenes.
aaron.pk/oauth2 @aaronpk
Scope
Limiting access to resouces
aaron.pk/oauth2 @aaronpk
Limiting Access to Third Parties
aaron.pk/oauth2 @aaronpk
Limiting Access to Third Parties
aaron.pk/oauth2 @aaronpk
Limiting Access to Third Parties
aaron.pk/oauth2 @aaronpk
OAuth 2 scope
¡ Created to limit access to the third party.
¡ 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.
aaron.pk/oauth2 @aaronpk
OAuth 2 scope on Facebook
https://www.facebook.com/dialog/oauth?
client_id=YOUR_APP_ID&redirect_uri=YOUR_URL
&scope=email,read_stream
aaron.pk/oauth2 @aaronpk
OAuth 2 scope on Facebook
aaron.pk/oauth2 @aaronpk
OAuth 2 scope on Github
https://github.com/login/oauth/authorize?
client_id=...&scope=user,public_repo
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.
aaron.pk/oauth2 @aaronpk
Proposed New UI for Twitter
by Ben Ward
http://blog.benward.me/post/968515729
Implementing an OAuth Server
Implementing an OAuth
Server
¡ Find a server library already written:
¡ A short list available here: http://oauth.net/2/
aaron.pk/oauth2 @aaronpk
Implementing an OAuth
Server
¡ Choose which grant types you want to support
¡ Authorization Code – for traditional web apps
¡ Implicit – for browser-based apps and mobile apps
¡ Password – for your own website or mobile apps
¡ Client Credentials – if applications can access resources on
their own
aaron.pk/oauth2 @aaronpk
OAuth 2 scope on your service
¡ Think about what scopes you might offer
aaron.pk/oauth2 @aaronpk
Mobile Applications
¡ External user agents are best
¡ Use the service’s primary app for authentication, like
Facebook
¡ Or open native Safari on iPhone rather than use an
embedded browser
aaron.pk/oauth2 @aaronpk
Staying Involved
aaron.pk/oauth2 @aaronpk
Join the Mailing List!
¡ https://www.ietf.org/mailman/listinfo/oauth
aaron.pk/oauth2 @aaronpk
oauth.net
aaron.pk/oauth2 @aaronpk
oauth.net Website
¡ http://oauth.net
aaron.pk/oauth2 @aaronpk
github.com/aaronpk/oauth.net
aaron.pk/oauth2 @aaronpk
More Info, Slides & Code Samples:
aaron.pk/oauth2
Thanks.
Aaron Parecki
@aaronpk
aaronparecki.com
github.com/aaronpk