Accept only S256 PKCE challenges #205
No files matched your search
@@ -2,6 +2,8 @@
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*
|
||||
* Modified by Coffey Labs in 2026 for INBUXA.
|
||||
*/
|
||||
|
||||
use super::{DeviceAuthResponse, FormData, MAX_POST_LEN, OAuthCode, PkceCodeChallenge};
|
||||
@@ -260,16 +262,16 @@ impl OAuthApiHandler for Server {
|
||||
}
|
||||
|
||||
// Parse and validate PKCE challenge (RFC 7636).
|
||||
// inbuxa: S256 only, as the metadata says. With `plain` (also
|
||||
// RFC 7636's default when no method is named) the challenge is
|
||||
// the verifier, so it protects nothing.
|
||||
let pkce_challenge = match code_challenge {
|
||||
Some(challenge) => match code_challenge_method.as_deref().unwrap_or("plain") {
|
||||
"S256" => PkceCodeChallenge::S256(challenge),
|
||||
"plain" if stateless_client.is_none() => {
|
||||
PkceCodeChallenge::Plain(challenge)
|
||||
}
|
||||
Some(challenge) => match code_challenge_method.as_deref() {
|
||||
Some("S256") => PkceCodeChallenge::S256(challenge),
|
||||
_ => {
|
||||
return Err(trc::AuthEvent::Error
|
||||
.into_err()
|
||||
.details("Unsupported PKCE code_challenge_method."));
|
||||
return Err(trc::AuthEvent::Error.into_err().details(
|
||||
"Unsupported PKCE code_challenge_method: use S256.",
|
||||
));
|
||||
}
|
||||
},
|
||||
None => {
|
||||
|
||||
@@ -351,6 +351,29 @@ pub async fn test(test: &mut TestServer) {
|
||||
"unknown resource indicator must not be authorized"
|
||||
);
|
||||
|
||||
// inbuxa: only S256 is accepted. `plain`, named or as RFC 7636's default
|
||||
// when no method is given, sends the verifier itself as the challenge.
|
||||
for method in [Some("plain"), None] {
|
||||
let (status, _) = post_login_raw(&LoginRequest::AuthCode {
|
||||
account_name: "[email protected]".to_string(),
|
||||
account_secret: "this is a very strong password".to_string(),
|
||||
mfa_token: None,
|
||||
client_id: client_id.to_string(),
|
||||
redirect_uri: "com.example.app:/cb".to_string().into(),
|
||||
nonce: None,
|
||||
scope: Some(PROFILE_SCOPE.to_string()),
|
||||
code_challenge: Some(PKCE_VERIFIER.to_string()),
|
||||
code_challenge_method: method.map(str::to_string),
|
||||
state: None,
|
||||
resource: vec![],
|
||||
})
|
||||
.await;
|
||||
assert_ne!(
|
||||
status, 200,
|
||||
"PKCE method {method:?} must not be authorized"
|
||||
);
|
||||
}
|
||||
|
||||
// Authenticate with the correct password, PKCE (S256), scope and a valid resource indicator
|
||||
let response = http
|
||||
.post::<LoginResponse>(
|
||||
|
||||
Reference in new issue
Block a user