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