Upgrade to Pro — share decks privately, control downloads, hide ads and more …

API Authorization with OAuth2

API Authorization with OAuth2

Developer Week 2013

Bastian Hofmann

June 25, 2013
Tweet

More Decks by Bastian Hofmann

Other Decks in Programming

Transcript

  1. show of hands: web application? mobile? desktop? used an oauth

    api in one of their apps, oauth2? implemented an oauth api themselves? Why is knowing about OAuth important?
  2. API because in nearly every web or mobile application you

    are talking with external apis at some time, be it to get additional data, single-sign-on, imports/exports etc
  3. and if you look at the big api providers everybody

    uses oauth, and a lot of them already oauth2, of course all of them offer their client libraries and sdks which already handle oauth for you, but it's still very important to know how they work and what the security implications are
  4. ResearchGate gives science back to the people who make it

    happen. We help researchers build reputation and accelerate scientific progress. On their terms. ‟ the goal is to give...
  5. Questions? Ask by the way, if you have any questions

    throughout this talk, if you don't understand something, just raise your hand and ask. probably my fault anyways since i spoke to quickly or my accent was too bad
  6. http://oauth.net/ So before we start with OAuth2 I want to

    take a few minutes and quickly explain how the first version of OAuth works, so we understand why OAuth2 is even necessary and why some decisions in OAuth2 were made
  7. lanyrd.com twitter.com Pre Registration of Client at Twitter: - Shared

    Consumer Key - Shared Consumer Secret first of all the client needs to preregister at the api server, from there it gets a shared consumer key and a shared consumer secret
  8. HTTP POST Connect with Twitter lanyrd.com after that each time

    a user of the client wants to connect with the api
  9. twitter.com HTTP POST Connect with Twitter HTTP GET Consumer Key

    Redirect URI Signature (Consumer Secret) lanyrd.com the client, server to server, with his consumer key and a redirect callback url (more on that one later) requests a request token from the api. this request like all the other server to server requests later is signed with an oauth signature which as the consumer secret as a key. i'll explain oauth signatures later as well.
  10. twitter.com HTTP POST Connect with Twitter Request Token Request Token

    Secret lanyrd.com in response of this request token request the api issues a request token and a request token secret to the client and internally binds them to the consumer key of the client
  11. http://twitter.com/authorize? requestToken=... HTTP Redirect lanyrd.com the client also remembers this

    request token and request token secret, binds them to the current user or his session and redirects the user in the browser to the authorization endpoint of the api, the issued request token is attached as a query parameter to this redirect
  12. HTTP GET twitter.com/ authorize the user is is now at

    the authorization endpoint of the api
  13. Grant permission twitter.com/ authorize Create verifier and bind it to

    User and Request Token and after that he grants permission to the client to access the api in his name. if he did that the api provider created a verifier and binds it to the authorizing user and the issued request token
  14. Redirect URI? verifier=...&requestToken=.. HTTP Redirect twitter.com/ authorize after that he

    redirects the user back to the callback url provided by the client in the first step when getting the request token, and adds the authorized request token and the created verifier as query parameters to this redirect
  15. HTTP GET HTTP GET Consumer Key, RequestToken Verifier Signature (Consumer

    & Request Token Secret) twitter.com lanyrd.com which can use the request token, its consumer key and the received verifier to get an access token (server to server) from the api this request is signed with the consumer secret and request token secret as a key
  16. HTTP GET Access Token Access Token Secret twitter.com lanyrd.com if

    everything is valid the api issues an access token and an access token secret which are bound to the client and the authorized user to the client
  17. HTTP GET API Request Consumer Key, Access Token Signature (Consumer

    & Access Token Secret) twitter.com lanyrd.com now finally the client can access the api with its consumer key the access token. each request is signed with a signature that has the consumer secret and the access token secret as a key.
  18. POST /oauth/request_token HTTP/1.1 Host: api.twitter.com Authorization: OAuth oauth_consumer_key=“abcdef“, oauth_signature_method=“HMAC-SHA1“, oauth_timestamp=“137131200“,

    oauth_nonce=“gggg“, oauth_callback=“http%3A%2F %2Fexample.com%2Fcallback“ oauth_signature=“...“ in detail: getting the request token
  19. POST /oauth/access_token HTTP/1.1 Host: api.twitter.com Authorization: OAuth oauth_consumer_key=“abcdef“, oauth_token=“defghi“ oauth_signature_method=“HMAC-SHA1“,

    oauth_timestamp=“137131201“, oauth_nonce=“hhhhh“, oauth_verifier=“qrstuvw“ oauth_signature=“...“ client gets the access token
  20. POST /1/statuses/update.json HTTP/1.1 Host: api.twitter.com Authorization: OAuth oauth_consumer_key=“abcdef“, oauth_token=“ xzyabc“

    oauth_signature_method=“HMAC-SHA1“, oauth_timestamp=“137131203“, oauth_nonce=“iiiiiii“, oauth_signature=“...“ status=New %20Tweet&trim_user=true&include_entities=tru e finally with the access token the client can access the api for the authorized user
  21. GET&http%3A%2F %2Fphotos.example.net%2Fphotos %2Fvacation.jpg&oauth_consumer_key %3D123%26oauth_nonce %3D456%26oauth_signature_method %3DHMAC-SHA1%26oauth_timestamp %3D1191242096%26oauth_token %3D789%26oauth_version%3D1.0 so you

    have the http method, the url including the sorted query parameters and if there is a request body even a hash over the requestbody, concatenated together this is the so called base string
  22. PLAINTEXT and then there are different signature methods where you

    crypt the signature, of course for testing there is an insecure one: PLAINTEXT, where the basestring is just transported plainly without encryption
  23. HMAC-SHA1 Salt: consumerSecret(&tokenSecret) there is HMAC-SHA1 where the basestring is

    encrypted with the consumer secret and the token secret as a key (shared secret)
  24. Does not work well with non web or JavaScript based

    clients The „Invalid Signature“ Problem Complicated Flow, many requests Problems but oauth1 has some problems...
  25. Different client profiles No signatures No Token Secrets Cookie-like Bearer

    Token No Request Tokens Much more flexible regarding extensions Mandatory TSL/SSL What's new?
  26. lanyrd.com twitter.com Pre Registration of Client at Twitter: - Shared

    Client ID - Shared Client Secret - Redirect URI first of all the client needs to preregister at the api server, from there it gets a shared client id and a shared client secret, he also has to preregister a callback url for later use (pre- registration so that we can get rid of the request token step)
  27. http://twitter.com/authorize? &clientId=... HTTPS Redirect lanyrd.com the client directly redirects him

    to the authorization endpoint of the api and adds its client id as a query parameter to the url
  28. HTTPS GET twitter.com/ authorize the user is is now at

    the authorization endpoint of the api
  29. Grant permission twitter.com/ authorize Create authorization code and bind it

    to User and ClientID and after that he grants permission to the client to access the api in his name. if he did that the api provider creates an authorization code and binds it to the authorizing user and the client's client id
  30. Redirect URI?authorizationCode=... HTTPS Redirect twitter.com/ authorize the user is the

    redirected to the client's pre registered callback url with the generated authorization code as a query parameter
  31. HTTPS GET HTTPS GET Client ID Authorization Code Client Secret

    twitter.com lanyrd.com the client can take the authorization code and together with the client id and client secret it can retrieve an access token server to server from the api
  32. HTTPS GET Access Token (Refresh Token) twitter.com lanyrd.com if the

    authorization code is valid the api creates an access token which is bound to the client id and the user authorized by the authorization code and passes it with an optional refresh token to the client
  33. HTTPS GET HTTPS API Request Access Token twitter.com lanyrd.com with

    the access token the client can now access the api
  34. HTTPS GET HTTPS GET Client ID Refresh Token Client Secret

    twitter.com lanyrd.com if the access token expired and the api issued a refresh token the client can use this refresh token and his client id an secret to get a new access token
  35. POST /oauth2/token HTTP/1.1 Host: api.twitter.com Authorization: Basic mnopqrs Content-Type: application/x-www-form-

    urlencoded;charset=UTF-8 grant_type=authorization_code&code=ghijkl another way of authorization: header not as parameter in the request body
  36. HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 { "access_token": "jklmno", "expires_in": 3600,

    "refresh_token": "qrstuvq", "token_type": "bearer" } access token response
  37. POST /oauth2/token HTTP/1.1 Host: api.twitter.com Authorization: Basic mnopqrs Content-Type: application/x-www-form-

    urlencoded;charset=UTF-8 grant_type=refresh_token&code=qrstuvq getting a new access token with a refresh token
  38. Bearer Tokens so far we have seen the bearer token

    type, which is the most simple one
  39. GET /1/statuses/home_timeline HTTP/1.1 Host: api.twitter.com Authorization: Bearer jklmno you just

    put the bearer token (the access token) in the authorization header, similar to a cookie, this is secure since everything is done through https
  40. Signatures there is still signature support for oauth2 which is

    a bit similar to oauth2 but more simple
  41. HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 { "access_token“: "jklmno“, "token_type“: "mac“,

    "expires_in“: 3600, "refresh_token“: "qrstuvq“ "mac_key":"adijq39jdlaska9asud", "mac_algorithm":"hmac-sha-1" } in your access token response you also get a key and algorithm for generating the signature
  42. GET /1/statuses/home_timeline HTTP/1.1 Host: api.twitter.com Authorization: MAC id=“jklmno“, nonce=“274312:dj83hs“, mac=“.....“

    the builded signature is included in the authorization header together with the access token and a nonce value to prevent replay attacks
  43. timestamp\n nonce\n HTTP_METHOD\n HTTP Request URI\n Hostname\n Port\n (Authorization extension)

    the signatures base string is builded like this and encrypted according to the given algorithm from the access token response
  44. User-Agent Profile for javascript only applications there is the user-agent

    profile, user-agent because it only happens in the user-agent, the browser
  45. http://twitter.com/authorize? &clientId=... Open Popup lanyrd.com when the user wants to

    connect with an api the javascript application opens a browser popup (or an iframe but popup is better because of fishing) pointing to the authorization endpoint of the api, and adds its client id to it
  46. http://twitter.com/authorize? &clientId=... Open Popup lanyrd.com HTTPS GET twitter.co m/ authorize

    in the popup the user is is now at the authorization endpoint of the api
  47. http://twitter.com/authorize? &clientId=... Open Popup lanyrd.com Grant Permission twitter.co m/ authorize

    if the user grants permission to the api to access the api in his name
  48. lanyrd.com HTTPS Redirect RedirectURI#ac cessToken twitter.co m/ authorize RedirectURI #accessTok

    en lanyrd.com the authorization endpoint generates an access token for the user and the client and redirects the user back to the preregistered callback url of the client. the access token is added to the fragment part of the callback url. this still happens in the popup
  49. lanyrd.com RedirectURI #accessTok en Parse Access Token from Fragment Send

    it to opening window Close popup lanyrd.com because the access token is in the fragment it is not transported to the backend serving the callback url, so the only thing this can do is rendering out a bit of javascript that takes the fragment part of the url and parses the access token out of it and if the callback url is on the same hostname as the javascript app that opened the window, it can make a function call to send the access token to it
  50. Same Origin Policy this is secure because of the same

    origin policy that is built into the browsers. it says that you can only access pages and windows and resources that are on the some host that your application is. this is a very basic security feature in browsers, otherwise malicious sites would have access to everything that is currently open in your browser or where you have session or login cookies stored at
  51. lanyrd.com HTTPS Ajax Request to API Access Token twitter.co m

    now that our javascript application has the access token it can make requests to the api with it
  52. Same Origin Policy but remember: same origin policy, we can't

    just make ajax request to foreign hosts because of this. though for api requests that is a fine and valid use case, since authorization there is not done by cookies.
  53. Backend api.twitter.com Client lanyrd. com AJAX Access-Control-Allow-Origin: * http://www.w3.org/TR/cors/ which

    works like this: whenever you try to make an ajax request to a foreign hostname, the browser first does a HEAD request to this resource and check if the response contains an 'access-control-allow-origin' header whose value matches the requesting hostname, if it does it executes the request (a bit simplified, there are a couple more headers)
  54. 1.<script> 2. var fragmentString = location.hash.substr(1); 3. var fragment =

    {}; 4. var fragmentItemStrings = fragmentString.split('&'); 5. for (var i in fragmentItemStrings) { 6. var fragmentItem = fragmentItemStrings[i].split('='); 7. if (fragmentItem.length !== 2) { 8. continue; 9. } 10. fragment[fragmentItem[0]] = fragmentItem[1]; 11. } 12. opener.setAccessToken(fragment['access_token']); 13. window.close(); 14.</script> a bit of code how to get the access token out of the fragment
  55. State oauth2 also has some additional features that are very

    important. most importantly and often overlooked the state query parameter that can and should be added the whole authorization redirects. its very simple if you redirect the user to the authorization endpoint and add a state parameter, you get the same value in the state parameter back when the api redirects the user back to you
  56. CSRF this is very important for security and cross site

    request forgery protection, use it to check that the session where redirect to the authorization endpoint of the api started is the same session as where the redirect back to the client arrived and no attacker got between that and redirected the response with the authorization code or access token to his one session, so that he gets access to the the api data of another user