doido_auth/controllers/
oauth.rs1use crate::error::AuthError;
4use crate::oauth::get_provider;
5use crate::state::global;
6use doido_auth_macros::auth_controller;
7use doido_controller::axum::http::StatusCode;
8use doido_controller::axum::response::{IntoResponse, Redirect, Response};
9use doido_core::Result;
10use serde::Deserialize;
11
12pub struct AuthOauth;
14
15#[derive(Debug, Deserialize)]
16struct OAuthCallbackQuery {
17 code: String,
18 #[allow(dead_code)]
19 state: Option<String>,
20}
21
22#[auth_controller]
23impl AuthOauth {
24 pub async fn authorize(ctx: doido_controller::Context) -> Result<Response> {
26 let provider = ctx.param("provider").unwrap_or("unknown");
27 let state = global();
28 let oauth = state
29 .oauth
30 .get(provider)
31 .cloned()
32 .or_else(|| get_provider(provider))
33 .ok_or_else(|| AuthError::OAuth(format!("unknown provider {provider}")))?;
34 let url = oauth.authorize_url(&uuid::Uuid::new_v4().to_string())?;
35 Ok(Redirect::temporary(&url).into_response())
36 }
37
38 pub async fn callback(ctx: doido_controller::Context) -> Result<Response> {
40 let provider = ctx.param("provider").unwrap_or("unknown").to_string();
41 let query: OAuthCallbackQuery = ctx.params()?;
42 let state = global();
43 let oauth = state
44 .oauth
45 .get(&provider)
46 .cloned()
47 .or_else(|| get_provider(&provider))
48 .ok_or_else(|| AuthError::OAuth(format!("unknown provider {provider}")))?;
49 let tokens = oauth.exchange_code(&query.code)?;
50 Ok((StatusCode::OK, doido_controller::axum::Json(tokens)).into_response())
51 }
52}