use super::verify;
use actix_web::{HttpRequest, HttpResponse};
use serde_json::json;
pub async fn oauth2_userinfo_handler(req: HttpRequest) -> HttpResponse {
let header = req
.headers()
.get("Authorization")
.and_then(|v| v.to_str().ok())
.unwrap_or("");
let Some(token) = header.strip_prefix("Bearer ").filter(|t| !t.is_empty()) else {
return unauthorized(None);
};
let Some(claims) = verify::<super::BearerClaims>(token) else {
return unauthorized(Some("Invalid access token"));
};
if claims.typ != "at" {
return unauthorized(Some("Token is not an access token"));
}
if super::now_unix() >= claims.exp {
return unauthorized(Some("Access token has expired"));
}
let mut body = json!({
"sub": claims.email,
"email": claims.email,
"client_id": claims.cid,
});
if let Some(scope) = claims.scope {
body["scope"] = json!(scope);
}
HttpResponse::Ok().json(body)
}
fn unauthorized(detail: Option<&str>) -> HttpResponse {
let challenge = match detail {
Some(detail) => format!("Bearer error=\"invalid_token\", error_description=\"{detail}\""),
None => "Bearer".to_string(),
};
HttpResponse::Unauthorized()
.insert_header(("WWW-Authenticate", challenge))
.json(json!({
"error": "invalid_token",
"error_description": detail.unwrap_or("Missing Authorization header"),
}))
}