Normalize error responses

This commit is contained in:
Pierre HUBERT 2022-04-14 17:13:07 +02:00
parent 078a913f6a
commit 0b64c88fc6

View File

@ -1,3 +1,5 @@
use std::fmt::Debug;
use actix::Addr;
use actix_identity::Identity;
use actix_web::{HttpRequest, HttpResponse, Responder, web};
@ -152,6 +154,21 @@ pub async fn authorize(user: CurrentUser, id: Identity, query: web::Query<Author
))).finish()
}
#[derive(serde::Serialize)]
struct ErrorResponse {
error: String,
error_description: String,
}
pub fn error_response<D: Debug>(query: &D, error: &str, description: &str) -> HttpResponse {
log::warn!("request failed: {} - {} => '{:#?}'", error, description, query);
HttpResponse::BadRequest()
.json(ErrorResponse {
error: error.to_string(),
error_description: description.to_string(),
})
}
#[derive(Debug, serde::Deserialize)]
pub struct TokenAuthorizationCodeQuery {
redirect_uri: String,
@ -207,8 +224,11 @@ pub async fn token(req: HttpRequest,
(None, None, Some(v)) => {
let token = match v.to_str().unwrap_or_default().strip_prefix("Basic ") {
None => {
log::warn!("Token request failed: Authorization header does not start with 'Basic '! => got '{:#?}'", v);
return Ok(HttpResponse::Unauthorized().body("Authorization header does not start with 'Basic '"));
return Ok(error_response(
&query,
"invalid_request",
&format!("Authorization header does not start with 'Basic ', got '{:#?}'", v),
));
}
Some(v) => v
};
@ -216,8 +236,8 @@ pub async fn token(req: HttpRequest,
let decode = String::from_utf8_lossy(&match base64::decode(token) {
Ok(d) => d,
Err(e) => {
log::warn!("Failed to decode authorization header! {:?}", e);
return Ok(HttpResponse::InternalServerError().body("Failed to decode authorization header!"));
log::error!("Failed to decode authorization header: {:?}", e);
return Ok(error_response(&query, "invalid_request", "Failed to decode authorization header!"));
}
}).to_string();
@ -228,8 +248,7 @@ pub async fn token(req: HttpRequest,
}
_ => {
log::warn!("Token request failed: Unknown client authentication method! {:#?}", query.0);
return Ok(HttpResponse::BadRequest().body("Authentication method unknown!"));
return Ok(error_response(&query, "invalid_request", "Authentication method unknown!"));
}
};
@ -238,8 +257,7 @@ pub async fn token(req: HttpRequest,
.ok_or_else(|| ErrorUnauthorized("Client not found"))?;
if !client.secret.eq(&client_secret) {
log::warn!("Token request failed: client secret is invalid! {:#?}", query.0);
return Ok(HttpResponse::Unauthorized().body("Client secret is invalid!"));
return Ok(error_response(&query, "invalid_request", "Client secret is invalid!"));
}
let token_response = match (query.grant_type.as_str(),
@ -251,30 +269,25 @@ pub async fn token(req: HttpRequest,
.await.unwrap()
{
None => {
log::warn!("Token request failed: Session not found! {:#?}", query.0);
return Ok(HttpResponse::NotFound().body("Session not found!"));
return Ok(error_response(&query, "invalid_request", "Session not found!"));
}
Some(s) => s,
};
if session.client != client.id {
log::warn!("Token request failed: Client mismatch! {:#?}", query.0);
return Ok(HttpResponse::Unauthorized().body("Client mismatch!"));
return Ok(error_response(&query, "invalid_request", "Client mismatch!"));
}
if session.redirect_uri != q.redirect_uri {
log::warn!("Token request failed: Invalid redirect URI! {:#?}", query.0);
return Ok(HttpResponse::Unauthorized().body("Invalid redirect URI!"));
return Ok(error_response(&query, "invalid_request", "Invalid redirect URI!"));
}
if session.authorization_code_expire_at < time() {
log::warn!("Token request failed: Authorization code expired! {:#?}", query.0);
return Ok(HttpResponse::Unauthorized().body("Authorization code expired!"));
return Ok(error_response(&query, "invalid_request", "Authorization code expired!"));
}
if session.authorization_code_used {
log::warn!("Token request failed: Authorization already used! {:#?}", query.0);
return Ok(HttpResponse::Unauthorized().body("Authorization already used!"));
return Ok(error_response(&query, "invalid_request", "Authorization already used!"));
}
// Mark session as used
@ -308,15 +321,13 @@ pub async fn token(req: HttpRequest,
.await.unwrap()
{
None => {
log::warn!("Token refresh failed: Session not found! {:#?}", query.0);
return Ok(HttpResponse::NotFound().body("Session not found!"));
return Ok(error_response(&query, "invalid_request", "Session not found!"));
}
Some(s) => s,
};
if session.client != client.id {
log::warn!("Token request failed: Client mismatch! {:#?}", query.0);
return Ok(HttpResponse::Unauthorized().body("Client mismatch!"));
return Ok(error_response(&query, "invalid_request", "Client mismatch!"));
}
session.refresh_token = rand_str(OPEN_ID_REFRESH_TOKEN_LEN);
@ -338,8 +349,7 @@ pub async fn token(req: HttpRequest,
}
_ => {
log::warn!("Token request failed: Grant type unsupported or incomplete! {:#?}", query.0);
return Ok(HttpResponse::BadRequest().body("Grant type unsupported!"));
return Ok(error_response(&query, "invalid_request", "Grant type unsupported!"));
}
};