Implementation is mostly ported from the official CLI, with minor changes to utilise having predefined sso_id in the config file.
Tested with Google based SSO.
Auth flow
Can be summarised with:
Generate two random values, state and ssoCodeVerifier
hash and B64 escape the ssoCodeVerifier
spin up a local callback server (I assume port range is important here because of the allowed redirect_uris on Bitwarden end)
open a webbrowser initializing the SSO flow using the previously generated values
obtain the authorization_code via the callback server
replace the code for tokens by calling the /identity/token endpoint (same as for passwords, but different params)
Quirks
2FA
Due to the way 2FA is implemented in rbw (try to authenticate without 2FA, fallback to it as needed based on the response from server) SSO users with 2FA configured have to go through the "webbrowser flow" twice: once to get the response about the missing 2FA, second time to send 2FA alongside the SSO obtained code.
Bitwarden CLI reuses the authorization_code obtained in first iteration in such cases, but I feel this approach would require bigger overhaul in rbw.
Password
SSO flow doesn't use the master password in its auth, so theoretically we don't have to ask for it during login.
Of course it's still required for the unlock operation.
I kept the master password prompt in SSO flow to be in sync with the password flow, which automatically calls unlock after login.
Notes
Usual disclaimer: I don't really write Rust, feel free to suggest more idiomatic code wherever you see fit.
Especially the error handling feels like it could use some improvements
Resolves https://github.com/doy/rbw/issues/118
Implementation is mostly ported from the official CLI, with minor changes to utilise having predefined
sso_id
in the config file.Tested with Google based SSO.
Auth flow
Can be summarised with:
state
andssoCodeVerifier
ssoCodeVerifier
redirect_uris
on Bitwarden end)authorization_code
via the callback server/identity/token
endpoint (same as for passwords, but different params)Quirks
2FA
Due to the way 2FA is implemented in
rbw
(try to authenticate without 2FA, fallback to it as needed based on the response from server) SSO users with 2FA configured have to go through the "webbrowser flow" twice: once to get the response about the missing 2FA, second time to send 2FA alongside the SSO obtained code. Bitwarden CLI reuses the authorization_code obtained in first iteration in such cases, but I feel this approach would require bigger overhaul inrbw
.Password
SSO flow doesn't use the master password in its auth, so theoretically we don't have to ask for it during
login
. Of course it's still required for theunlock
operation.I kept the master password prompt in SSO flow to be in sync with the password flow, which automatically calls
unlock
afterlogin
.Notes
Usual disclaimer: I don't really write Rust, feel free to suggest more idiomatic code wherever you see fit. Especially the error handling feels like it could use some improvements