oauth2
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
pub mod auth;
|
||||
pub mod auth_pages;
|
||||
pub mod oauth2;
|
||||
pub mod admin_categories;
|
||||
pub mod admin_dashboard;
|
||||
pub mod admin_form;
|
||||
|
||||
56
src/controllers/oauth2.rs
Normal file
56
src/controllers/oauth2.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
//! 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))
|
||||
}
|
||||
Reference in New Issue
Block a user