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

OAuth 2.0 Simplified - PDXNode May 2018

OAuth 2.0 Simplified - PDXNode May 2018

OAuth 2.0 Simplified: OAuth 2.0 has become the industry standard in providing secure access to web APIs. OAuth allows users to grant external applications access to their data, such as profile data, photos, and email, without compromising account security. However, OAuth can be intimidating when first starting out. In this talk, you'll learn about the various OAuth workflows, and get a simplified overview of the framework, highlighting a few typical use cases.

Aaron Parecki

May 10, 2018
Tweet

More Decks by Aaron Parecki

Other Decks in Technology

Transcript

  1. Before OAuth • Apps stored the user’s password • Apps

    got complete access to a user’s account • Users couldn’t revoke access except by changing their password • Compromised apps exposed the user’s password
  2. 6

  3. 7

  4. 9 Hotel key cards, but for apps 9 The door

    doesn’t need to know who you are
  5. Obtaining an Access Token Applications use an OAuth flow to

    obtain an access token • Authorization Code Flow: web apps, native apps • Device Flow: browserless or input-constrained devices • Password: not really OAuth, only for first-party apps • Refresh Token: getting a new access token when it expires
  6. Using an Access Token 12 POST /resource/1/update HTTP/1.1 Authorization: Bearer

    RsT5OjbzRn430zqMLgV3Ia Host: api.authorization-server.com description=Hello+World
  7. Registering an Application • Registering an application gives you a

    client_id • and if the application is not a "public client", then also a client_secret • These identify the application to the service.
  8. Client ID and Secret 17 • A "public client" means

    anything where the client cannot keep strings confidential. • Javascript clients: "view source" • Native apps: can decompile and see strings • No secret is used for these clients, only the ID
  9. Build the "Log in" link • response_type=code - indicates that

    your client expects to receive an authorization code • client_id=CLIENT_ID - The client ID you received when you first created the application • redirect_uri=REDIRECT_URI - Indicates the URL to return the user to after authorization is complete, such as https://example-app.com/callback • scope=photos - A space-separated string indicating which parts of the user's account you wish to access • state=1234zyx - A random string generated by your application, which you'll verify later
  10. 21

  11. If User Allows 22 https://example.com/auth?code=AUTH_CODE_HERE&state=1234zyx The user is redirected back

    to the application with an authorization code https://example.com/auth?error=access_denied The user is redirected back to the application with an error code If User Denies
  12. Verify State • The application verifies the state matches the

    expected value • (or extracts session data from the state)
  13. Exchange the Code for an Access Token • grant_type=authorization_code -

    indicates that this request contains an authorization code • code=CODE_FROM_QUERY - Include the authorization code from the query string of this request • redirect_uri=REDIRECT_URI - This must match the redirect_uri used in the original request • client_id=CLIENT_ID - The client ID you received when you first created the application • client_secret=CLIENT_SECRET - Since this request is made from server- side code, the secret is included
  14. Exchange the Code for an Access Token 25 POST https://api.authorization-server.com/token

    grant_type=authorization_code& code=AUTH_CODE_HERE& redirect_uri=REDIRECT_URI& client_id=CLIENT_ID& client_secret=CLIENT_SECRET
  15. Exchange the Code for an Access Token 26 { "access_token":"RsT5OjbzRn430zqMLgV3Ia",

    "expires_in":3600, "refresh_token":"64d049f8b21191e12522d5d96d5641af5e8" } The server replies with an access token and expiration time or if there was an error: {"error":"invalid_request"}
  16. example-app.com Connect with Google Client accounts.google.com email password Authorization Server

    accounts.google.com Yes No Allow Example App to access your public profile and contacts? example-app.com/callback Loading… Direct the user to the authorization server response_type=code &redirect_uri=example-app.com/callback &state=00000 User signs in Authorization server redirects back to the app code=XYZ123&state=00000 Exchange authorization code for an access token
  17. Build the "Log in" link • response_type=code - indicates that

    your client expects to receive an authorization code • client_id=CLIENT_ID - The client ID you received when you first created the application • redirect_uri=REDIRECT_URI - Indicates the URI to return the user to after authorization is complete, such as https://example-app.com/callback • scope=photos - A space-separated string indicating which parts of the user's account you wish to access • state=1234zyx - A random string generated by your application, which you'll verify later
  18. 31

  19. If User Allows 32 https://example.com/auth?code=AUTH_CODE_HERE&state=1234zyx The user is redirected back

    to the application with an authorization code https://example.com/auth?error=access_denied The user is redirected back to the application with an error code If User Denies
  20. Verify State • The application verifies the state matches the

    expected value • (or extracts session data from the state)
  21. Exchange the Code for an Access Token • grant_type=authorization_code -

    indicates that this request contains an authorization code • code=CODE_FROM_QUERY - Include the authorization code from the query string of this request • redirect_uri=REDIRECT_URI - This must match the redirect_uri used in the original request • client_id=CLIENT_ID - The client ID you received when you first created the application
  22. Exchange the Code for an Access Token 35 POST https://api.authorization-server.com/token

    grant_type=authorization_code& code=AUTH_CODE_HERE& redirect_uri=REDIRECT_URI& client_id=CLIENT_ID Note: no client secret used by Javascript apps!
  23. Exchange the Code for an Access Token 36 { "access_token":"RsT5OjbzRn430zqMLgV3Ia",

    "expires_in":3600 } The server replies with an access token and expiration time or if there was an error: {"error":"invalid_request"} Note: no refresh token for Javascript apps!
  24. Redirect URLs for Native Apps • There is no built-in

    security for redirect URIs like when we use DNS, • since any app can claim any URL scheme. • So instead, we add an extra step at the beginning to solve this:
  25. PKCE: Proof Key for Code Exchange 44 RFC 7636: Implemented

    by Google and a few others • First create a "code verifier", a random string 43-128 characters long. • Compute the SHA256 hash of the code verifier, call that the code challenge • Include code_challenge=XXXXXX and code_challenge_method=S256 in the initial authorization request • Send the code verifier when exchanging the authorization code for an access token • (For clients that can't support SHA256, include the plaintext verifier as the challenge, and set the method to "plain")
  26. Generate the Code Verifier 45 4A6hBupTkAtgbaQs39RSELUEqtSWTDTcRzVh1PpxD5YVKllU Generate a random string

    43-128 characters long ipSBt30y48l401NGbLjo026cqwsRQzR5KI40AuLAdZ8 The challenge is the SHA256 hash of the verifier string base64url(sha256(code_verifier)) Generate the Code Challenge
  27. Build the "Log in" link 46 https://authorization-server.com/auth? response_type=code& client_id=CLIENT_ID& redirect_uri=REDIRECT_URI&

    scope=photos& state=1234zyx& code_challenge=XXXXXXXXXXXXX& code_challenge_method=S256 Include the code challenge (the hashed value) in the request
  28. 47

  29. If User Allows 48 example://auth?code=AUTH_CODE_HERE&state=1234zyx The user is redirected back

    to the application with an authorization code example://auth?error=access_denied The user is redirected back to the application with an error code If User Denies
  30. Verify State • The application verifies the state matches the

    expected value • (or extracts session data from the state)
  31. Exchange the Code for an Access Token • grant_type=authorization_code -

    indicates that this request contains an authorization code • code=CODE_FROM_QUERY - Include the authorization code from the query string of this request • redirect_uri=REDIRECT_URI - This must match the redirect_uri used in the original request • client_id=CLIENT_ID - The client ID you received when you first created the application • code_verifier=VERIFIER_STRING - The plaintext code verifier initially created
  32. Exchange the Code for an Access Token 51 POST https://api.authorization-server.com/token

    grant_type=authorization_code& code=AUTH_CODE_HERE& redirect_uri=REDIRECT_URI& client_id=CLIENT_ID& code_verifier=VERIFIER_STRING Note: code verifier used in place of client secret
  33. Exchange the Code for an Access Token 52 { "access_token":"RsT5OjbzRn430zqMLgV3Ia",

    "expires_in":3600", "refresh_token":"64d049f8b2119a12522d5dd96d5641af5e8" } The server compares the code_verifier with the code_challenge that was in the request when it generated the authorization code, and responds with an access token.
  34. Exchange the Username and Password for a Token 54 POST

    https://api.authorization-server.com/token grant_type=password& username=USERNAME& password=PASSWORD& client_id=CLIENT_ID& client_secret=CLIENT_SECRET The user’s credentials are sent directly! Not a good idea for third party apps!
  35. Exchange the Client ID and Secret for a Token 56

    POST https://api.authorization-server.com/token grant_type=client_credentials& client_id=CLIENT_ID& client_secret=CLIENT_SECRET No user context in the request, so the access token can only be used to access the application’s resources
  36. Request a Device Code 59 { "device_code": "NGU5OWFiNjQ5YmQwNGY3YTdmZTEyNzQ3YzQ1YSA", "user_code": "BDWD-HQPK",

    "verification_uri": "https://example.com/device", "interval": 5, "expires_in": 1800 } The server responds with a new device code and user code, as well as the URL the user should visit to enter the code.
  37. 62

  38. Poll the Token Endpoint 64 { "error": "authorization_pending" } While

    the device waits for the user to enter the code and authorize the application, the device polls the token endpoint.
  39. 65

  40. 66

  41. 67

  42. Poll the Token Endpoint 68 { "access_token": "RsT5OjbzRn430zqMLgV3Ia", "expires_in": 3600,

    "refresh_token": "b7aab35e97298a060e0ede5b43ed1f70a8" } Once the user has logged in on their phone or computer, and authorized the application, the request will return an access token.
  43. What is a Refresh Token? • A special token used

    to get new access tokens • Usually requires scope: offline_access, tho that depends on the service
  44. Exchange the Code for an Access Token 72 POST https://authorization-server.com/token

    grant_type=authorization_code& code=AUTH_CODE_HERE& redirect_uri=REDIRECT_URI& client_id=CLIENT_ID& client_secret=CLIENT_SECRET
  45. Refresh Token in the Response 73 { "access_token": "RsT5OjbzRn430zqMLgV3Ia", "expires_in":

    3600, "refresh_token": "64d049f8b21191e12522d5d96d5641af5e8" }
  46. Further Reading • PKCE: Proof-Key for Code Exchange (RFC 7636)

    • oauth.net/2/pkce • OAuth for Native Apps (RFC 8252) • oauth.net/2/native-apps • Security Considerations (RFC 6819) • oauth.net/2/security-considerations • OpenID Connect • openid.net/connect • IndieAuth • indieauth.net