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

OAuth in 2021. What's new?

Dominick Baier
January 27, 2021
280

OAuth in 2021. What's new?

Dominick Baier

January 27, 2021
Tweet

Transcript

  1. OAuth in 2021
    What’s new?
    Dominick Baier
    @leastprivilege

    View Slide

  2. 2
    @leastprivilege
    Me
    • Co-Creator of IdentityServer & IdentityModel OSS Project
    – Certified OpenID Connect & OAuth 2.0 Engine for ASP.NET Core
    – https://identityserver.io
    • Co-Creator of PolicyServer
    – Authorization for modern Applications
    – https://policyserver.io
    • Co-Founder of Duende Software
    – the new home of IdentityServer
    – https://duendesoftware.com
    email [email protected]
    blog https://leastprivilege.com
    twitter @leastprivilege
    slides https://speakerdeck.com/leastprivilege

    View Slide

  3. 3
    @leastprivilege
    IdentityServer
    https://github.com/DuendeSoftware/IdentityServer
    https://github.com/IdentityServer/IdentityServer4

    View Slide

  4. 4
    @leastprivilege
    Agenda
    • OAuth 2.1
    • Metadata, signing algorithms & key rotation
    • JWT profile for OAuth access tokens
    • Resource Isolation
    • JAR & PAR
    • Proof-of-possession access tokens
    https://duendesoftware.com/training/highsecurityoauth

    View Slide

  5. 5
    @leastprivilege
    OAuth 2.1

    View Slide

  6. 6
    @leastprivilege
    Current BCPs & Security Considerations
    OAuth 2.0 Security
    Best Current Practice
    https://tools.ietf.org/html/draft-ietf-oauth-
    security-topics/
    OAuth 2.0 Threat Model &
    Security Considerations
    https://tools.ietf.org/html/rfc6819
    JSON Web Token
    Best Current Practices
    https://tools.ietf.org/html/rfc8725
    OAuth 2.0 for native Applications
    https://tools.ietf.org/html/rfc8252
    OAuth 2.0 for Browser-Based Applications
    https://tools.ietf.org/wg/oauth/draft-ietf-oauth-browser-based-apps/
    JSON Web Token (JWT) Profile
    for OAuth 2.0 Access Tokens
    https://tools.ietf.org/wg/oauth/draft-ietf-oauth-
    access-token-jwt/

    View Slide

  7. 7
    @leastprivilege
    No more Implicit Flow
    • Implicit flow was a workaround in 2012 to overcome cross-origin AJAX
    limitations
    – solved now with CORS
    • Error prone
    – tokens are transmitted via URLs and can leak easily
    • log files
    • browser history
    • referrer headers
    • implementation errors
    • proxies
    – no solution for token injection attacks (without adding OpenID Connect)

    View Slide

  8. 8
    @leastprivilege
    Implicit Flow Request
    GET /authorize
    ?client_id=app1
    &redirect_uri=https://app.com/cb.html
    &response_type=token
    &state=j1y…a23
    &scope=api1 api2

    View Slide

  9. 9
    @leastprivilege
    Implicit Flow Response
    GET /callback.html
    #token=32x…133
    &expires_in=3600
    &token_type=Bearer
    &state=j1y…a23

    View Slide

  10. 10
    @leastprivilege
    No more Password Grant
    • Exposes user's credentials to client
    – increased attack surface
    – credentials can leak in more places than just the authorization server
    – users are trained to type in credentials in multiple places
    • more prone to phishing attacks
    • Incompatible with modern authentication flows
    – FIDO
    – 2FA
    – federation

    View Slide

  11. 11
    @leastprivilege
    Original Flows
    Application Type Flow
    Machine to Machine Client Credentials Flow
    Server-side Web Application OAuth Code Flow
    OpenID Connect Hybrid Flow
    Password Grant
    Native Desktop/Mobile
    Applications
    Implicit Flow
    OAuth Code Flow
    OpenID Connect Hybrid Flow
    Password Grant
    SPAs Implicit Flow
    Password Grant
    Code Flow

    View Slide

  12. 12
    @leastprivilege
    Grand Unification
    Application Type Flow
    Machine to Machine Client Credentials Flow
    Interactive Application Code Flow + PKCE

    View Slide

  13. 13
    @leastprivilege
    Authorization Code Injection
    GET /authorize
    ?client_id=app1
    &redirect_uri=https://app.com/cb
    GET /cb?code=stolen
    client id/secret/stolen
    access token
    3
    1
    2

    View Slide

  14. 14
    @leastprivilege
    Mitigation: Proof Key for Code Exchange
    GET /authorize
    ?client_id=app1
    &redirect_uri=https://app.com/cb
    &code_challenge=cy..fc
    GET /cb?code=xyz
    client id/secret
    code / code_verifier
    access token
    3
    1
    2
    code_verifier = random number
    code_challenge = hash(code_verifier)

    View Slide

  15. 15
    @leastprivilege
    Redirect URI Validation Attacks
    • Problematic
    – https://*.somesite.com/cb
    • e.g. sub-domain takeover
    – https://somesite.com/*
    • find a page with an open redirector
    • find a page where attacker can inject content
    GET
    /authorize?response_type=code&client_id=s6BhdRkqt3&state=9ad67f13
    &redirect_uri=https://somesite.com/some_endoint

    View Slide

  16. 16
    @leastprivilege
    OAuth 2.1
    • RFC 6749 + RFC 6750 + various BCPs == OAuth 2.1
    – https://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2-1/
    • Most important changes
    – omission of implicit grant
    – omission of password grant
    – PKCE must be used with the authorization code grant
    – redirect URIs must be compared using exact string matching
    – refresh tokens must be either sender-constrained or one-time use only
    – bearer tokens usage omits token in the query string

    View Slide

  17. 17
    @leastprivilege
    OAuth Metadata, Key Rotation &
    Signing Algorithms

    View Slide

  18. 18
    @leastprivilege
    OAuth/OpenID Connect Metadata

    View Slide

  19. 19
    @leastprivilege
    Key Rotation & Algorithms
    • Rotation
    – recommended to rotate keys regularly
    – must keep a history of old keys (depending on max access token lifetime)
    • Algorithms
    – OIDC mandates RS256 as a minimum
    – OpenBanking/PSD2 requires PS256
    – FHIR requires EC-based algorithms

    View Slide

  20. 20
    @leastprivilege
    JWT Profile for OAuth Access Tokens

    View Slide

  21. 21
    @leastprivilege
    Access Tokens
    • RFC 6749 has no information about token format or content

    View Slide

  22. 22
    @leastprivilege
    Self-contained Tokens
    • JWTs are convenient to use and have good library support
    {
    "typ": "JWT",
    "alg": "RS256",
    "kid": "mj399j…"
    }
    {
    "iss": "https://issuer",
    "exp": 1340819380,
    "nbf": 1340818761,
    "client_id": "client",
    "user_id": "bob",
    "scope": "scopeA scopeB",
    }
    Header
    Payload
    eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMD.4MTkzODAsDQogImh0dHA6Ly9leGFt
    Header Payload Signature

    View Slide

  23. 23
    @leastprivilege
    JWT Claim Types (all optional)
    • iss (Issuer)
    – identifies the principal that issued the JWT
    • sub (Subject)
    – identifies the principal that is the subject of the JWT
    • aud (Audience)
    – identifies the recipients that the JWT is intended for
    • exp (Expiration Time)
    – identifies the expiration time on or after which the JWT MUST NOT be accepted for processing
    • nbf (Not Before)
    – identifies the time before which the JWT MUST NOT be accepted for processing
    • iat (Issued At)
    – identifies the time at which the JWT was issued
    • jti (JWT ID)
    – provides a unique identifier for the JWT
    https://tools.ietf.org/html/rfc7519#section-4.1

    View Slide

  24. 24
    @leastprivilege
    Lessons learned with JWTs
    • In absence of a standard, every vendor came up with different claims and
    semantics
    – how to convey user and client ID
    – define additonal claims
    – nbf vs iat
    – scopes vs audiences
    – required vs optional
    – cross-JWT confusion and substitution attacks
    • Two specs aim to provide interoperable definitions
    – https://tools.ietf.org/html/rfc8725
    – https://datatracker.ietf.org/doc/html/draft-ietf-oauth-access-token-jwt

    View Slide

  25. 25
    @leastprivilege
    sub & client_id
    • client_id
    – OAuth client ID
    • sub
    – if user is present: sub as defined in OpenID Connect
    – if no user is present: OAuth client ID
    https://datatracker.ietf.org/doc/html/draft-ietf-oauth-access-token-jwt#section-2.2

    View Slide

  26. 26
    @leastprivilege
    Other required claims
    • iss
    – identifies the principal that issued the JWT
    • exp
    – identifies the expiration time on or after which the JWT MUST NOT be accepted for processing
    • aud
    – identifies the recipient(s) that the JWT is intended for
    • iat
    – identifies the time at which the JWT was issued
    • jti
    – provides a unique identifier for the JWT

    View Slide

  27. 27
    @leastprivilege
    Scopes in JWTs
    {
    "iss": "issuer",
    "aud": "audience",
    "exp": 1340819380,
    "iat": 1340818761,
    "jti": "random_id"
    "sub": "123",
    "client_id": "456",
    "scope": "scopeA scopeB"
    }

    View Slide

  28. 28
    @leastprivilege
    Cross-JWT Confusion
    https://www.rfc-editor.org/rfc/rfc8725.html#name-cross-jwt-confusion

    View Slide

  29. 29
    @leastprivilege
    Example JWT per Profile
    {
    "typ": "at+jwt",
    "alg": "RS256",
    "kid": "mj399j…"
    }
    {
    "iss": "issuer",
    "aud": "audience",
    "exp": 1340819380,
    "iat": 1340818761,
    "jti": "random_id"
    "sub": "123",
    "client_id": "456",
    "scope": "scopeA scopeB"
    }

    View Slide

  30. 30
    @leastprivilege
    Resource Isolation

    View Slide

  31. 31
    @leastprivilege
    Resource Isolation
    • OAuth uses the scope parameters to indicate "what" the clients wants to
    access
    The authorization and token endpoints allow the client to specify the scope of the
    access request using the "scope" request parameter.
    The value of the scope parameter is expressed as a list of space-delimited, case-
    sensitive strings.
    If the value contains multiple space-delimited strings, their order does not matter,
    and each string adds an additional access range to the requested scope.
    The authorization server MAY fully or partially ignore the scope requested by the
    client, based on the authorization server policy or the resource owner's instructions.
    RFC6749

    View Slide

  32. 32
    @leastprivilege
    Example: GitHub Scopes
    https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/

    View Slide

  33. 33
    @leastprivilege
    Example: Google Scopes
    https://developers.google.com/oauthplayground/

    View Slide

  34. 34
    @leastprivilege
    Problems with Scope Model
    • Token can be re-used at multiple resources
    – makes tokens very powerful
    • in case of leakage
    – prohibits resource-specific processing
    • e.g. token content, encryption
    – concerns about token re-use
    • especially with absence of sender constraints
    • Can't prohibit that clients requests token that can be used at multiple resources

    View Slide

  35. 35
    @leastprivilege
    Shared vs Resource-specific Access Tokens
    {
    "iss": "https://issuer",
    "iat": 1340818761,
    "exp": 1340819380,
    "client_id": "backoffice",
    "scope": [ "orders", "invoicing" ]
    "sub": "182jmm199",
    "more_data": "…"
    }
    orders
    invoicing
    trust
    boundary?

    View Slide

  36. 36
    @leastprivilege
    Resource Indicators
    • RFC 8707 introduces new request parameter
    – resource
    • Indicates target service or resource to which access is being requested
    – must be an absolute URI
    – might be a physical network address
    – multiple resource parameters are allowed

    View Slide

  37. 37
    @leastprivilege
    Authorize Request
    • Request access to one or more resource
    – can be combined with scope
    GET /as/authorize?
    client_id=client&
    response_type=code&
    state=xyz&
    redirect_uri=https://client/cb&
    resource=https://invoice.api.com&
    resource=https://customer.api.com
    1

    View Slide

  38. 38
    @leastprivilege
    Redeeming the Code
    • Resource for access token must be specified
    – returned token is for the requested resource only
    POST /as/token
    grant_type=authorization_code&
    redirect_uri=https//client/cb&
    code=abc&
    resource=https://invoice.api.com
    {
    "access_token":"ey…Yw",
    "token_type":"Bearer",
    "expires_in":3600,
    "refresh_token":"4L…C2"
    }
    2
    {
    "iss": "http://as.com",
    "aud": "https://invoice.api.com"
    "iat": 1588420700
    "exp": 1588420800,
    "sub": "123",
    "client_id": "456"
    }

    View Slide

  39. 39
    @leastprivilege
    Getting access to other Resources
    • Refresh token can be used to request additional access tokens
    POST /as/token
    grant_type=refresh_token&
    refresh_token=4L…C2&
    resource=https://customer.api.com
    {
    "access_token":"ey…Yw",
    "token_type":"Bearer",
    "expires_in":3600,
    "refresh_token":"4L…C2"
    }
    3
    {
    "iss": "http://as.com",
    "aud": "https://customer.api.com"
    "iat": 1588420700
    "exp": 1588420800,
    "sub": "123",
    "client_id": "456"
    }

    View Slide

  40. 40
    @leastprivilege
    JWT Secured Authorize Request (JAR)
    Pushed Authorize Request (PAR)

    View Slide

  41. 41
    @leastprivilege
    JWT Secured Authorization Requests (JAR)
    • Allows passing authorization parameters as a JSON Web Token
    – signed for integrity and client authentication
    – encrypted for confidentiality
    • Mitigates several known attacks
    – redirection URI re-writing
    – mix-up attacks
    https://tools.ietf.org/html/draft-ietf-oauth-jwsreq

    View Slide

  42. 42
    @leastprivilege
    JWT Secured Authorization Request
    GET /authorize?client_id=client&response_type=code&redirect_uri=https://myapp.com/cb
    &state=abc&code_challenge=def&scope=openid customer.api
    GET /authorize?client_id=client&request=
    eyJhbGciOiJSUzI1NiIsImtpZCI6ImsyYmRjIn0.ewogICAgImlzcyI6ICJzNkJoZF
    JrcXQzIiwKICAgIC.JhdWQiOiAiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20iL
    Aog ICAgInJlc3BvbnNlX3R5cGUiOiAiY29kZSBpZF90b2tlbiIsCiAgICAiY2xpZW
    50X2 lkIjogInM2QmhkUmtxdDMiLAogICAgInJlZGlyZWN0X3VyaSI6ICJodHR
    wczovL2Ns aWVudC5leGFtcGxlLm9yZy9jYiIsCiAgICAic2NvcGUiOiAib3Blbml
    kIiwKICAgIC JzdGF0ZSI6ICJhZjBpZmpzbGRraiI.sCiAgICAibm9uY2UiOiAibi0wU
    zZfV3pBMk1q IiwKICAgICJtYXhfYWdlIjogODY0MDAKfQ.Nsxa_18VUElVaPjqW
    _ToI1yrEJ67BgK b5xsuZRVqzGkfKrOIX7BCx0biSxYGmjK9KJPctH1OC0iQJwXu5Y

    View Slide

  43. 43
    @leastprivilege
    Request Object
    {
    "typ": "oauth.authz.req+jwt",
    "alg": "RS256",
    "kid": "1"
    }.
    {
    "iss": "client",
    "aud": "https://authorizationserver.com",
    "response_type": "code",
    "client_id": "client",
    "redirect_uri": "https://myapp.com/cb",
    "scope": "openid customer.api",
    "state": "abc",
    "code_challenge": "def"
    }.
    [Signature]

    View Slide

  44. 44
    @leastprivilege
    Pushed Authorization Requests (PAR)
    • Complements JAR
    • Provides interoperable endpoint to push authorization request parameters
    – in exchange for a request_uri
    – allows for authentication for confidential clients
    – manages entropy and lifetime
    https://tools.ietf.org/html/draft-ietf-oauth-par

    View Slide

  45. 45
    @leastprivilege
    Pushed Authorization Request & Response
    POST /par
    client_id=client&
    response_type=code&
    redirect_uri=https://myapp.com/cb&
    state=abc&
    code_challenge=def&
    authorization_details={…}
    HTTP/1.1 201 Created
    {
    "request_uri": "urn:par:bwc4JK-cc191e-Y1LTC2",
    "expires_in": 90
    }

    View Slide

  46. 46
    @leastprivilege
    Authorization Request using request_uri
    • Front-channel only used to transmit reference to authenticated and
    validated request object
    GET /authorize?client_id=client&
    request_uri=urn:par:bwc4JK-cc191e-Y1LTC2

    View Slide

  47. 47
    @leastprivilege
    Proof-of-Possession (PoP)
    Access Tokens

    View Slide

  48. 48
    @leastprivilege
    Weakness of Bearer Tokens
    • Bearer tokens are not bound to the client
    – attacker can replay leaked tokens
    Authorization: Bearer

    View Slide

  49. 49
    @leastprivilege
    "Proof-of-Possession" History
    • Most wanted feature since initial OAuth 2.0 spec
    – only bearer tokens were specified
    • Several attempts to introduce PoP at the application layer
    – required a lot of application layer crypto (e.g. signing of HTTP requests)
    – some unsolved problems (e.g. streaming)
    • ...then at the transport layer
    – HTTP token binding (deprecated)

    View Slide

  50. 50
    @leastprivilege
    PoP Today
    • Transport Layer
    – Mutual TLS
    – https://tools.ietf.org/html/rfc8705
    • Application Layer
    – DPop
    – https://tools.ietf.org/html/draft-fett-oauth-dpop

    View Slide

  51. 51
    @leastprivilege
    cnf Claim
    {
    "iss": "https://server.example.com",
    "client_id": "client1",
    "exp": 1493726400,
    "cnf": { "some_key_material" }
    }
    HTTP/1.1 200 OK Content-Type: application/json
    {
    "active": true,
    "iss": "https://server.example.com",
    "client_id": "client1",
    "exp": 1493726400,
    "cnf": { "some_key_material" }
    }
    JWT
    Introspection
    https://tools.ietf.org/html/rfc7800

    View Slide

  52. 52
    @leastprivilege
    Mutual TLS
    TLS Tunnel
    server certificate
    client certificate
    • authentication
    • proving to know a secret
    (private key)
    • validate chain of trust
    (optional)
    • negotiate key material
    • sign & encrypt traffic

    View Slide

  53. 53
    @leastprivilege
    Creating an X.509 Client Certificate
    static X509Certificate2 CreateClientCertificate(string name)
    {
    var distinguishedName = new X500DistinguishedName($"CN={name}");
    using (var rsa = RSA.Create(2048))
    {
    var request = new CertificateRequest(
    distinguishedName, rsa, HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1);
    request.CertificateExtensions.Add(
    new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment |
    X509KeyUsageFlags.DigitalSignature, false));
    request.CertificateExtensions.Add(
    new X509EnhancedKeyUsageExtension(
    new OidCollection { new Oid("1.3.6.1.5.5.7.3.2") }, false));
    return request.CreateSelfSigned(
    new DateTimeOffset(DateTime.UtcNow.AddDays(-1)),
    new DateTimeOffset(DateTime.UtcNow.AddDays(10)));
    }
    }

    View Slide

  54. 54
    @leastprivilege
    Setting a Client Certificate
    static SocketsHttpHandler GetHandler(X509Certificate2 certificate)
    {
    var handler = new SocketsHttpHandler();
    handler.SslOptions.ClientCertificates =
    new X509CertificateCollection { certificate };
    return handler;
    }

    View Slide

  55. 55
    @leastprivilege
    Calling the Token Endpoint
    static async Task RequestTokenAsync()
    {
    var client = new HttpClient(GetHandler());
    var disco = await client.GetDiscoveryDocumentAsync("https://demo.duendesoftware.com");
    var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
    {
    Address = disco.MtlsEndpointAliases.TokenEndpoint,
    ClientId = "mtls",
    Scope = "api1"
    });
    return response;
    }

    View Slide

  56. 56
    @leastprivilege
    Proof-of-Possession with MTLS
    {
    "iss": "https://issuer",
    "exp": 1340819380,
    "nbf": 1340818761,
    "client_id": "182jmm199",
    "scope": "api1",
    "cnf": {
    "x5t#S256": "bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2"
    }
    }

    View Slide

  57. 57
    @leastprivilege
    Verifying Access Token Ownership at Resource
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddAuthentication("jwt")
    .AddJwtBearer("jwt", options => { … })
    .AddCertificate(options => { … });
    services.AddCertificateForwarding(…)
    }
    public void Configure(IApplicationBuilder app)
    {
    app.UseForwardedHeaders(…)
    app.UseCertificateForwarding();
    app.UseAuthentication();
    app.UseConfirmationValidation(…)
    app.UseAuthorization();
    }

    View Slide

  58. 58
    @leastprivilege
    Application Level Proof-of-Possession
    • OAuth 2.0 Demonstration of Proof-of-Possession at the Application Layer
    (DPoP)
    An application-level sender-constraining for access and
    refresh tokens that can be used in cases where MTLS is
    not available. It uses proof-of- possession based on a
    public/private key pair and application-level signing.
    DPoP can be used with public clients and, in case of
    confidential clients, can be combined with any client
    authentication method.
    https://tools.ietf.org/html/draft-fett-oauth-dpop

    View Slide

  59. 59
    @leastprivilege
    DPop Token Request
    POST /token
    grant_type=authorization_code
    code=xyz
    redirect_uri=https://…
    Dpop: eyJ0…3Lg

    View Slide

  60. 60
    @leastprivilege
    DPop Proof Token (Token Request)
    {
    "typ": "dpop+jwt",
    "alg": "ES256",
    "jwk": {
    "kty": "EC",
    "x": "l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs",
    "y": "9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA",
    "crv": "P-256"
    }
    }.
    {
    "jti": "-BwC3ESc6acc2lTc",
    "htm": "POST",
    "htu": "https://server.example.com/token",
    "iat": 1562262616
    }.[Signature]
    public key
    unique ID
    HTTP method
    HTTP URL
    signature proves knowledge of private key

    View Slide

  61. 61
    @leastprivilege
    DPop Token Response
    • Access token contains the public key as confirmation method
    {
    "iss": "https://server.example.com",
    "client_id": "client1",
    "exp": 1493726400,
    "cnf": { "jkt":"0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I" }
    }
    Base64url encoding of the JWK SHA-256 Thumbprint of the public key (RFC 7638)
    https://tools.ietf.org/html/rfc7638

    View Slide

  62. 62
    @leastprivilege
    Resource Access
    GET /resource
    Authorization: Dpop ey…MQ
    DPop: ey…bQ

    View Slide

  63. 63
    @leastprivilege
    DPoP Proof Token (Resource Access)
    {
    "typ": "dpop+jwt",
    "alg": "ES256",
    "jwk": {
    "kty": "EC",
    "x": "l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs",
    "y": "9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA",
    "crv": "P-256"
    }
    }.
    {
    "jti": "e1j3V_bKic8-LAEB",
    "htm": "GET",
    "htu": "https://resource.example.org/resource",
    "iat": 1562262618
    }.[Signature]
    same public key
    resource must
    create jkt and
    compare with
    access token
    signature proves knowledge of private key

    View Slide

  64. 64
    @leastprivilege
    Summary
    • OAuth keeps evolving
    • OAuth 2.1
    – wraps up several guidance documents
    – removes protocol flows that turned out to be problematic
    • Additional specs strengthen OAuth security
    – JAR & PAR
    – Resource Indicators
    – PoP

    View Slide