OpenID Connect response_mode handling - flawed discovery, missing validation
- Dominant language
- C#
- Stars
- 20.1k
- Forks
- 1.8k
- Avg merge
- 4d 8h
- Merged PRs (30d)
- 75
Description
### Steps To Reproduce
- You use an IdP that does not support (and actively rejects) `response_mode=form_post`
- You use bitwarden server's SSO functionality (OIDC) to login
### Expected Result
Bitwarden should have noticed from the discovery information that the IdP does not support `form_post` and consequently have set the respective query parameter value to `query`. Thus, the login would work.
### Actual Result
My strict IdP rejects users being redirected to it from bitwarden due to the unsupported parameter value.
### Screenshots or Videos
_No response_
### Additional Context
I would like to report two issues with the Bitwarden SSO implementation that recently surfaced on our end when we [upgraded our IdP](https://github.com/kanidm/kanidm/issues/3461#issuecomment-2683821694).
## Flawed discovery of `response_modes_supported`
- bitwarden does not consider the list of supported response modes advertised by the IdP
- the field is optional, however, the choice bitwarden makes (`form_post`) does not match the specified default if absent (`query` and `fragment`)
- it is also not possible to override this in the bitwarden configuration
Background:
> response_modes_supported
> OPTIONAL. JSON array containing a list of the OAuth 2.0 response_mode values that this OP supports, as specified in [OAuth 2.0 Multiple Response Type Encoding Practices](https://openid.net/specs/openid-connect-discovery-1_0.html#OAuth.Responses) [OAuth.Responses]. If omitted, the default for Dynamic OpenID Providers is ["query", "fragment"].
Source: https://openid.net/specs/openid-connect-discovery-1_0.html
## Missing validation of `form_post`
- **if** you choose to go down that `form_post` road, you should be validating how the response comes in
- currently you can swap the `response_mode` query parameter value to `query` (either manually as user in the browser or on-the-fly in a proxy) and bitwarden will continue processing although it requested a `form_post`
## Context
The first issue currently keeps us from upgrading our IdP because we either need to wait for them to relax validation on their end or we put a proxy-based hack in place.
In my view, you could just switch to `query` as a quick solution as this is what you have been accepting anyway so the situation does not get worse and it seems to be considered secure enough for the standard to choose it as default. You could allow administrators to change that to `form_post` in case their IdPs support that or you react to the discovery values.
I could provide more information, but I tried to reduce it to what someone implementing the OIDC authentication on your end would need to know to fix it. If you have OIDC-related questions I can recommend asking in the IdP-issue I linked as there is quite some domain expertise available over there.
### Build Version
bitwarden/nginx:2025.2.0, bitwarden/admin:2025.2.0, bitwarden/api:2025.2.0, bitwarden/icons:2025.2.0, bitwarden/web:2025.2.1, bitwarden/mssql:2025.2.0, bitwarden/attachments:2025.2.0, bitwarden/sso:2025.2.0, bitwarden/notifications:2025.2.0, bitwarden/events:2025.2.0, bitwarden/identity:2025.2.0
### Environment
Self-Hosted
### Environment Details
- OS: Arch Linux
- Environment: Docker
### Issue Tracking Info
- [x] I understand that work is tracked outside of Github. A PR will be linked to this issue should one be opened to address it, but Bitwarden doesn't use fields like "assigned", "milestone", or "project" to track progress.
Contributor guide
Assessment
This issue has not been assessed yet.