...
Support PKCE in the authorization code flow
Add field to label OAuth 2 clients as either “public” or “confidential”; backfill existing clients as “confidential”
Public clients should not be issued secrets
Public clients should be required to use PKCE
Revoke the current iteration of a refresh token when an old refresh token is used
Don’t save consent records for public OAuth clients
Background
There are currently many ways to authenticate a request to Synapse, including
...
Token binding introduces a public/private keypair and encrypts additional data to bind tokens to a TLS connection, thus a token could not be used if intercepted via MitM/token export. While powerful, implementing token binding can be complicated and has seen low adoption. We may choose to further investigate token binding as in [4] later. Token binding as described in [OAuth 2.0 Token Binding] does not seem to be an acceptable solution, because the draft has expired, and the mechanism to implement token binding on the client side does not seem to be supported by any major browsers (abandoned by Chrome, and only implemented in Edge before it became Chromium-based).
Refresh token rotation is implemented, but we currently do not revoke an active token if an invalid token is used. We should extend our implementation to include this behavior.
Risk in Saving Consent Records for Public OAuth Clients
In Synapse, we keep track of when a user consents to a particular selection of scope and claims, so that a user does not have to re-authorize an application that has already been authorized. This is for convenience; this mechanism isn’t specification-related.
A new attack mechanism is opened up if this same mechanism is applied to public OAuth clients, because the client credentials (if they exist) are not secrets--a malicious actor could use a public client that a user has already authorized to gain access to an account without a user’s consent.
To illustrate this scenario, consider:
Alice, an Synapse Python Client user who authorizes access to their account with OAuth. Alice is somewhat security-aware, and carefully checks the information she authorizes an OAuth client to have before granting it.
Mal, a malicious actor trying to gain access to user resources by taking advantage of the public OAuth clients in Synapse.
Because Alice uses the Python client, she has authorized the related public OAuth client to access all of her account resources accessible via OAuth. Synapse has saved an authorization record, so that Alice can quickly log-in in the Python client with minimal friction.
Mal has created an app that claims to save Alice a lot of time in her analyses, and has convinced Alice to attempt to log in to her app. Unbeknownst to Alice, the app uses the same OAuth client as the Synapse Python client, and requests the same set of scopes and claims. Because Synapse has saved her authorization record, Alice never has a chance to see that she is authorizing the “Synapse Python Client” OAuth client, which would tip off to Alice that Mal’s app is malicious. Mal now has unauthorized access Alice’s account.
...
References
...