fix(oauth): rfc8414 should judement the response_types (#485)

response_types_supported should be judement while try to do 'Authorization Code Flow'

Signed-off-by: jokemanfire <hu.dingyang@zte.com.cn>
This commit is contained in:
jokemanfire 2025-12-10 00:18:18 +08:00 committed by GitHub
parent d4fcac02f8
commit bce0555068
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 21 additions and 2 deletions

View file

@ -154,7 +154,7 @@ pub enum AuthError {
}
/// oauth2 metadata
#[derive(Debug, Clone, Deserialize, Serialize)]
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct AuthorizationMetadata {
pub authorization_endpoint: String,
pub token_endpoint: String,
@ -162,6 +162,7 @@ pub struct AuthorizationMetadata {
pub issuer: Option<String>,
pub jwks_uri: Option<String>,
pub scopes_supported: Option<Vec<String>>,
pub response_types_supported: Option<Vec<String>>,
// allow additional fields
#[serde(flatten)]
pub additional_fields: HashMap<String, serde_json::Value>,
@ -379,7 +380,17 @@ impl AuthorizationManager {
self.oauth_client = Some(client_builder);
Ok(())
}
/// validate if the server support the response type
fn validate_response_supported(&self, response_type: &str) -> Result<(), AuthError> {
if let Some(metadata) = self.metadata.as_ref() {
if let Some(response_types_supported) = metadata.response_types_supported.as_ref() {
if !response_types_supported.contains(&response_type.to_string()) {
return Err(AuthError::InvalidScope(response_type.to_string()));
}
}
}
Ok(())
}
/// dynamic register oauth2 client
pub async fn register_client(
&mut self,
@ -397,6 +408,10 @@ impl AuthorizationManager {
));
};
// RFC 8414 RECOMMENDS response_types_supported in the metadata. This field is optional,
// but if present and does not include the flow we use ("code"), bail out early with a clear error.
self.validate_response_supported("code")?;
let registration_request = ClientRegistrationRequest {
client_name: name.to_string(),
redirect_uris: vec![redirect_uri.to_string()],
@ -485,6 +500,9 @@ impl AuthorizationManager {
.as_ref()
.ok_or_else(|| AuthError::InternalError("OAuth client not configured".to_string()))?;
// ensure the server supports the response type we intend to use when metadata is available
self.validate_response_supported("code")?;
// generate pkce challenge
let (pkce_challenge, pkce_verifier) = PkceCodeChallenge::new_random_sha256();

View file

@ -529,6 +529,7 @@ async fn oauth_authorization_server() -> impl IntoResponse {
token_endpoint: format!("http://{}/oauth/token", BIND_ADDRESS),
scopes_supported: Some(vec!["profile".to_string(), "email".to_string()]),
registration_endpoint: Some(format!("http://{}/oauth/register", BIND_ADDRESS)),
response_types_supported: Some(vec!["code".to_string()]),
issuer: Some(BIND_ADDRESS.to_string()),
jwks_uri: Some(format!("http://{}/oauth/jwks", BIND_ADDRESS)),
additional_fields,