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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  5. 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

    View Slide

  6. 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

    View Slide

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

    View Slide

  8. 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

    View Slide

  9. 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

    View Slide

  10. 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

    View Slide

  11. 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

    View Slide

  12. 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

    View Slide

  13. 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

    View Slide

  14. 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

    View Slide

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

    View Slide

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

    View Slide

  17. 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)

    View Slide

  18. 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

    View Slide

  19. 19
    @leastprivilege / @brocklallen
    Approach 1: Hybrid Flow Response

    name="id_token"
    value="xjsj…aas" />
    name="code"
    value="i8j1…jj19" />

    POST /cb
    cryptographically
    linked via c_hash

    View Slide

  20. 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

    View Slide

  21. 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

    View Slide

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

    View Slide

  23. 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

    View Slide

  24. 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

    View Slide

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

    View Slide

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

    View Slide

  27. 27
    @leastprivilege / @brocklallen
    Revocation

    View Slide

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

    View Slide

  29. 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

    View Slide

  30. 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

    View Slide

  31. 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

    View Slide

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

    View Slide

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

    View Slide

  34. 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

    View Slide

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

    View Slide

  36. 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

    View Slide

  37. 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

    View Slide

  38. 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

    View Slide

  39. 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

    View Slide

  40. 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

    View Slide

  41. 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

    View Slide

  42. 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

    View Slide

  43. 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?

    View Slide

  44. 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

    View Slide

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

    View Slide

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

    View Slide

  47. 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

    View Slide

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

    View Slide

  49. 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/

    View Slide

  50. 50
    @leastprivilege / @brocklallen
    Devices with constrained Input

    View Slide

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

    View Slide

  52. 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

    View Slide

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

    View Slide