Files
kompress_eshop/src/controllers/oauth2.rs
2026-06-18 18:26:40 +02:00

57 lines
2.2 KiB
Rust

//! HTML OAuth2 (Google) sign-in.
//!
//! The provider round-trip is handled by loco-oauth2's built-in authorize +
//! cookie-callback handlers. The callback upserts the user, stores an OAuth2
//! session, sets loco-oauth2's *private* session cookie, and redirects to the
//! configured `protected_url` — which is our [`complete`] handler. There we
//! trade the OAuth2 session for OUR Loco `auth_token` JWT cookie, so the rest of
//! the app (the Casbin layer, `guard`, the unified `/login`) treats a Google
//! user exactly like a password login. Admins (matching `ADMIN_EMAIL`) land on
//! the dashboard, everyone else on the storefront.
use loco_oauth2::controllers::{
middleware::OAuth2CookieUser,
oauth2::{google_authorization_url, google_callback_cookie},
};
use loco_rs::prelude::*;
use crate::{
controllers::auth as auth_controller,
models::{o_auth2_sessions, users, users::OAuth2UserProfile},
shared::guard,
};
type GoogleCookieUser = OAuth2CookieUser<OAuth2UserProfile, users::Model, o_auth2_sessions::Model>;
/// Bridge from loco-oauth2's session cookie to our own auth cookie.
#[debug_handler]
async fn complete(State(ctx): State<AppContext>, user: GoogleCookieUser) -> Result<Response> {
let user: &users::Model = user.as_ref();
let jwt_secret = ctx.config.get_jwt_config()?;
let token = user
.generate_jwt(&jwt_secret.secret, jwt_secret.expiration)
.or_else(|_| unauthorized("unauthorized!"))?;
let dest = if guard::is_admin(&ctx, user) {
"/admin/dashboard"
} else {
"/"
};
format::render()
.cookies(&[auth_controller::auth_cookie(&token, jwt_secret.expiration)])?
.redirect(dest)
}
pub fn routes() -> Routes {
Routes::new()
.prefix("api/oauth2")
// Redirects the browser to Google's consent screen.
.add("/google", get(google_authorization_url))
// Google redirects back here; loco-oauth2 exchanges the code, upserts
// the user, and redirects to `protected_url` (/api/oauth2/protected).
.add(
"/google/callback/cookie",
get(google_callback_cookie::<OAuth2UserProfile, users::Model, o_auth2_sessions::Model>),
)
.add("/protected", get(complete))
}