Securing RESTful APIs Using OAuth 2 and OpenID Connect Jonathan LeBlanc (@jcleblanc) Head of Developer Evangelism PayPal North America
Jan 28, 2015
Securing RESTful APIsUsing OAuth 2 and OpenID Connect
Jonathan LeBlanc (@jcleblanc) Head of Developer Evangelism
PayPal North America
What We’re Covering
Auth History and REST Concepts
Adding in an Auth Mechanism
Integration in Practice (server + client side integrations)
What We Want
The Ultimate Decision
Security Usability
Path to the Standard
The Insecure, Unmanageable Start
Very Secure, Long to Implement
Two Currently Widely Used Specs
REST Architecture
What a RESTful API isn’t
Our API is RESTful, we support GET, PUT, POST, and DELETE requests
No…actually you just support HTTP…like the rest of the web.
What a RESTful API is
Honor HTTP request verbs
Use proper HTTP status codes
No version numbering in URIs
Return format via HTTP Accept header
Does Anyone Actually Do That?
Very few APIs follow pragmatic REST principles
HATEOAS
"links": [{ "href": "https://api.sandbox.paypal.com/v1/payments/ payment/PAY-6RV75EKEYSZ6Y", "rel": "self", "method": "GET" },{ "href": "https://www.sandbox.paypal.com/webscr? cmd=_express-checkout&token=EC-6019609", "rel": "approval_url", "method": "REDIRECT" },{ "href": "https://api.sandbox.paypal.com/v1/payments/ payment/PAY-6RV75EKEYSZ6Y/execute", "rel": "execute", "method": "POST" }]
Adding Auth Mechanisms
Reasons for Auth
Rate Limiting and Attack Vector Protection
Having the ability to revoke application access
Needing to allow users to revoke an applications access to their data
When You Need Access Security
A Few Different Flavors of Usage
User login (authentication)
Application only (bearer tokens)
User Involvement (authorization)
Practical Implementation
Fetching the Access Token
Fetch the Access TokenAccess Token Endpointclient_id grant_typeclient_secret
HTTP POSTAccess Token Endpoint
Fetching the Access Token
curl https://api.sandbox.paypal.com/v1/oauth2/token \ -H "Accept: application/json" \ -H "Accept-Language: en_US" \ -u "EOJ2S-Z6OoN_le_KS1d75wsZ6y0SFd…" \ -d "grant_type=client_credentials"
Access Token Response
{ "scope": "https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card", "access_token": "EEwJ6tF9x5WCIZDYzyZGaz6K…", "token_type": "Bearer", "app_id": "APP-6XR95014SS315863X", "expires_in": 28800}
Using the Access Token
Fetch Privileged ResourcesResource EndpointToken Type (Authorization header) Access Token (Authorization header)
HTTP GET / PUT / POST / DELETEResource Endpoint
Using the Access Token
curl -v https://api.sandbox.paypal.com/v1/payments/payment \-H "Content-Type:application/json" \-H "Authorization:Bearer EMxItHE7Zl4cMdkv…" \-d "{...}"
A few implementation differences
Endpoints
Scopes (dynamic / static)
Using the Access Token in a request
OAuth 2 & JavaScript?
The Complexities of JavaScript
The same-origin policy
Keeping private keys private
Not having to provide a hacked
experience
The Ways we Made it Work
Server-side proxy
Flash / iframe proxy
Private token storage mechanism
User Agent Flow: Redirect
Prepare the Redirect URIAuthorization Endpointclient_id response_type (token)scope redirect_uri
Browser RedirectRedirect URI
User Agent Flow: Redirect
Building the redirect link
var auth_uri = auth_endpoint + "?response_type=token" + "&client_id=" + client_id + "&scope=profile" + "&redirect_uri=" + window.location; $("#auth_btn").attr("href", auth_uri);
User Agent Flow: Hash Mod
Fetch the Hash Modaccess_tokenrefresh_tokenexpires_in
Extract Access Token
User Agent Flow: Hash Mod
http://site.com/callback#access_token=rBEGu1FQr54AzqE3Q&refresh_token=rEBt51FZr54HayqE3V4a&expires_in=3600
var hash = document.location.hash;var match = hash.match(/access_token=(\w+)/);
Extracting the access token from the hash
User Agent Flow: Get Resources
Set Request Headers + URIResource EndpointHeader: token type + access tokenHeader: accept data type
HTTPS Request
User Agent Flow: Get Resources
$.ajax({ url: resource_uri, beforeSend: function (xhr) { xhr.setRequestHeader('Authorization', 'OAuth ' + token); xhr.setRequestHeader('Accept', 'application/json'); }, success: function (response) { //use response object }});
Making an authorized request
Using the Skeleton Key
How it’s Normally Used
Access user details
Push data throughuser social streams
But why?
Access token as a control structure
Improve Existing Products
Our showcase: Seamless Checkout
The Last Considerations
REST and OAuth are specifications, not religions
Don’t alienate your developers with security
Open source is your friend
A Few Code Links
OAuth2 & OpenID Connect Sampleshttps://github.com/jcleblanc/oauthhttps://github.com/paypal/paypal-access
Log in with PayPalhttp://bit.ly/loginwithpaypal
Thank You! Questions?
http://slideshare.net/jcleblancJonathan LeBlanc (@jcleblanc)
Head of Developer Evangelism PayPal North America