57 lines
2.2 KiB
Rust
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))
|
|
}
|