chore: add and fix hanldlers to use openid with casdoor for Single Sign-On
This commit is contained in:
parent
4cbdf902f8
commit
97a411bdc8
@ -1,3 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use urlencoding::{encode,decode};
|
||||
// use tokio::sync::RwLock;
|
||||
@ -33,6 +34,9 @@ use crate::{
|
||||
TotpMode,
|
||||
Random,
|
||||
AppConnectInfo,
|
||||
OpenidData,
|
||||
OpenidCli,
|
||||
// OpenidClaims,
|
||||
// UserNotifyData,
|
||||
// TOKEN_AUTH_VALUE,
|
||||
// TOKEN_KEY_VALUE,
|
||||
@ -73,7 +77,7 @@ pub fn users_router_handlers() -> Router {
|
||||
// }
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
// has_cookie=true;
|
||||
// TODO check value
|
||||
// TODO check value
|
||||
// let sid: String = format!("{}",&auth_state.sid());
|
||||
// println!("auth_sid: {}",&sid);
|
||||
// println!("id: {}",&auth_state.id());
|
||||
@ -205,7 +209,7 @@ pub fn users_router_handlers() -> Router {
|
||||
"signup_handler"
|
||||
);
|
||||
if !auth_state.is_admin() {
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
println!("Count error: {}",e);
|
||||
0
|
||||
});
|
||||
@ -215,7 +219,7 @@ pub fn users_router_handlers() -> Router {
|
||||
let _ = req_handler.trace_req(msg);
|
||||
return Redirect::temporary( &format!("/")).into_response();
|
||||
}
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
println!("Count error: {}",e);
|
||||
-1
|
||||
});
|
||||
@ -237,7 +241,7 @@ pub fn users_router_handlers() -> Router {
|
||||
Ok(totp) => {
|
||||
req_handler.context.insert("otp_code", &totp.get_secret_base32());
|
||||
req_handler.context.insert("otp_url", &totp.get_url());
|
||||
req_handler.context.insert("otp_qr", &totp.get_qr().unwrap_or_default());
|
||||
req_handler.context.insert("otp_qr", &totp.get_qr_base64().unwrap_or_default());
|
||||
req_handler.context.insert("totp_digits", &app_dbs.config.totp_digits);
|
||||
req_handler.context.insert("totp_algorithm",&format!("{}",&app_dbs.config.totp_algorithm));
|
||||
},
|
||||
@ -347,7 +351,7 @@ pub fn users_router_handlers() -> Router {
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
otp_enabled = false;
|
||||
}
|
||||
@ -370,14 +374,14 @@ pub fn users_router_handlers() -> Router {
|
||||
} else {
|
||||
DEFAULT_ROLES.to_owned()
|
||||
};
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
let _ = req_handler.trace_req( format!("Users count error: {}",e));
|
||||
println!("Count error: {}",e);
|
||||
-1
|
||||
});
|
||||
let isadmin = if user_data.id == "A" || total_users < 1 {
|
||||
true
|
||||
} else {
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let mut new_items = user_data.items.to_owned();
|
||||
@ -428,7 +432,6 @@ pub fn users_router_handlers() -> Router {
|
||||
}
|
||||
};
|
||||
let session_token = req_handler.new_token();
|
||||
println!("session: {}", &session_token.to_string());
|
||||
let session_cookie = add_session_cookie(true,&cookies, &session_token, &str_user_data, 0, &app_dbs, "/").await;
|
||||
let _ = req_handler.trace_req(format!("User '{}' created",&user_data.name));
|
||||
if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie); }
|
||||
@ -455,7 +458,7 @@ pub fn users_router_handlers() -> Router {
|
||||
&random,
|
||||
"login_handler"
|
||||
);
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
let _ = req_handler.trace_req( format!("Users count error: {}",e));
|
||||
println!("Count error: {}",e);
|
||||
-1
|
||||
@ -469,6 +472,7 @@ pub fn users_router_handlers() -> Router {
|
||||
if req_handler.req_header.is_browser() {
|
||||
res_headers.append(axum::http::header::CONTENT_TYPE,"text/html; charset=utf-8".parse().unwrap());
|
||||
}
|
||||
req_handler.context.insert("openid_auths", &app_dbs.config.openid_auths.clone().into_keys().collect::<Vec<String>>());
|
||||
// req_handler.context.insert("with_menu", "1");
|
||||
req_handler.context.insert("use_mail", &app_dbs.config.use_mail);
|
||||
req_handler.context.insert("totp_mode", &format!("{}",&app_dbs.config.totp_mode));
|
||||
@ -487,14 +491,90 @@ pub fn users_router_handlers() -> Router {
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
}
|
||||
async fn post_login_handler(
|
||||
async fn login_openid_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
Extension(openid_clients): Extension<Arc<HashMap<String,OpenidCli>>>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(user_login): Json<UserLogin>,
|
||||
axum::extract::Path(data): axum::extract::Path<String>,
|
||||
) -> Response {
|
||||
dbg!(&header);
|
||||
dbg!(&uri);
|
||||
dbg!(&data);
|
||||
SessionStoreDB::cleanup_data(&app_dbs).await;
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"login_handler"
|
||||
);
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
let _ = req_handler.trace_req( format!("Users count error: {}",e));
|
||||
println!("Count error: {}",e);
|
||||
-1
|
||||
});
|
||||
if total_users < 1 {
|
||||
let _ = req_handler.trace_req(String::from("No users found"));
|
||||
return Redirect::temporary( &format!("/signup")).into_response();
|
||||
}
|
||||
if data.is_empty() {
|
||||
return Redirect::temporary( &format!("/login")).into_response();
|
||||
}
|
||||
let (str_user_data,url) = if let Some(openid_conf) = app_dbs.config.openid_auths.get(&data) {
|
||||
if let Some(openid_cli) = openid_clients.get(&data) {
|
||||
dbg!(&openid_conf);
|
||||
match openid_conf.get_auth(openid_cli).await {
|
||||
Ok(openid) => {
|
||||
//let _ = req_handler.trace_req(format!("User '{}' created",&user_data.name));
|
||||
let str_user_data = format!("{}|{}|{}", &data, openid.token.secret(), openid.nonce.secret());
|
||||
//let session_cookie = add_session_cookie(true,&cookies, &session_token, &str_user_data, 0, &app_dbs, "/").await;
|
||||
//if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie) };
|
||||
//let _new_auth_state = AuthState::from_cookie(session_cookie.to_string(), &app_dbs).await;
|
||||
/*req_handler = ReqHandler::new(
|
||||
req_handler.req_header,
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&new_auth_state,
|
||||
&random,
|
||||
"post_login_handler"
|
||||
);*/
|
||||
//let _ = req_handler.trace_req(format!("user '{}', new token: '{}', cookie: '{}' ",&user_login.name, &session_token, &session_cookie));
|
||||
(str_user_data, format!("{}", openid.url.to_string()))
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Error openid login handler: {}", e);
|
||||
(String::from(""), String::from("/login"))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(String::from(""), String::from("/login"))
|
||||
}
|
||||
} else {
|
||||
(String::from(""), String::from("/login"))
|
||||
};
|
||||
let session_token = req_handler.new_token();
|
||||
dbg!(&url);
|
||||
let session_cookie = add_session_cookie(true,&cookies, &session_token, &str_user_data, 0, &app_dbs, "/").await;
|
||||
if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie) };
|
||||
let _new_auth_state = AuthState::from_cookie(session_cookie.to_string(), &app_dbs).await;
|
||||
return Redirect::temporary(&format!("{}",url)).into_response()
|
||||
}
|
||||
|
||||
async fn login_user (
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
app_dbs: Arc<AppDBs>,
|
||||
cookies: Cookies,
|
||||
random: Random,
|
||||
app_connect_info: AppConnectInfo,
|
||||
user_login: UserLogin,
|
||||
source: &str,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let mut req_handler = ReqHandler::new(
|
||||
@ -505,7 +585,8 @@ pub fn users_router_handlers() -> Router {
|
||||
&random,
|
||||
"post_login_handler"
|
||||
);
|
||||
if user_login.name.is_empty() || user_login.password.is_empty() {
|
||||
dbg!(&user_login);
|
||||
if user_login.name.is_empty() || source != "from_login_openid" && user_login.password.is_empty() {
|
||||
let _ = req_handler.trace_req(String::from("Empty name or password"));
|
||||
// return Err(error_page(&SignupError::MissingDetails));
|
||||
return (
|
||||
@ -514,6 +595,8 @@ pub fn users_router_handlers() -> Router {
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
dbg!(&user_login);
|
||||
dbg!(&source);
|
||||
let field = if user_login.name.contains("@") {
|
||||
"email"
|
||||
} else {
|
||||
@ -523,6 +606,7 @@ pub fn users_router_handlers() -> Router {
|
||||
println!("Error select: {}", e);
|
||||
User::default()
|
||||
});
|
||||
dbg!(&user_sel);
|
||||
if user_sel.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("No name '{}' found",&user_login.name));
|
||||
// User not exists
|
||||
@ -532,6 +616,7 @@ pub fn users_router_handlers() -> Router {
|
||||
"Error data"
|
||||
).into_response();
|
||||
}
|
||||
dbg!(&user_sel);
|
||||
if user_sel.status != UserStatus::Active && user_sel.status != UserStatus::Created {
|
||||
let _ = req_handler.trace_req(format!("user '{}' in not valid status: {}",&user_login.name, &user_sel.status));
|
||||
return (
|
||||
@ -540,53 +625,59 @@ pub fn users_router_handlers() -> Router {
|
||||
"Error status"
|
||||
).into_response();
|
||||
}
|
||||
if verify_password(&user_login.password, &user_sel.password).is_err() {
|
||||
let _ = req_handler.trace_req(format!("user '{}' not valid password: {}",&user_login.name, &user_sel.password));
|
||||
println!("password NOT valid");
|
||||
// TODO
|
||||
//return Err(error_page(&SignupError::PasswordsDoNotMatch))
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error data"
|
||||
).into_response();
|
||||
}
|
||||
let result=format!("{}:{}","OK",&user_sel.otp_verified);
|
||||
if app_dbs.config.totp_mode != TotpMode::No {
|
||||
if user_login.otp_auth.is_empty()
|
||||
&& (app_dbs.config.totp_mode == TotpMode::Mandatory || user_sel.otp_enabled)
|
||||
{
|
||||
let _ = req_handler.trace_req(format!("user '{}' not valid Totp: {}",&user_login.name, &user_sel.otp_enabled));
|
||||
dbg!(&user_sel);
|
||||
let result = if source == "from_login_openid" {
|
||||
format!("{}:true", "OK")
|
||||
} else {
|
||||
if verify_password(&user_login.password, &user_sel.password).is_err() {
|
||||
let _ = req_handler.trace_req(format!("user '{}' not valid password: {}", &user_login.name, &user_sel.password));
|
||||
println!("password NOT valid");
|
||||
// TODO
|
||||
//return Err(error_page(&SignupError::PasswordsDoNotMatch))
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
result
|
||||
"Error data"
|
||||
).into_response();
|
||||
} else if user_sel.otp_enabled && user_sel.otp_verified
|
||||
&& !user_sel.otp_base32.is_empty() && !user_sel.otp_defs.is_empty()
|
||||
{
|
||||
match req_handler.otp_check(&user_sel.otp_base32,&user_login.otp_auth, &user_sel.otp_defs) {
|
||||
Ok(val) => {
|
||||
if !val {
|
||||
let _ = req_handler.trace_req(format!("user '{}' not valid TOTP code",&user_login.name));
|
||||
}
|
||||
let result = format!("{}:{}", "OK", &user_sel.otp_verified);
|
||||
if app_dbs.config.totp_mode != TotpMode::No {
|
||||
if user_login.otp_auth.is_empty()
|
||||
&& (app_dbs.config.totp_mode == TotpMode::Mandatory || user_sel.otp_enabled)
|
||||
{
|
||||
let _ = req_handler.trace_req(format!("user '{}' not valid Totp: {}", &user_login.name, &user_sel.otp_enabled));
|
||||
return (
|
||||
req_handler.req_header.header,
|
||||
result
|
||||
).into_response();
|
||||
} else if user_sel.otp_enabled && user_sel.otp_verified
|
||||
&& !user_sel.otp_base32.is_empty() && !user_sel.otp_defs.is_empty()
|
||||
{
|
||||
match req_handler.otp_check(&user_sel.otp_base32, &user_login.otp_auth, &user_sel.otp_defs) {
|
||||
Ok(val) => {
|
||||
if !val {
|
||||
let _ = req_handler.trace_req(format!("user '{}' not valid TOTP code", &user_login.name));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = req_handler.trace_req(format!("user '{}' TOTP check error: {}", &user_login.name, e));
|
||||
println!("TOTP check: {}", e);
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = req_handler.trace_req(format!("user '{}' TOTP check error: {}",&user_login.name,e));
|
||||
println!("TOTP check: {}", e);
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
};
|
||||
user_sel.lastaccess = chrono::Utc::now().timestamp().to_string();
|
||||
if user_sel.status != UserStatus::Active { user_sel.status = UserStatus::Active }
|
||||
let user_data = user_sel.session_data();
|
||||
@ -610,11 +701,11 @@ pub fn users_router_handlers() -> Router {
|
||||
if app_dbs.config.protocol == "https" {
|
||||
(
|
||||
req_handler.req_header.header,
|
||||
result
|
||||
result
|
||||
).into_response()
|
||||
} else {
|
||||
(
|
||||
result
|
||||
result
|
||||
).into_response()
|
||||
}
|
||||
},
|
||||
@ -628,7 +719,78 @@ pub fn users_router_handlers() -> Router {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn post_login_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(user_login): Json<UserLogin>,
|
||||
) -> Response {
|
||||
login_user ( header, uri,
|
||||
app_dbs, cookies, random,
|
||||
app_connect_info,
|
||||
user_login,
|
||||
"post_login"
|
||||
).await
|
||||
}
|
||||
async fn from_login_openid_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Extension(openid_clients): Extension<Arc<HashMap<String,OpenidCli>>>,
|
||||
//axum::extract::Path(data): axum::extract::Path<String>,
|
||||
data: axum::extract::Query<OpenidData>,
|
||||
// Json(user_login): Json<UserLogin>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let user_data = auth_state.user_data();
|
||||
//let _req_handler = ReqHandler::new(
|
||||
// ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
// &app_dbs,
|
||||
// &uri,
|
||||
// &auth_state,
|
||||
// &random,
|
||||
// "post_login_handler"
|
||||
//);
|
||||
if user_data.len() > 1 && user_data[1] == data.state {
|
||||
println!("OK State {} == {}", user_data[1], data.state);
|
||||
}
|
||||
let mut user_login = UserLogin::default();
|
||||
if let Some(openid_conf) = app_dbs.config.openid_auths.get(&user_data[0]) {
|
||||
if let Some(openid_cli) = openid_clients.get(&user_data[0]) {
|
||||
dbg!(openid_conf);
|
||||
match openid_conf.get_token(openid_cli, data.code.to_owned(), user_data[2].to_owned()).await {
|
||||
Ok(data) => {
|
||||
dbg!("{}", &data);
|
||||
user_login = UserLogin {
|
||||
name: data.name.to_owned(),
|
||||
password: String::from(""),
|
||||
otp_auth: String::from(""),
|
||||
email: data.email.to_owned(),
|
||||
};
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Error openid login handler: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ! user_login.name.is_empty() {
|
||||
let _res = login_user(header, uri,
|
||||
app_dbs, cookies, random,
|
||||
app_connect_info,
|
||||
user_login,
|
||||
"from_login_openid"
|
||||
).await;
|
||||
}
|
||||
let url="https://tiicl.tls13.io:8800";
|
||||
Redirect::temporary(&format!("{}",url)).into_response()
|
||||
}
|
||||
async fn logout_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
@ -856,7 +1018,7 @@ pub fn users_router_handlers() -> Router {
|
||||
Ok(totp) => {
|
||||
req_handler.context.insert("otp_code", &user_sel.otp_base32);
|
||||
req_handler.context.insert("otp_url", &user_sel.otp_auth_url);
|
||||
req_handler.context.insert("otp_qr", &totp.get_qr().unwrap_or_default());
|
||||
req_handler.context.insert("otp_qr", &totp.get_qr_base64().unwrap_or_default());
|
||||
},
|
||||
Err(e) => {
|
||||
println!("User settings error totp: {}",e);
|
||||
@ -867,7 +1029,7 @@ pub fn users_router_handlers() -> Router {
|
||||
Ok(totp) => {
|
||||
req_handler.context.insert("otp_code", &totp.get_secret_base32());
|
||||
req_handler.context.insert("otp_url", &totp.get_url());
|
||||
req_handler.context.insert("otp_qr", &totp.get_qr().unwrap_or_default());
|
||||
req_handler.context.insert("otp_qr", &totp.get_qr_base64().unwrap_or_default());
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Error TOTP generartor: {}",e);
|
||||
@ -1707,6 +1869,10 @@ pub fn users_router_handlers() -> Router {
|
||||
|
||||
.route("/login", get(login_handler))
|
||||
.route("/login", post(post_login_handler))
|
||||
|
||||
.route("/openid/:data", get(login_openid_handler))
|
||||
//.route("/from_openid/:data", get(from_login_openid_handler))
|
||||
.route("/from_openid", get(from_login_openid_handler))
|
||||
|
||||
.route("/signup", get(signup_handler))
|
||||
.route("/signup", post(post_signup_handler))
|
||||
|
Loading…
Reference in New Issue
Block a user