Can sign in and sign out
This commit is contained in:
parent
fffa561d43
commit
2f8fd66648
@ -29,6 +29,8 @@ async fn main() -> std::io::Result<()> {
|
||||
))
|
||||
// Web configuration routes
|
||||
.route("/", web::get().to(web_ui::home))
|
||||
.route("/oidc_cb", web::get().to(web_ui::oidc_cb))
|
||||
.route("/sign_out", web::get().to(web_ui::sign_out))
|
||||
|
||||
// API routes
|
||||
// TODO
|
||||
|
@ -1,17 +1,18 @@
|
||||
use crate::app_config::AppConfig;
|
||||
use crate::constants::{STATE_KEY, USER_SESSION_KEY};
|
||||
use crate::server::{HttpFailure, HttpResult};
|
||||
use crate::user::User;
|
||||
use crate::user::{User, UserID};
|
||||
use crate::utils;
|
||||
use actix_session::Session;
|
||||
use actix_web::HttpResponse;
|
||||
use actix_web::{web, HttpResponse};
|
||||
use light_openid::primitives::OpenIDConfig;
|
||||
|
||||
// Main route
|
||||
pub async fn home(session: Session) -> HttpResult {
|
||||
// Get user information
|
||||
// Get user information, requesting authentication if information is missing
|
||||
let Some(user): Option<User> = session.get(USER_SESSION_KEY)? else {
|
||||
// Generate auth state
|
||||
let state = utils::rand_str(10);
|
||||
let state = utils::rand_str(50);
|
||||
session.insert(STATE_KEY, &state)?;
|
||||
|
||||
let oidc = AppConfig::get().openid_provider();
|
||||
@ -28,3 +29,68 @@ pub async fn home(session: Session) -> HttpResult {
|
||||
|
||||
Ok(HttpResponse::Ok().body("You are authenticated!"))
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct AuthCallbackQuery {
|
||||
code: String,
|
||||
state: String,
|
||||
}
|
||||
|
||||
// Authenticate user callback
|
||||
pub async fn oidc_cb(session: Session, query: web::Query<AuthCallbackQuery>) -> HttpResult {
|
||||
if session.get(STATE_KEY)? != Some(query.state.to_string()) {
|
||||
return Ok(HttpResponse::BadRequest()
|
||||
.append_header(("content-type", "text/html"))
|
||||
.body("State mismatch! <a href='/'>Try again</a>"));
|
||||
}
|
||||
|
||||
let oidc = AppConfig::get().openid_provider();
|
||||
let config = OpenIDConfig::load_from_url(oidc.configuration_url)
|
||||
.await
|
||||
.map_err(HttpFailure::OpenID)?;
|
||||
|
||||
let (token, _) = match config
|
||||
.request_token(
|
||||
oidc.client_id,
|
||||
oidc.client_secret,
|
||||
&query.code,
|
||||
&oidc.redirect_url,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
log::error!("Failed to request user token! {e}");
|
||||
|
||||
return Ok(HttpResponse::BadRequest()
|
||||
.append_header(("content-type", "text/html"))
|
||||
.body("Authentication failed! <a href='/'>Try again</a>"));
|
||||
}
|
||||
};
|
||||
|
||||
let (user, _) = config
|
||||
.request_user_info(&token)
|
||||
.await
|
||||
.map_err(HttpFailure::OpenID)?;
|
||||
|
||||
let user = User {
|
||||
id: UserID(user.sub),
|
||||
name: user.name.unwrap_or("no_name".to_string()),
|
||||
email: user.email.unwrap_or("no@mail.com".to_string()),
|
||||
};
|
||||
log::info!("Successful authentication as {:?}", user);
|
||||
session.insert(USER_SESSION_KEY, user)?;
|
||||
|
||||
Ok(HttpResponse::Found()
|
||||
.insert_header(("location", "/"))
|
||||
.finish())
|
||||
}
|
||||
|
||||
/// De-authenticate user
|
||||
pub async fn sign_out(session: Session) -> HttpResult {
|
||||
session.remove(USER_SESSION_KEY);
|
||||
|
||||
Ok(HttpResponse::Found()
|
||||
.insert_header(("location", "/"))
|
||||
.finish())
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct UserID(String);
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||
pub struct UserID(pub String);
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||
pub struct User {
|
||||
pub id: UserID,
|
||||
pub name: String,
|
||||
|
Loading…
Reference in New Issue
Block a user