Securing Your APIs with OAuth 2.0

11954e59b49809173d48133ec4047fce?s=47 Aaron Parecki
September 20, 2019

Securing Your APIs with OAuth 2.0

Presented at API Days Melbourne 2019

In this talk, you’ll learn how to use OAuth 2.0 to secure access to your APIs. OAuth is an authorization protocol which enables applications to access data on behalf of users without needing to know their username and password. This enables many use cases such as easily enabling multi-factor authorization for your users, and better separation of concerns of all your backend services. We’ll look at how to use JWT access tokens, as well as the tradeoffs that come with them. We’ll look at how to design scopes that allow granular access to various parts of your backend services. We’ll also look at how to design a microservices architecture protected by OAuth at a gateway.

11954e59b49809173d48133ec4047fce?s=128

Aaron Parecki

September 20, 2019
Tweet

Transcript

  1. Securing Your APIs with OAuth 2.0 AARON PARECKI @aaronpk aaronpk.com

  2. Specs are not good tutorials!

  3. RFC6749 RFC6750 CLIENT TYPE AUTH METHOD GRANT TYPE RFC6819 RFC7009

    RFC7592 RFC7662 RFC7636 RFC7591 RFC7519 BUILDING YOUR APPLICATION RFC8252 OIDC RFC8414 STATE PARAM TLS CSRF UMA 2 FAPI RFC7515 RFC7516 RFC7517 RFC7518 TOKEN BINDING POP SECURITY BCP CIBA HTTP SIGNING MUTUAL TLS SPA BCP JARM JAR TOKEN EXCHANGE DPOP
  4. @aaronpk THE PASSWORD ANTI-PATTERN

  5. @aaronpk THE PASSWORD ANTI-PATTERN facebook.com ~2010

  6. @aaronpk

  7. @aaronpk so... how can I let an app access my

    data without giving it my password?
  8. @aaronpk An open standard for authorization

  9. @aaronpk https://yelp.com/

  10. but… OAuth doesn’t tell the app who logged in

  11. None
  12. @aaronpk A HOTEL KEY CARD, FOR APPS Authorization Server Access

    Token Resource Server (API)
  13. Authentication Authorization provides user identity provides delegated access

  14. @aaronpk https://gmail.com

  15. @aaronpk https://accounts.google.com/oauth/authorize?response_ty

  16. @aaronpk https://accounts.google.com/oauth/authorize?response_ty

  17. @aaronpk https://accounts.google.com/oauth/authorize?response_ty

  18. @aaronpk https://gmail.com

  19. @aaronpk HOW OAUTH WORKS

  20. @aaronpk 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 ▸ Client Credentials: for machine-to-machine authentication
  21. @aaronpk POST /resource/1/update HTTP/1.1 Authorization: Bearer RsT5OjbzRn430zqMLgV3Ia Host: api.authorization-server.com description=Hello+World

    USING AN ACCESS TOKEN
  22. @aaronpk ROLES IN OAUTH OAuth Server (Authorization Server) aka the

    token factory API (Resource Server) The Application (Client) The User (Resource Owner) Device (User Agent)
  23. AUTHORIZATION CODE GRANT TYPE:

  24. User: I’d like to use this great app App: Please

    go to the authorization server to grant me access User: I’d like to log in to “Yelp”, it wants to access my contacts AS: Here is a temporary code the app can use App: Here is the temporary code, and my secret, please give me a token User: Here is the temporary code, please use this to get a token AS: Here is an access token! App: Please let me access this user’s data with this access token! User Agent App OAuth Server API ?
  25. Front Channel Back Channel https://accounts.google.com/?... Passing data via the browser's

    address bar The user, or malicious software, can modify the requests and responses Sent from client to server HTTPS request from client to server, so requests cannot be tampered with
  26. Back Channel Benefits ‣ The application knows it's talking to

    the right server ‣ Connection from app to server can't be tampered with ‣ Response from the server can be trusted because it came back in the same connection
  27. OAuth Server OAuth Client Passing Data via the Back Channel

  28. OAuth Server OAuth Client Passing Data via the Front Channel

  29. Front Channel Benefits https://accounts.google.com/?... ‣ Lets the server prompt the

    user for additional auth factors without the client involved ‣ The user being involved enables them to give consent ‣ Doesn't require the receiver to have a publicly routable IP
 (e.g. can work on a phone)
  30. The app builds the auth link https://authorization-server.com/auth • response_type=code -

    indicates that your app 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=contacts - 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 Front Channel
  31. The app builds the auth link https://authorization-server.com/auth? response_type=code& client_id=CLIENT_ID& redirect_uri=REDIRECT_URI&

    scope=contacts& state=1234zyx Front Channel
  32. Front Channel

  33. The user is redirected back to the application with an

    authorization code https://example.com/callback?error=access_denied&state=1234xyz The user is redirected back to the application with an error code If User Denies If User Allows https://example.com/callback? code=AUTH_CODE_HERE& state=1234zyx Front Channel
  34. Verify State • The application verifies the state matches the

    value it started with • This lets the application have more confidence that it isn't trying to exchange an attacker's authorization code The app must do this because it received the authorization code via the front channel! Front Channel
  35. Exchange the Code for an Access Token POST https://api.authorization-server.com/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 Back Channel
  36. Exchange the Code for an Access Token POST https://api.authorization-server.com/token Content-type:

    application/x-www-form-urlencoded grant_type=authorization_code& code=AUTH_CODE_HERE& redirect_uri=REDIRECT_URI& client_id=CLIENT_ID& client_secret=CLIENT_SECRET Back Channel
  37. Exchange the Code for an Access Token { "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"} Back Channel
  38. Public Clients Confidential Clients Application running on a server Has

    the ability to keep strings secret since code is running in a trusted environment The application can't keep strings secret JavaScript/Single-Page apps: "view source" Native apps: decompile and extract strings
  39. Problem: • The authorization server returns the authorization code in

    the front channel • so it can't guarantee it was actually received by the correct application • it needs a way to verify that the correct application is using it to get a token • Normally the client_secret solves this, but we can't use a secret!
  40. @aaronpk PKCE PROOF-KEY FOR CODE EXCHANGE RFC 7636 (pronounced "pixie")

  41. User: I’d like to use this great app App: Please

    go to the authorization server to grant me access, take this hash with you User: I’d like to log in to this app, here's the hashed secret it gave me AS: Here is a temporary code the app can use App: Here's the code, and the plaintext secret, please give me a token User: Here is the temporary code, please use this to get a token AS: Let me verify the hash of that secret... ok here is an access token! App: Please let me access this user’s data with this access token! App: Hang on while I generate a new secret and hash it User Agent App OAuth Server API ?
  42. OAuth Server (Authorization Server) aka the token factory API (Resource

    Server) The Application (Client) The User's Device (User Agent)
  43. OAuth Server (Authorization Server) aka the token factory API (Resource

    Server) The Application (Client) The User's Device (User Agent)
  44. SCOPE

  45. https://accounts.google.com/oauth/authorize?response_type

  46. https://arstechnica.com/information-technology/2017/05/dont-trust-oauth-why-the-google-docs-worm-was-so-convincing/

  47. None
  48. None
  49. None
  50. None
  51. None
  52. None
  53. None
  54. None
  55. None
  56. None
  57. Scope • Allows an application to request a limited-capability access

    token • Limits what an access token can do within what a user is already allowed to do • Is not a way to build a permissions system
  58. ACCESS TOKENS

  59. Types of Access Tokens MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEwMDAsI mlzcyI6Imh0dHBzOi8vYXV0aG9yaXphdGlvbi1zZXJ2ZXIuY29tIiw iY2lkIjoiaHR0cHM6Ly9leGFtcGxlLWFwcC5jb20iLCJpYXQiOjE0N zAwMDI3MDMsImV4cCI6MTUyOTE3NDg1MSwic2NvcGUiOiJyZWFkIHd yaXRlIn0.QiIrnmaC4VrbAYAsu0YPeuJ992p20fSxrXWPLw-gkFA

    Reference Self-Encoded (e.g. JWT)
  60. Reference Tokens MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3 * user_id * expiration * permissions *

    ...
  61. Self-Encoded Tokens eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEwMDAsI mlzcyI6Imh0dHBzOi8vYXV0aG9yaXphdGlvbi1zZXJ2ZXIuY29tIiw iY2lkIjoiaHR0cHM6Ly9leGFtcGxlLWFwcC5jb20iLCJpYXQiOjE0N zAwMDI3MDMsImV4cCI6MTUyOTE3NDg1MSwic2NvcGUiOiJyZWFkIHd yaXRlIn0.QiIrnmaC4VrbAYAsu0YPeuJ992p20fSxrXWPLw-gkFA { "sub": "{USER_ID}",

    "aud": "{CLIENT_ID}", "exp": 1524240821, "scope": "create" }
  62. are you building an app? are you building an API?

    Authorization: Bearer RsT5OjbzRn430zqMLgV3Ia just use the token parse/extract/introspect the token { "sub": "{USER_ID}", "aud": "{CLIENT_ID}", "exp": 1524240821, "scp": "create" }
  63. only the API should try to understand
 access tokens

  64. Types of Access Tokens MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEwMDAsI mlzcyI6Imh0dHBzOi8vYXV0aG9yaXphdGlvbi1zZXJ2ZXIuY29tIiw iY2lkIjoiaHR0cHM6Ly9leGFtcGxlLWFwcC5jb20iLCJpYXQiOjE0N zAwMDI3MDMsImV4cCI6MTUyOTE3NDg1MSwic2NvcGUiOiJyZWFkIHd yaXRlIn0.QiIrnmaC4VrbAYAsu0YPeuJ992p20fSxrXWPLw-gkFA

    Reference Self-Encoded (e.g. JWT)
  65. Pros • Can be revoked by deleting from the database

    • Can easily show a list of active tokens to the user Reference Tokens Cons • Requires storing all active tokens • API must check the validity with either a DB lookup or HTTP request Best for • Small scale APIs with an integrated OAuth server
  66. Pros • Requires no storage • Better separation of concerns

    (no shared storage between authorization server and API) • Can be validated at the API without a DB/HTTP lookup Self-Encoded Tokens Cons • Cannot be revoked without storing additional information • Cannot get a list of all active tokens Best for • Large-scale distributed architectures, and using an external OAuth server
  67. A JWT Access Token eyJraWQiOiJvQ1JjR3RxVDhRV2tJR0MyVXpmcEZUczVqSkdnM00zSTNOMHgtZDJhSFNNIiwiYWxn IjoiUlMyNTYifQ.eyJ2ZXIiOjEsImp0aSI6IkFULkp3eVRTcTlqNDU0bDNTNmRTM1VTV1hMVVpwe kdKdWNSd1ZEbFZCNWNIc3cuVVM1V1NGYVFiQllUMC9GM2tjMG8vK1ZUY3VZZzdwVnZqZXZTT3hkU HhCMD0iLCJpc3MiOiJodHRwczovL2Rldi0zOTYzNDMub2t0YXByZXZpZXcuY29tL29hdXRoMi9kZ WZhdWx0IiwiYXVkIjoiYXBpOi8vZGVmYXVsdCIsImlhdCI6MTU0MzgwMzAyNSwiZXhwIjoxNTQzO DA2NjI1LCJjaWQiOiIwb2FoenBwM3RjcEZyZmNXSTBoNyIsInVpZCI6IjAwdWkwZmpraWV5TDQ2b

    WEwMGg3Iiwic2NwIjpbIm9mZmxpbmVfYWNjZXNzIiwicGhvdG8iXSwic3ViIjoiaW5xdWlzaXRpd mUtYWxiYXRyb3NzQGV4YW1wbGUuY29tIn0.ncVkzcc6qrFJSXE3-5UsRu_kHvbwIMKYL3PFaMwRe YTquPAcOQ8t93xF0bxbS8wrP0udCDvk6eYq4VbjoFdD59Yy6ltz0OKQl3- g8uFg2RwqTBMOKR0mYtQH0RCr9ORhSsmKolaDDt4TcRX78ZOAyhZ_Qg_UcEoHM4uZikpzBJYpYKb CCfbx-6FzYyHuvevSFzURISYpSHv3nbzirkEzKbOv7eZlg1cCYBdUoGuVBskyHxfMxFpoKQU3mwI FdlQJR8LZ8hA_5ZdYjjMeSXfjnhlP2rppJiHy1NreGXXcUsUA74V2t_keY44deTrnPgoFOSe9Ich Wqcj6sDMDutC4ag
  68. A JWT Access Token { "typ": "JWT", "alg": "RS256", "kid":

    "oCRcGtqT8QWkIGC2UzfpFTs5jJGg3M3I3N0x-d2aHSM" } { "ver": 1, "jti": "AT.JwyTSq9j454l3S6dS3USWXLUZpzGJucRwVDlVB5cHsw.US5WSFaQbBYT0/F3kc0o/+VTcuYg7pVvjevSOxdPxB0=", "iss": "https://dev-396343.oktapreview.com/oauth2/default", "aud": "api://default", "iat": 1543803025, "exp": 1543806625, "cid": "0oahzpp3tcpFrfcWI0h7", "uid": "00ui0fjkieyL46ma00h7", "scp": [ "offline_access", "photo" ], "sub": "inquisitive-albatross@example.com" } header claims
  69. None
  70. None
  71. Libraries!

  72. Access Token Validation The Fast Way The Strong Way Inspect

    the JWT Check the expiration timestamp Validate the cryptographic signature Check the token at the introspection endpoint eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZS I6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6ImI5ZDRhNzViLTA2MDMtNDgxYy1hM jgyLTY3YTk0NDJiNGRkNiIsImlhdCI6MTUzMjQwMDkyMiwiZXhwIjoxNTMyNDA0NTIyfQ.S jYROEt8lZpEOq1eKh3OxRmRk3xttOXZeD5yW8aW2k8 { "sub": "1234567890", "name": "John Doe", "admin": true, "jti": "b9d4a75b-0603-481c-a282-67a9442b4dd6", "iat": 1532400922, "exp": 1532404522 } POST https://authorization-server.com/introspect token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3OD &client_id={CLIENT_ID} &client_secret={CLIENT_SECRET}
  73. Rejecting Revoked Tokens 1:00 2:00 3:00 4:00 5:00 6:00 7:00

    expired 0:00 Local Validation Remote Introspection User revokes application
  74. API Gateway Token Validation API Gateway CUSTOMER API BILLING API

    ORDER API LOCAL VALIDATION TOKEN INTROSPECTION
  75. How long should access tokens last?

  76. @aaronpk DIFFERENT LIFETIMES FOR DIFFERENT USERS/SCOPES ACCESS TOKEN 1 HOUR

    REFRESH TOKEN 24 HOURS ACCESS TOKEN 24 HOURS REFRESH TOKEN UNLIMITED ACCESS TOKEN 4 HOURS Admin Users Consumer Users Privileged Scopes Requires admin users to log in every day Best UX, log in once and appear to be logged in forever Prevent applications from using privileged scopes without the user being present
  77. RESOURCES

  78. oauth.com

  79. oauth.com/playground

  80. oauth.net

  81. developer.okta.com/signup

  82. oauth2simplified.com

  83. Thank You! @aaronpk developer.okta.com