Slide 1

Slide 1 text

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

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 dominick.baier@leastprivilege.com 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 Soon 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 Token Binding OpenID Connect Token Binding OpenID Connect Federation … OAuth 2.0 Token Exchange OAuth 2.0 Mutual TLS OAuth 2.0 Device Flow OAuth 2.0 Discovery 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

Slide 8

Slide 8 text

8 @leastprivilege / @brocklallen Client Credentials Flow 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 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 10

Slide 10 text

10 @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 11

Slide 11 text

11 @leastprivilege / @brocklallen Challenges for Clients • Request token – which protocol flow to use? – is a user involved? • Manage token – where to store them? – how to renew the token? – is long-lived access required? • Use token

Slide 12

Slide 12 text

12 @leastprivilege / @brocklallen User-Centric Clients • More front-end concerns – authenticate user • UI workflows – start/join (single sign-on) session • listening to session change notifications • potentially coordinating token storage with session lifetime – make API calls on behalf of the user – silently renew tokens • To accommodate all of these requirements, Authorization Code Flow was created

Slide 13

Slide 13 text

13 @leastprivilege / @brocklallen Front-Channel: Authorization Code Flow Request GET /authorize ?client_id=app1 &redirect_uri=https://app.com/cb &response_type=code &scope=openid email api1 api2 offline_access

Slide 14

Slide 14 text

14 @leastprivilege / @brocklallen Front-Channel: Authorization Code Flow Response GET /cb?code=xyz

Slide 15

Slide 15 text

15 @leastprivilege / @brocklallen Back-Channel: Retrieving Tokens • Exchange code for access & refresh token – using client id and secret code (client_id:client_secret) { id_token: "xxae…988", access_token: "xyz…123", refresh_token: "jdj9…192j", expires_in: 3600, token_type: "Bearer" }

Slide 16

Slide 16 text

16 @leastprivilege / @brocklallen Issues with Code Flow • Historically only designed for confidential clients • 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 17

Slide 17 text

17 @leastprivilege / @brocklallen 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 18

Slide 18 text

18 @leastprivilege / @brocklallen Hybrid Flow Response POST /cb cryptographically linked via c_hash

Slide 19

Slide 19 text

19 @leastprivilege / @brocklallen Server-side Web Applications (e.g. ASP.NET Core) • Built-in features make writing clients easy – OpenID Connect authentication handler supports Hybrid Flow • extensibility points to customize behavior – token storage mechanism that is automatically tied to session • uses cookies for storage by default • can be replaced with distributed cache • can be used for automatic token lifetime management • Can revoke refresh tokens at logout time (if not needed anymore) https://leastprivilege.com/2019/01/14/automatic-oauth-2-0-token-management-in-asp-net-core/

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 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 22

Slide 22 text

22 @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 23

Slide 23 text

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

Slide 24

Slide 24 text

24 @leastprivilege / @brocklallen Using a browser for driving the authentication workflow authentication request render UI & workflow

Slide 25

Slide 25 text

25 @leastprivilege / @brocklallen Code Flow + PKCE GET /authorize ?client_id=nativeapp &scope=openid profile api1 api2 offline_access &redirect_uri=com.mycompany.nativeapp://cb &response_type=code &nonce=j1y…a23 &code_challenge=x929..1921 nonce = random_number code_verifier = random_number code_challenge = hash(code_verifier)

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

27 @leastprivilege / @brocklallen Requesting the access token • Exchange code for access token – using client id and code verifier code & code verifier (client_id) { id_token: "ka9…2129", access_token: "xyz…123", refresh_token: "dxy…103" expires_in: 3600, token_type: "Bearer" }

Slide 28

Slide 28 text

28 @leastprivilege / @brocklallen Proof-Key for Code Exchange (PKCE) • PKCE (RFC 7636) introduces a per-request client secret – allows binding front–channel to back-channel client – prohibits token substitution – also works without a client secret • Similar goals as nonce and c_hash approach – independent of OpenID Connect – verification happens on the token server

Slide 29

Slide 29 text

29 @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 30

Slide 30 text

30 @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 31

Slide 31 text

31 @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 32

Slide 32 text

32 @leastprivilege / @brocklallen History (1) • Same-domain architectures – client and APIs are in same application or origin – cookies are used to secure AJAX calls • Problems and limitations – Cross-Site Request forgery • mitigation techniques well understood, but require extra work – cross-domain API access – non-browser API clients

Slide 33

Slide 33 text

33 @leastprivilege / @brocklallen History (2) • OAuth 2 implicit flow tried to solve those problems • Needed to work under certain constraints – no AJAX (CORS did not really exist yet) – no client secret

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

35 @leastprivilege / @brocklallen Implicit Flow Request GET /authorize ?client_id=app1 &redirect_uri=https://app.com/cb.html &response_type=id_token token &nonce=j1y…a23 &scope=openid email api1 api2

Slide 36

Slide 36 text

36 @leastprivilege / @brocklallen Response GET /callback.html #id_token=x12f…zsz &token=32x…133 &expires_in=3600 &token_type=Bearer

Slide 37

Slide 37 text

37 @leastprivilege / @brocklallen Problems with Implicit Flow • Implicit flow is out-dated – relies solely on # vs ? handling in browser for leakage protection – tokens end up in URL history in browser – traditionally no protection against token substitution attacks • OpenID Connect added at_hash claim • needs client side crypto similar to Hybrid Flow • IETF wants to deprecate Implicit Flow – CORS widely deployed now – use Code Flow + PKCE instead

Slide 38

Slide 38 text

38 @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 recommended – but not always easy* – HTTP token binding might help in the future** • Token renewal should be tied to session lifetime – "Silent renew" technique – bind refresh tokens to session * https://www.youtube.com/watch?v=uf12a-0AluI ** https://groups.google.com/a/chromium.org/forum/#!topic/net-dev/8QD01FloF1o

Slide 39

Slide 39 text

39 @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 40

Slide 40 text

40 @leastprivilege / @brocklallen The new kid on the block: SameSite Cookies • Can prevent all cross-origin usages of cookies • On by default for ASP.NET Core authentication cookies – LAX only https://caniuse.com/#search=samesite

Slide 41

Slide 41 text

41 @leastprivilege / @brocklallen "BFF" Architecture Front-End private Back-End httponly + same site cookies 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 42

Slide 42 text

42 @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 • ASP.NET Core Security & SPA Samples – https://github.com/leastprivilege/AspNetCoreSecuritySamples • Native Client Samples – https://github.com/IdentityModel/IdentityModel.OidcClient.Samples

Slide 43

Slide 43 text

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