OpenID Connect & OAuth 2.
0
Security Best Practices
Dominick
@leastprivilege
Baier
Me
• Independent Consultant
– Specializing on Application Security Architectures & Security Protocols
– Working with Software Development Teams (ISVs and in-house)
• 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
email [email protected]
blog https://leastprivilege.com
twitter @leastprivilege
slides https://speakerdeck.com/leastprivilege
@leastprivilege 2
High Security OAuth
FAPI
https://fapi.openid.net
@leastprivilege 3
Agenda
• OAuth security best current practices & OAuth 2.1
– common attacks, countermeasures & recommendations
• Advanced OAuth
– tokens, scopes, resources and audience restrictions
– rich authorization requests (RAR)
– JWT secured authorization requests & request objects (JAR)
– pushed authorization requests (PAR)
– strong client authentication
– proof-of-possession access tokens
– delegation, impersonation and token exchange
– "OAuth 3.0" outlook
https://identityserver.io/training/advanced-oauth.html
@leastprivilege 4
Some Context…
2005 2007 2012 2014 2015 2017 2019/20 Soon Future
OAuth 2.0 for Native Apps BCP
OAuth 1.0 OAuth 2.0 OAuth 2.1
Bearer Tokens OAuth 2.0 Token Exchange "OAuth 3.0"
SAML 2.0p OAuth 2.0 OAuth 2.0 Mutual TLS
WS-Federation Threat Model & OAuth 2.0 Resource Indicators
WS-Trust Security JSON Web Token BCP
Considerations 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 JAR, RAR, PAR
OAuth 2.0 PKCE JWT Access Token Profile
OAuth 2.0 Security Topics BCP
OpenID Connect Core OAuth 2.0 for Browser-based
OpenID Connect Discovery
Applications BCP
@leastprivilege 5
Relevant Documents
OAuth 2.0 for native Applications OAuth 2.0 for Browser-Based Applications
https://tools.ietf.org/html/rfc8252 https://tools.ietf.org/wg/oauth/draft-ietf-oauth-browser-based-apps/
OAuth 2.0 Security
Best Current Practice
https://tools.ietf.org/html/draft-ietf-oauth-
security-topics/
JSON Web Token JSON Web Token (JWT) Profile
Best Current Practices for OAuth 2.0 Access Tokens
https://tools.ietf.org/html/rfc8725 https://tools.ietf.org/wg/oauth/draft-ietf-oauth-
access-token-jwt/
OAuth 2.0 Threat Model &
Security Considerations
https://tools.ietf.org/html/rfc6819
@leastprivilege 6
The Big Picture
Security Token
Browser Service
Web App
Web API
Native App
Web API Web API
Server App
"Thing"
@leastprivilege 7
Simplified
Authorization
Server
2
Resource Client Resource
Owner Server
Attack Model (1)
• no TLS
can read/write (unprotected)
• TLS compromise
network traffic
• other network infrastructure
issues (e.g. DNS)
Authorization
Server
2
Resource Client Resource
Owner Server
Attack Model (2)
compromise of an endpoint • Client, AS or RS
Authorization
Server
2
Resource Client Resource
Owner Server
Attack Model (3)
• rogue client or RS registered with legit AS
additional endpoints • trick legit client to trust rogue AS
Authorization • trick user in using rogue client or RS
Server
• manipulation of network messages
2
Client Resource
Server
Resource
Owner
Attack Model (4)
can read, but not modify, • open redirector vulnerabilities
the contents of the • client or AS
authorization request or response • redirect interception on
mobile devices
• leakage
Authorization • browser history
Server • proxies
• log files
2
Resource Client Resource
Owner Server
@leastprivilege 13
Implicit Flow Request
GET /authorize
?client_id=app1
&redirect_uri=https://app.com/cb.html
&response_type=token
&state=j1y…a23
&scope=api1 api2
@leastprivilege 14
Implicit Flow Response
GET /callback.html
#token=32x…133
&expires_in=3600
&token_type=Bearer
&state=j1y…a23
@leastprivilege 15
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)
@leastprivilege 16
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
@leastprivilege 17
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 Implicit Flow
Applications OAuth Code Flow
OpenID Connect Hybrid Flow
Password Grant
SPAs Implicit Flow
Password Grant
Code Flow
@leastprivilege 18
Grand Unification
Application Type Flow
Machine to Machine Client Credentials Flow
Interactive Application Code Flow + PKCE
@leastprivilege 19
Machine to Machine
client_id/client_secret,
scope=api1 api2 Authorization Server
access token
APIs
access token
Scopes: api1, api2 api3…
@leastprivilege 20
Client Authentication
• Shared secrets are not recommended
– can easily leak (configuration management, network traces, proxies…)
– should have high entropy (e.g. GUIDs, RNGs)
– should be stored non-reversible on authorization server
• Asymmetric keys
– no need to store any secret on authorization server
– secret does not get transmitted over a network
– provides key material for sender constraining
– signed JWTs and/or Mutual TLS
@leastprivilege 21
Bearer Tokens
JWT
• No binding to client
Header {
– attacker could use leaked token "typ": "JWT",
to call APIs "alg": "RS256"
"kid": "1"
– invoice.api can call customer.api }
(or vice versa)
Payload {
"iss": "https://my_issuer",
"exp": "1340819380",
"aud": [ "invoice.api",
"customer.api" ]
"client_id": "client1",
}
@leastprivilege 22
Interactive Applications
• Browser 3
client id/secret/code
redirect-based access token
2
GET /cb?code=xyz
1
GET /authorize
?client_id=app1
&redirect_uri=https://app.com/cb
@leastprivilege 23
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
@leastprivilege 24
Credential Leakage via Referrer Headers
• Might happen on client or authorization server
GET /some_endpoint?code=xyz
<html>
<body>
<img src='https://evil.com/image.png' />
</body>
</html>
GET https://evil.com/image.png
Referrer: https://myapp.com/cb?code=xyz
@leastprivilege 25
Authorization Code Injection
3
client id/secret/stolen
access token
2
GET /cb?code=stolen
1
GET /authorize
?client_id=app1
&redirect_uri=https://app.com/cb
@leastprivilege 26
Mitigation: Proof Key for Code Exchange
3
client id/secret
code / code_verifier
access token
code_verifier = random number 2
code_challenge = hash(code_verifier)
GET /cb?code=xyz
1
GET /authorize
?client_id=app1
&redirect_uri=https://app.com/cb
&code_challenge=cy..fc
@leastprivilege 27
Cross Site Request Forgery
• Similar to session fixation attacks
– attacker pre-creates code
– tries to force victim into same "logon session"
GET /cb?code=pre_created_code HTTP/1.1
Host: www.app.com
@leastprivilege 28
Anti-CSRF
• Use state parameter to bind CSRF-Token to user-agent
– PKCE helps as well (if enforced)
– token can be used to store state locally as well
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=9ad67f13
&redirect_uri=https%3A%2F%2Fwww.app.com%2Fcb
GET /cb?code=xyz&state=9ad67f13
Host: www.app.com associate with some user-agent
specific data (session storage, cookie..)
authorization server must
echo back the value
@leastprivilege 29
Countermeasures Summary
• Always do exact matching of redirect URIs
• Beware of open redirectors
• Callback pages should not contain third-party resources
– use Content Security Policy for lock-down
• Always use PKCE
• Use state parameter to bind request to user-agent
• Immediately invalidate state after usage
• Immediately invalidate authorization codes after usage
• Use rel="noreferrer" and referrer policies
@leastprivilege 30
MixUp Attack (Variant 1)
1. User selects H-AS
2. Attacker intercepts
request, and changes
3 A-AS 6 code + secret
to A-AS
3. Client stores A-AS Attacker AS (A-AS)
selection in user session
4. Attacker changes HTTP 7
1 /login?p=H-AS 302 A-AS
response to point to
2 /login?p=A-AS 302 H-AS 4
H-AS
5. User authenticates with Honest AS (H-AS)
H-AS – redirects back 5
6. Client still assumes that /cb?code=xyz
A-AS was used and sends
code and client secret
to A-AS
7. Attacker can redeem code
@leastprivilege 31
MixUp Attack (Variant 2)
1. User selects A-AS 5
2. Clients sends user A-AS code + secret
to A-AS to authenticate Attacker AS (A-AS)
3. A-AS changes client ID
and redirect URI and
forwards to H-AS 1 /login?p=A-AS 302 A-AS
3
2
4. User authenticates with
H-AS – redirects back
Honest AS (H-AS)
5. Client sends H-AS code and
client secret to A-AS
/cb?code=xyz
4
@leastprivilege 32
MixUp Countermeasures
1. Use AS-specific redirect URIs with exact redirect URI matching
2. Store for each authorization request the intended AS
3. Compare the intended AS with the actual redirect URI where the
authorization response was received
@leastprivilege 33
How does ASP.NET Core prevent MixUp Attacks?
• Each external provider is represented by an authentication handler
– with a unique name + unique callback endpoint
Challenge (name = as1)
GET /authorize?client_id=mvc&redirect_uri=https://myapp.com/signin-as1
&state=protected(correlationId + other_data)
set cookie: correlation.as1.correlationId
Callback
GET /signin-as1?code=xyz&state=protected(correlationId + other_data)
read cookie: correlation.as1.correlationId
@leastprivilege 34
Public Clients
• Slightly different rules
– 1:many mapping of client ID to client instance
– public clients cannot store secrets (and thus don’t use them)
• IOW no way to authenticate a public client
• there are exceptions for certain environments (e.g. trusted hardware)
• Native desktop/mobile applications
• Browser-based appplications (aka SPAs)
@leastprivilege 35
Anti Pattern: Native Login Dialogs
username/password Token service
Username
Password token
trust
Login
API
token
@leastprivilege 36
Using a browser with Code Flow + PKCE
authentication request
render UI & workflow
@leastprivilege 37
Different Approaches
• Choice of browser
– embedded web view
• private browser & private cookie container
– system browser**
• e.g. ASAuthenticationSession, Chrome Custom Tabs, or desktop browser
• full featured including address bar & add-ins
• shared cookie container
• Handling the callback
– event handling
– custom URI schemes
– local HTTP listener
– "claimed" HTTPS URIs**
** most recommended
@leastprivilege 38
Token Storage & Management
• Typically login workflow only used initially
– afterwards refresh tokens are used for "session management"
• All 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)
• Tokens can be revoked when not needed anymore
– logout
– uninstall
@leastprivilege 39
Browser-based Applications (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)
• Two fundamental ways to do API authentication in SPAs
– implicit credential that browser sends automatically
• cookies, Integrated Windows authentication (Kerberos), X509 client certificates
– explicit credential that must be sent from application code
• access tokens
@leastprivilege 40
JavaScript Applications with a Backend JavaScript Applications without a Backend
• Application Server • Browser
• iniates protocol flow • initiates flow
• stores & manages tokens • store & manages tokens
• proxies cross-domain calls • makes all API calls
• Browser • use no cookies
• stores no tokens
• uses cookies
@leastprivilege 41
Same-Site Architecture
https://*.myapp.com
Identity Provider Back-End / APIs external APIs
cookies +
anti-forgery
Browser Front-End
@leastprivilege 42
Anti-Forgery Protection
• Anti-Forgery Tokens
– cookie + header mechanism (e.g. ASP.NET Core MVC)
• SameSite Cookies
– automatic cookie isolation by site
January 2020
@leastprivilege 43
Access Token Storage in Browsers
• No "secure" data storage mechanism in browsers
– session storage, local storage, in-memory…
– prone to XSS-based attacks
• potential exfiltration of tokens
• origin-isolation of storage mechanism is a slight improvement
• Content Security Policy (CSP) highly recommend – but not always easy
– strict dynamic support not widely deployed yet
@leastprivilege 44
Refresh Token Storage in Browsers
• Session-bound token refresh
– "silent renew" technique relies on (third party) cookies in iframe
• becomes more and more problematic with browser default settings
• Unbound refresh tokens are dangerous when stored in browser
– MUST rotate refresh tokens on each use, in order to be able to detect a stolen
refresh token if one is replayed
– SHOULD detect replay of refresh tokens
– MUST either set a maximum lifetime on refresh tokens OR expire if the refresh
token has not been used within some amount of time
@leastprivilege 45
OAuth 2.1
@leastprivilege 46
OAuth 2.1
• RFC 6749 + RFC 6750 + various BCPs == OAuth 2.1
– https://tools.ietf.org/html/draft-parecki-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
@leastprivilege 47
Summary
• Some threats can‘t be mitigated (as a developer)
– compromise of infrastructure
• Some threats are easy to mitigate
– CSRF, injection attacks, open redirectors...
• Some threats are hard to mitigate
– complex setups that specifically target an application
• Know your threat/attacker model
– implement the mitigations that affect you
@leastprivilege 48