Recently the OAuth community has been concerned with some attack vectors around mixed up clients, particularly when dynamic client registration and discovery are used with user-selected OpenID Providers.
Broadly, the attacks consist of using dynamic client registration, or the compromise of an OpenID Provider (OP), to trick the Relying Party (RP) into sending an authorization code to the attacker’s Token Endpoint. Once a code is stolen, an attack that involves cutting and pasting values and state in authorization requests and responses can be used to confuse the relying party into binding an authorization to the wrong user.
Many deployments of OpenID Connect (and OAuth) in which the configuration is static, and the OPs are trusted, are at greatly reduced risk of these attacks. Despite that, these suggestions are best current practices that we recommend to all deployments to improve security, with a particular emphasis on more dynamic environments.
The full research papers on these attacks can be read here: A Comprehensive Formal Security Analysis of OAuth 2.0, and On the security of modern Single Sign-On Protocols: Second-Order Vulnerabilities in OpenID Connect.
Using the Hybrid Flow to mitigate attacks by a bad OP
Fortunately, the Hybrid flow of OpenID Connect is already hardened against these attacks, as the ID Token cryptographically binds the issuer to the code, and the user’s session, and through doing dynamic discovery on the issuer, the token endpoint. In fact, any OpenID Connect flow that returns an ID Token from the Authorization Endpoint already contains the same information returned by the OAuth 2.0 Mix-Up Mitigation draft specification, the Issuer (as the
iss claim) and the Client ID (as the
aud claim), enabling the RP to verify it, and thus prevent mix-up attacks.
To protect against the Mix-Up attack, RPs that allow user-driven dynamic OP discovery and client registration should:
Use the hybrid
code id_token flow, and verify in the authorization response that:
- The response contains tokens required for the response type that you requested (
- The ID Token is valid (signature validates,
aud is correct).
- The issuer (
iss value) matches the OP that the request was made to, and the token endpoint you will exchange the code at is the one listed in the issuer’s discovery document.
nonce value matches the nonce associated with the user session that initiated the authorization request.
c_hash value verifies correctly.
To aid the implementation of the best practice, we recommend that OPs consider supporting OAuth 2.0 Form Post Response Mode, as it makes it simpler for clients doing
code id_token to get both the code and the ID Token on the backend for verification.
OPs MUST also follow the OpenID Connect requirement for exact matching of a pre-registered redirect URI, to protect against open redirector attacks.
Using the Code Flow to mitigate attacks involving a compromised OP
Environments with statically registered OPs are not susceptible to dynamic registration attacks (by definition), however, it is still possible for a whitelisted OPs to potentially attack other OPs and for malicious users to bind stolen codes to their own sessions. This may sound far-fetched (why would your trusted OPs attack each other after all?), but if one OP was compromised for example, it could be used to attack the other OPs, which is not ideal. To protect against such attacks, RPs using the “code” flow with statically registered OPs should:
- Register a different redirect URI for each OP, and record the redirect URI used in the outgoing authorization request in the user’s session together with
nonce. On receiving the authorization code in the response, verify that the user’s session contains the state value of the response, and that the redirect URI of the response matches the one used in the request.
- Always use
nonce with the code flow (even though that parameter is optional to use). After performing the code exchange, compare the
nonce in the returned id token to the
nonce associated to the user’s session from when the request was made, and don’t accept the authorization if they don’t match.
The OpenID Connect working group believes that when the above best practices are followed, the attacks described are prevented.
This advice was drafted at a working meeting of the OpenID Connect WG at the 22nd Internet Identity Workshop (IIW), and reviewed at the OAuth Security Workshop 2016 in Trier Germany.