e034b46
use axum::extract::{Query, State};
use axum_extra::extract::cookie::CookieJar;
use serde::Deserialize;
use crate::error::AuthError;
use crate::features::AuthService;
use crate::features::oauth::types::OAuthProvider;
use crate::features::oauth::types::{CallbackCmd, OAuthLoginResp};
use export::data::AppResponseData;
use super::super::cookies;
#[derive(Debug, Deserialize, utoipa::IntoParams)]
pub(crate) struct CallbackQuery {
pub provider: OAuthProvider,
pub code: String,
pub state: String,
}
#[utoipa::path(
get,
path = "/auth/oauth/callback",
tag = "auth",
params(CallbackQuery),
responses(
(status = 200, description = "OAuth login completed. Returns token pair and the resolved user_id.", body = AppResponseData<OAuthLoginResp>),
(status = 400, description = "Missing state cookie or invalid state.", body = super::super::openapi::ErrorBody),
(status = 401, description = "OAuth flow rejected.", body = super::super::openapi::ErrorBody),
),
)]
pub(crate) async fn handler(
State(svc): State<AuthService>,
jar: CookieJar,
Query(q): Query<CallbackQuery>,
) -> Result<(CookieJar, AppResponseData<OAuthLoginResp>), AuthError> {
let cookie_name =
crate::features::oauth::usecase::cookie_name(&svc.config.cookie_name_prefix, q.provider);
let temp_key_value = cookies::read_cookie_value(&jar, &cookie_name).ok_or_else(|| {
AuthError::BadRequest(format!("missing oauth state cookie {cookie_name}"))
})?;
let cmd = CallbackCmd {
provider: q.provider,
code: q.code,
state: q.state,
temp_key_value,
app_id: None,
};
let resp = svc.oauth_callback(cmd).await?;
let jar = cookies::remove_cookie(jar, &cookie_name);
Ok((jar, AppResponseData::ok(resp)))
}