Slide 1

Slide 1 text

Building Clients for OpenID Connect/OAuth 2-based Systems Dominick Baier @leastprivilege https://github.com/leastprivilege/AspNetCoreSecuritySamples

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

4 @leastprivilege / @brocklallen It's complicated! https://openid.net/wg/ https://tools.ietf.org/wg/oauth/

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

7 @leastprivilege / @brocklallen Challenges for Clients • Request token • Use token • Manage token

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

10 @leastprivilege / @brocklallen Use Token • Token (typically) transmitted via Authorization header – form body or query string as alternative Authorization: Bearer GET /service/resource https://tools.ietf.org/html/rfc6750

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

15 @leastprivilege / @brocklallen Authorization Code Flow Response GET /cb?code=xyz

Slide 16

Slide 16 text

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" }

Slide 17

Slide 17 text

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)

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

19 @leastprivilege / @brocklallen Approach 1: Hybrid Flow Response POST /cb cryptographically linked via c_hash

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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" }

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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" }

Slide 26

Slide 26 text

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" }

Slide 27

Slide 27 text

27 @leastprivilege / @brocklallen Revocation

Slide 28

Slide 28 text

28 @leastprivilege / @brocklallen Token Revocation • Endpoint to programmatically revoke tokens (RFC 7009) – reference tokens – refresh tokens /revoke?token=a19..18a

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

32 @leastprivilege / @brocklallen Anti Pattern: Resource Owner Password Flow Username Password Login username/password token token trust Token service API 1 2 3

Slide 33

Slide 33 text

33 @leastprivilege / @brocklallen Using a browser for driving the authentication workflow (aka AppAuth) authentication request render UI & workflow

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

35 @leastprivilege / @brocklallen Receiving the response GET com.mycompany.nativeapp://cb?code=818…1299 callback

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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 … post-back: cookie + hidden field Page web api call: cookie + header

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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?

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

45 @leastprivilege / @brocklallen "SPA" Architecture HTML, JS, CSS APIs access token

Slide 46

Slide 46 text

46 @leastprivilege / @brocklallen History (2) • OAuth 2 designed for JavaScript-based applications – original Implicit Flow – now deprecated and replaced with Code Flow with PKCE

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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(); } });

Slide 49

Slide 49 text

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/

Slide 50

Slide 50 text

50 @leastprivilege / @brocklallen Devices with constrained Input

Slide 51

Slide 51 text

51 @leastprivilege / @brocklallen OAuth 2.0 Device Flow for Browserless and Input Constrained Devices

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

53 @leastprivilege / @brocklallen Thanks! …and (because I always forget) - we have stickers!