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

Building Clients for OpenID Connect/OAuth 2.0-based Systems

Building Clients for OpenID Connect/OAuth 2.0-based Systems

Dominick Baier

September 24, 2019
Tweet

More Decks by Dominick Baier

Other Decks in Programming

Transcript

  1. Building Clients for OpenID Connect/OAuth 2-based Systems Dominick Baier @leastprivilege

    https://github.com/leastprivilege/AspNetCoreSecuritySamples
  2. 2 @leastprivilege / @brocklallen Me • Independent Consultant – Specializing

    on Application Security Architectures – Working with Software Development Teams (ISVs and in-house) • Co-Creator of IdentityServer & IdentityModel OSS Project – Certified OpenID Connect & OAuth 2.0 Implementation for .NET – https://identityserver.io • Co-Creator of PolicyServer – Modern Authorization Solution – https://policyserver.io email [email protected] blog https://leastprivilege.com twitter @leastprivilege slides https://speakerdeck.com/leastprivilege
  3. 3 @leastprivilege / @brocklallen Objectives • Discuss common challenges for

    building clients • Look at recommended approaches for several client types – server to server – web applications – native/mobile applications – SPAs • Give you references to further reading material
  4. 5 @leastprivilege / @brocklallen Timeline 2005 SAML 2.0 2007 2009

    2012 2014 2015 2017 2019 Future OpenID Connect Session Management OpenID Connect Front-Channel Notifications OpenID Connect Back-Channel Notifications Authentication Method Reference Values OAuth 2.0 for Native Apps OAuth 2.0 Browser-based Apps OAuth 2.0 Security Topics BCP OAuth 2.0 Incremental AuthZ OAuth 2.0 Token Exchange OAuth 2.0 Mutual TLS OAuth 2.0 Device Flow OAuth 2.0 Resource Indicators OAuth 1.0 WS-Federation 1.2 OAuth 1.0a OAuth 2.0 Bearer Tokens OpenID Connect Core OpenID Connect Discovery OpenID Connect Dynamic Registration OAuth 2.0 Assertion Framework OAuth 2.0 Dynamic Client Registration OAuth 2.0 Token Introspection JSON Web Token (JWT) OAuth 2.0 JSON Web Token (JWT) Profile OAuth 2.0 SAML 2.0 Profile OAuth 2.0 PKCE
  5. 6 @leastprivilege / @brocklallen The Big Picture Browser Native App

    Server App "Thing" Web App Web API Web API Web API Security Token Service 1 2 1 public client 2 confidential client 1 2 2
  6. 8 @leastprivilege / @brocklallen Server to Server Communication APIs Authorization

    Server Scopes: api1, api2 api3… client_id=client1, client_secret=***, scope=api1 api2 access token access token
  7. 9 @leastprivilege / @brocklallen Access Tokens { "typ": "at+jwt", "alg":

    "RS256" "kid": "1" } { "iss": "https://my_issuer", "exp": "1340819380", "aud": "invoice.api", "client_id": "client1", } Header Payload
  8. 10 @leastprivilege / @brocklallen Use Token • Token (typically) transmitted

    via Authorization header – form body or query string as alternative Authorization: Bearer <token> GET /service/resource https://tools.ietf.org/html/rfc6750
  9. 11 @leastprivilege / @brocklallen Token Management • Store tokens server-side

    – in-memory, distributed cache, cookie, session storage, database… • Pro-active – keep track of expiration and renew token ahead of time • Re-active – wait for 401, renew, re-send
  10. 12 @leastprivilege / @brocklallen User-Centric Clients • Typical Pattern –

    authenticate user – start/join session – make API calls on behalf of the user • Typical client challenges – how to securely retrieve access token – access token storage & lifetime management – session management
  11. 13 @leastprivilege / @brocklallen Authorization Code Flow • Front-Channel –

    UI redirect to authorize endpoint – starts/joins a session – consent (if enabled) – returns authorization code • Back-Channel – exchange of authorization with access token – typically involves client authentication
  12. 14 @leastprivilege / @brocklallen Authorization Code Flow Request GET /authorize

    ?client_id=app1 &redirect_uri=https://app.com/cb &response_type=code &scope=openid email api1 api2
  13. 16 @leastprivilege / @brocklallen Retrieving the Access Token • Exchange

    code for access token – using client id and secret code (client_id:client_secret) { id_token: "xxae…988", access_token: "xyz…123", expires_in: 3600, token_type: "Bearer" }
  14. 17 @leastprivilege / @brocklallen Issues with Code Flow • Code

    substitution attack – client can be tricked into using its client secret with a leaked/stolen code • Different mitigation approaches – OpenID Connect: Hybrid Flow – OAuth2: Proof Key for Code Exchange (PKCE)
  15. 18 @leastprivilege / @brocklallen Approach 1: Hybrid Flow Request GET

    /authorize ?client_id=app1 &redirect_uri=https://app.com/cb &response_type=code id_token &response_mode=form_post &nonce=j1y…a23 &scope=openid email api1 api2
  16. 19 @leastprivilege / @brocklallen Approach 1: Hybrid Flow Response <form>

    <input type="hidden" name="id_token" value="xjsj…aas" /> <input type="hidden" name="code" value="i8j1…jj19" /> </form> POST /cb cryptographically linked via c_hash
  17. 20 @leastprivilege / @brocklallen Issues with Hybrid Flow • Heavier

    client libraries – id_token validation – cryptographic linking of artifacts • Identity token via front channel – might leak identity information – at least sub
  18. 21 @leastprivilege / @brocklallen Approach 2: PKCE Front-Channel GET /authorize

    ?client_id=app1 &redirect_uri=https://app.com/cb &response_type=code &scope=openid email api1 api2 &code_challenge=xyz code_verifier = random number code_challenge = hash(code_verifier) https://tools.ietf.org/html/rfc7636
  19. 22 @leastprivilege / @brocklallen Approach 2: PKCE Back-Channel • Pass

    code verifier in addition to client ID and secret code, code verifier (client_id:client_secret) { id_token: "xxae…988", access_token: "xyz…123", expires_in: 3600, token_type: "Bearer" }
  20. 23 @leastprivilege / @brocklallen Access Token Lifetime Management • Access

    tokens have finite lifetimes – requesting a new token requires browser round trip to authorization server – should be as short lived as possible • Refresh tokens allow renewal semantics – no user interaction required – typically combined with a revocation feature
  21. 24 @leastprivilege / @brocklallen Requesting a Refresh Token GET /authorize

    ?client_id=app1 &redirect_uri=https://app.com/cb &response_type=code &scope=openid email api1 offline_access
  22. 25 @leastprivilege / @brocklallen Retrieving the Access Token (w/ Refresh

    Token) code (client_id:client_secret) { id_token: "xxae…988", access_token: "xyz…123", refresh_token: "jdj9…192j", expires_in: 3600, token_type: "Bearer" }
  23. 26 @leastprivilege / @brocklallen Refreshing an Access Token refresh_token (client_id:client_secret)

    { id_token: "xxae…988", access_token: "xyz…123", refresh_token: "jdj9…192j", expires_in: 3600, token_type: "Bearer" }
  24. 28 @leastprivilege / @brocklallen Token Revocation • Endpoint to programmatically

    revoke tokens (RFC 7009) – reference tokens – refresh tokens /revoke?token=a19..18a
  25. 29 @leastprivilege / @brocklallen ASP.NET Core OpenID Connect Client •

    Supports both Hybrid Flow and PKCE – PKCE recommended • Token storage using session mechanism – can revoke refresh tokens at logout time (if not needed anymore) • Automatic token management by plugging in IdentityModel.AspNetCore – https://github.com/IdentityModel/IdentityModel.AspNetCore
  26. 30 @leastprivilege / @brocklallen Public Clients • So far we

    only looked at server-based clients – typically unique client IDs – can store a secret securely • Public clients cannot store a client secret securely – e.g. SPAs, mobile apps – 1:many mapping of client id to instance • Dynamic client registration can turn public into confidential client – additional bootstrapping infrastructure necessary
  27. 31 @leastprivilege / @brocklallen Native/Mobile Applications • Applications that have

    access to native platform APIs – desktop or mobile • "OAuth 2.0 for native Applications" – https://tools.ietf.org/html/rfc8252
  28. 32 @leastprivilege / @brocklallen Anti Pattern: Resource Owner Password Flow

    Username Password Login username/password token token trust Token service API 1 2 3
  29. 33 @leastprivilege / @brocklallen Using a browser for driving the

    authentication workflow (aka AppAuth) authentication request render UI & workflow
  30. 34 @leastprivilege / @brocklallen Request GET /authorize ?client_id=nativeapp &scope=openid profile

    api1 api2 offline_access &redirect_uri=com.mycompany.nativeapp://cb &response_type=code &code_challenge=x929..1921
  31. 36 @leastprivilege / @brocklallen Token Management • Tokens should be

    stored using secure data storage provided by OS – e.g. KeyChain on iOS, DPAPI on Windows… – some support additional security mechanisms (e.g. biometrics) • Refresh can be automated by client libraries – e.g. using HTTP message handler & HttpClient • Tokens can be revoked when not needed anymore – logout – uninstall
  32. 37 @leastprivilege / @brocklallen Client Libraries • Native libraries –

    https://github.com/openid/AppAuth-iOS – https://github.com/openid/AppAuth-Android • C# .NET standard library (desktop .NET, UWP, mobile, iOS, Android) – https://github.com/IdentityModel/IdentityModel.OidcClient2 – https://github.com/IdentityModel/IdentityModel.OidcClient.Samples
  33. 38 @leastprivilege / @brocklallen Browser-based Clients (aka SPAs) • The

    most problematic client type from a security point of view – but also most popular client type • Unique attacks due to "shared execution environment" nature of browser – Cross-Site Request Forgery (CSRF) – Cross-Site Scripting (XSS) • Ongoing work in IETF to produce useful guidance – https://tools.ietf.org/html/draft-parecki-oauth-browser-based-apps
  34. 39 @leastprivilege / @brocklallen Two approaches to authenticate APIs for

    SPAs • Implicit credential that browser sends automatically – Cookies – Integrated Windows authentication (Kerberos) – X509 client certificates • Explicit credential that must be sent from application code – Tokens
  35. 40 @leastprivilege / @brocklallen Server-side Application Threat: cross-site request forgery

    (CSRF) Browser Tab/Process Tab/Process login & set authentication cookie http://app.com http://app.com/delete/5 send authentication cookie
  36. 41 @leastprivilege / @brocklallen CSRF mitigation with anti-forgery tokens •

    Add explicit “credential” on every request – Authenticates calling app Server-side Application render page & anti-forgery cookie <form> <input type="hidden" value="anti-forgery token" /> </form> <script>…</script> post-back: cookie + hidden field Page web api call: cookie + header
  37. 42 @leastprivilege / @brocklallen CSRF mitigation with same-site cookies •

    Browser only sends cookie from page in same origin • Decent browser support (as of mid-2019) https://caniuse.com/#search=samesite HTTP/1.1 200 OK Set-Cookie: key=value; HttpOnly; SameSite=strict
  38. 43 @leastprivilege / @brocklallen Restrictions using cookies for APIs •

    Same-site cookies is still new – Some people still on older browsers • API must have server-side code to issue cookie to browser – Easy for legacy/mixed, more work for modern/SPA • Application must be same origin as API – Will your app always be the same domain as the API(s)? • Browser-based app is only app that can call the API – Will you ever want other apps to use the API?
  39. 44 @leastprivilege / @brocklallen Token based authentication • Tokens are

    a different form of credential – Commonly use JSON web token (JWT) – Sent via authorization header to authenticate HTTP request – Provides solution to CSRF that combines anti-forgery and authentication • Tokens help solve the architectural issues – More than just browser-based apps can use tokens – No cookie management needed in API – Can call APIs cross-domain
  40. 46 @leastprivilege / @brocklallen History (2) • OAuth 2 designed

    for JavaScript-based applications – original Implicit Flow – now deprecated and replaced with Code Flow with PKCE
  41. 47 @leastprivilege / @brocklallen Token Management for JS Apps •

    Regardless of the flow, tokens will be stored in the browser – e.g. session storage – prone to XSS-based attacks • potential exfiltration of tokens • even worse with refresh tokens – Content Security Policy (CSP) highly recommend – but not always easy • Not recommended to use refresh tokens in SPAs – rather use "token renew" technique – renewal bound to session
  42. 48 @leastprivilege / @brocklallen Java Script Client Library • https://github.com/IdentityModel/oidc-client-js

    var settings = { authority: 'http://localhost:5152/', client_id: 'spa', redirect_uri: 'http://localhost:5152/callback.html', response_type: 'code', scope: 'openid profile api', }; var mgr = new Oidc.UserManager(settings); mgr.getUser().then(function (user) { if (user) { log("logged in", user); } else { mgr.signinRedirect(); } });
  43. 49 @leastprivilege / @brocklallen "BFF" Architecture Front-End private Back-End httponly

    cookies + anti forgery protection APIs access token client https://leastprivilege.com/2019/01/18/an-alternative-way-to-secure-spas-with-asp-net-core-openid-connect-oauth-2-0-and-proxykit/
  44. 52 @leastprivilege / @brocklallen Further Reading • OAuth 2.0 –

    https://tools.ietf.org/html/rfc6749 • OAuth 2.0 Threat Model – https://tools.ietf.org/html/rfc6819 • OpenID Connect – https://openid.net/specs/openid-connect-core-1_0.html • PKCE – https://tools.ietf.org/html/rfc7636 • OAuth 2.0 Security Best Practices – https://tools.ietf.org/html/draft-ietf-oauth-security-topics-11 • SameSite Cookies – https://tools.ietf.org/html/draft-west-first-party-cookies-07 • IdentityServer samples – https://github.com/IdentityServer/IdentityServer4/tree/master/samples/Clients • ASP.NET Core Security & SPA Samples – https://github.com/leastprivilege/AspNetCoreSecuritySamples • Native Client Samples – https://github.com/IdentityModel/IdentityModel.OidcClient.Samples