100 lines
3.1 KiB
Rust
100 lines
3.1 KiB
Rust
|
use std::env;
|
||
|
|
||
|
use async_session::{MemoryStore, Session, SessionStore};
|
||
|
use axum::{
|
||
|
extract::Query,
|
||
|
http::HeaderMap,
|
||
|
response::{IntoResponse, Redirect},
|
||
|
Extension,
|
||
|
};
|
||
|
use oauth2::{
|
||
|
basic::BasicClient, reqwest::async_http_client, AuthUrl, AuthorizationCode, ClientId,
|
||
|
ClientSecret, CsrfToken, RedirectUrl, TokenResponse, TokenUrl,
|
||
|
};
|
||
|
use reqwest::header::SET_COOKIE;
|
||
|
use serde::Deserialize;
|
||
|
|
||
|
use crate::{User, COOKIE_NAME};
|
||
|
|
||
|
pub fn oauth_client() -> BasicClient {
|
||
|
let client_id = env::var("GITEA_CLIENT_ID").expect("Missing GITEA_CLIENT_ID");
|
||
|
let client_secret = env::var("GITEA_CLIENT_SECRET").expect("Missing GITEA_CLIENT_SECRET");
|
||
|
let redirect_url = env::var("GITEA_REDIRECT_URL")
|
||
|
.unwrap_or_else(|_| "http://127.0.0.1:3000/auth/authorized".to_string());
|
||
|
|
||
|
let auth_url =
|
||
|
env::var("GITEA_AUTH_URL").unwrap_or_else(|_| "https://git.front.kjuulh.io".to_string());
|
||
|
|
||
|
let token_url =
|
||
|
env::var("GITEA_TOKEN_URL").unwrap_or_else(|_| "https://git.front.kjuulh.io".to_string());
|
||
|
|
||
|
BasicClient::new(
|
||
|
ClientId::new(client_id),
|
||
|
Some(ClientSecret::new(client_secret)),
|
||
|
AuthUrl::new(auth_url).expect("AuthUrl was invalid"),
|
||
|
Some(TokenUrl::new(token_url).expect("Token url was invalid")),
|
||
|
)
|
||
|
.set_redirect_uri(RedirectUrl::new(redirect_url).expect("RedirectUrl was invalid"))
|
||
|
}
|
||
|
|
||
|
pub async fn gitea(Extension(client): Extension<BasicClient>) -> impl IntoResponse {
|
||
|
let (auth_url, _crsf_token) = client.authorize_url(CsrfToken::new_random).url();
|
||
|
|
||
|
Redirect::to(&auth_url.to_string())
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Deserialize)]
|
||
|
pub struct AuthRequest {
|
||
|
code: String,
|
||
|
state: String,
|
||
|
}
|
||
|
|
||
|
pub async fn authorized(
|
||
|
Query(query): Query<AuthRequest>,
|
||
|
Extension(store): Extension<MemoryStore>,
|
||
|
Extension(oauth_client): Extension<BasicClient>,
|
||
|
) -> impl IntoResponse {
|
||
|
let token = oauth_client
|
||
|
.exchange_code(AuthorizationCode::new(query.code.clone()))
|
||
|
.request_async(async_http_client)
|
||
|
.await
|
||
|
.expect("failed to get http client");
|
||
|
|
||
|
let client = reqwest::Client::new();
|
||
|
let user_data_json = client
|
||
|
.get(get_gitea_user_data_url())
|
||
|
.bearer_auth(token.access_token().secret())
|
||
|
.send()
|
||
|
.await
|
||
|
.expect("Request did not succeed");
|
||
|
// .text()
|
||
|
// .await
|
||
|
// .unwrap();
|
||
|
|
||
|
let user_data: User = user_data_json
|
||
|
.json::<User>()
|
||
|
.await
|
||
|
.expect("could not parse user");
|
||
|
|
||
|
let mut session = Session::new();
|
||
|
session
|
||
|
.insert("user", &user_data)
|
||
|
.expect("could not insert user data");
|
||
|
|
||
|
let cookie = store
|
||
|
.store_session(session)
|
||
|
.await
|
||
|
.expect("could not insert session")
|
||
|
.expect("session was not valid");
|
||
|
|
||
|
let cookie = format!("{}={}; SameSite=Lax; Path=/", COOKIE_NAME, cookie);
|
||
|
|
||
|
let mut headers = HeaderMap::new();
|
||
|
headers.insert(SET_COOKIE, cookie.parse().expect("Cookie is not valid"));
|
||
|
(headers, Redirect::to("/"))
|
||
|
}
|
||
|
|
||
|
fn get_gitea_user_data_url() -> String {
|
||
|
env::var("GITEA_USER_INFO_URL").expect("Missing GITEA_USER_INFO_URL")
|
||
|
}
|