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

Api Protection

Api Protection

Building a secure API is one of the most common requirements in the market nowadays. Yet there are many strategies with their strengths and fallbacks, some simple, some complex. Let’s together walk through the existing strategies and take a look at a solution, that could, potentially, end this discussion once and for all.

Armen Mkrtchyan

October 27, 2017
Tweet

More Decks by Armen Mkrtchyan

Other Decks in Technology

Transcript

  1. noun to·ken \ ˈtō-kən \ TOKEN „something given or shown

    as a guarantee (as of authority, right, or identity)“
  2. STEP 2 - NGINX CONFIGURATION ... http { server {

    location /foo/bar { auth_basic "Protected Area"; auth_basic_user_file /etc/apache2/.htpasswd; } } } ...
  3. STEP 3 - USE Access url in the browser -

    fill in the dialog base64_encode('user:password') => d3BhbG1lcjp0ZXN0dGVzdA== GET / HTTP/1.1
 Host: example.com
 Authorization: Basic d3BhbG1lcjp0ZXN0dGVzdA== // embed in URL
 https://user:[email protected] 2 1 3
  4. STEP 3 - USE Access url in the browser -

    fill in the dialog base64_encode('user:password') => d3BhbG1lcjp0ZXN0dGVzdA== GET / HTTP/1.1
 Host: example.com
 Authorization: Basic d3BhbG1lcjp0ZXN0dGVzdA== // embed in URL
 https://user:[email protected] 2 1 3
  5. STEP 1 - INITIALISE POST /initiate HTTP/1.1
 Host: photos.example.net
 Authorization:

    OAuth realm="Photos", \
 oauth_consumer_key="dpf43f3p2l4k3l03", \
 oauth_signature_method="HMAC-SHA1", \
 oauth_timestamp="137131200", \
 oauth_nonce="wIjqoS", \
 oauth_callback="http%3A%2F%2Fclient.example.com%2Fready", \
 oauth_signature="74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D" \ HTTP/1.1 200 OK
 Content-Type: application/x-www-form-urlencoded
 oauth_token=hh5s93j4hdidpola&
 oauth_token_secret=hdhd0244k9j7ao03&
 oauth_callback_confirmed=true
  6. STEP 1 - INITIALISE POST /initiate HTTP/1.1
 Host: photos.example.net
 Authorization:

    OAuth realm="Photos", \
 oauth_consumer_key="dpf43f3p2l4k3l03", \
 oauth_signature_method="HMAC-SHA1", \
 oauth_timestamp="137131200", \
 oauth_nonce="wIjqoS", \
 oauth_callback="http%3A%2F%2Fclient.example.com%2Fready", \
 oauth_signature="74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D" \ HTTP/1.1 200 OK
 Content-Type: application/x-www-form-urlencoded
 oauth_token=hh5s93j4hdidpola&
 oauth_token_secret=hdhd0244k9j7ao03&
 oauth_callback_confirmed=true
  7. STEP 2 - AUTHORIZATION GET /authorize?oauth_token=hh5s93j4hdidpola HTTP/1.1
 Host: photos.example.net //

    Asks for username and login and redirects to http://<oauth_callback>? \
 oauth_token=hh5s93j4hdidpola& \
 oauth_verifier=hfdp7dh39dks9884
  8. STEP 3 - TOKEN POST /token HTTP/1.1 Host: photos.example.net Authorization:

    OAuth realm="Photos", oauth_consumer_key="dpf43f3p2l4k3l03", \ oauth_token="hh5s93j4hdidpola", \ oauth_signature_method="HMAC-SHA1", \ oauth_timestamp="137131201", \ oauth_nonce="walatlh", \ oauth_verifier="hfdp7dh39dks9884", \ oauth_signature="gKgrFCywp7rO0OXSjdot%2FIHF7IU%3D" // redirects back with to http://<oauth_callback>? \ oauth_token=hh5s93j4hdidpola& \ oauth_verifier=hfdp7dh39dks9884
  9. STEP 4 - USING TOKEN GET /photos?file=vacation.jpg&size=original HTTP/1.1 Host: photos.example.net

    Authorization: OAuth realm="Photos", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_token="nnch734d00sl2jdk", oauth_signature_method="HMAC-SHA1", oauth_timestamp="137131202", oauth_nonce="chapoH", oauth_signature="MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D"
  10. AUTHORIZAION CODE - STEP 1 POST /authorize HTTP/1.1 Host: photos.example.net

    Content-Type: application/x-www-form-urlencoded response_type=code& \ client_id=CLIENT_ID& \ redirect_uri=https://client.example.com/cb& \ scope=email,birthday& \ state=csrf_string // Asks for user authorisation and redirects back HTTP/1.1 302 Found Location: https://client.example.com/cb?code=CODE&state=csrf_string
  11. AUTHORIZAION CODE - STEP 2 POST /token HTTP/1.1 Host: photos.example.net

    Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& \ code=CODE& \ redirect_uri=https://client.example.com/cb& \ client_id=CLIENT_id& Content-Type: application/json;charset=UTF-8 { "access_token":"2YotnFZFEjr1zCsicMWpAA", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA" }
  12. POST /token HTTP/1.1 Host: photos.example.net Content-Type: application/x-www-form-urlencoded grant_type=client_credentials& \ client_id=CLIENT_id&

    \ client_secret=CLIENT_SECRET Content-Type: application/json;charset=UTF-8 { "access_token":"2YotnFZFEjr1zCsicMWpAB", "expires_in":3600 }
  13. JWT

  14. • ISS - ISSUER (AKA ORIGIN) • SUB - SUBJECT

    (AKA USER_ID) • AUD - AUDIENCE (AKA CLIENT_ID) • EXP - EXPIRES AT • IAT - ISSUED AT JWT STANDARD CLAIMS
  15. BASIC AUTH - NICE, PASS INVOLVED OAUTH1 - TOO COMPLEX

    OAUTH2 - SOLVES THE PROBLEM, BUT... SELF-INVENTED - NO* JWT - OVER-SIMPLISTIC *unless you really know what you are doing
  16. 37signals, Asana, Amazon, Auth0, Azure, Bitbucket, Bitly, BufferApp, Clever, DeviantArt,

    Discogs, Disqus, Dropbox, EVE Online, Eventbrite, Facebook, FI-WARE, Flickr, Foursquare, GitHub, GitLab, Google, Hubic, Instagram, itembase, Jira, Linkedin, Mail.ru, Odnoklassniki, PayPal, QQ, Reddit, Salesforce, SensioLabs Connect, Sina Weibo, Spotify, Soundcloud, Stack Exchange, Stereomood, Strava, Toshl, Trello, Twitch, Twitter, Wunderlist, Vkontakte, Windows Live, XING, Yahoo, Yandex HTTPS://GITHUB.COM/HWI/ HWIOAUTHBUNDLE
  17. OAUTH2 + IDENTITY LAYER DISCOVERY DYNAMIC CLIENT REGISTRATION IMPLEMENTATION CERTIFICATION

    ID_TOKEN STANDARD CLAIMS SESSION MANAGEMENT JWKS FORM POST RESPONSE MODE
  18. AUTHORIZAION CODE - STEP 1 POST /authorize HTTP/1.1 Host: photos.example.net

    Content-Type: application/x-www-form-urlencoded response_type=code& \ client_id=CLIENT_ID& \ redirect_uri=https://client.example.com/cb& \ scope=email,birthday,openid& \ state=csrf_string // Asks for user authorisation and redirects back HTTP/1.1 302 Found Location: https://client.example.com/cb?code=CODE&state=csrf_string
  19. { "iss": "http://server.example.com", "sub": "248289761001", // aka user_id "aud": "s6BhdRkqt3",

    // aka client_id "nonce": "n-0S6_WzA2Mj", // aka CSRF token "exp": 1311281970, "iat": 1311280970 }
  20. GET /userinfo HTTP/1.1 Authorization: Bearer SlAV3...2hkKG { "sub": "248289761001", "name":

    "Jane Doe", "given_name": "Jane", "family_name": "Doe", "preferred_username": "j.doe", "email": "[email protected]", "picture": "http://example.com/janedoe/me.jpg" } IT'S A STANDARD!!! (SECTION 5.2)
  21. GET /userinfo HTTP/1.1 Authorization: Bearer SlAV3...2hkKG { "sub": "248289761001", "name":

    "Jane Doe", "given_name": "Jane", "family_name": "Doe", "preferred_username": "j.doe", "email": "[email protected]", "picture": "http://example.com/janedoe/me.jpg" }
  22. GET /.well-known/openid-configuration HTTP/1.1 Host: accounts.google.com Authorization: Bearer SlAV3...2hkKG { "issuer":

    "https://accounts.google.com", "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth", "token_endpoint": "https://www.googleapis.com/oauth2/v4/token", "userinfo_endpoint": "https://www.googleapis.com/oauth2/v3/userinfo", "revocation_endpoint": "https://accounts.google.com/o/oauth2/revoke", "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs", "response_types_supported": [ "code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token", "none" ], "scopes_supported": [ "openid", "email", "profile" ], "claims_supported": [ "aud", "email", "email_verified", "exp", "family_name", "given_name", "iat", "iss", "locale", "name", "picture", "sub" ] }
  23. „I might be no body, but wait ‘til I’m together

    like a symphony.“ – IMMORTAL TECHNIQUE – “THE PROPHECY”