chore: signin authz routes from config
This commit is contained in:
parent
814021eeac
commit
70956706f6
@ -6,4 +6,5 @@
|
||||
pub mod jwt;
|
||||
pub mod sessions;
|
||||
pub mod router;
|
||||
pub mod kratos;
|
||||
pub mod kratos;
|
||||
pub mod extauthz;
|
132
src/handlers/extauthz.rs
Normal file
132
src/handlers/extauthz.rs
Normal file
@ -0,0 +1,132 @@
|
||||
//
|
||||
/*! libresignin
|
||||
*/
|
||||
// Copyright 2022, Jesús Pérez Lorenzo
|
||||
//
|
||||
use axum::{
|
||||
// response::Html,
|
||||
// routing::get,
|
||||
// routing::post,
|
||||
// Router,
|
||||
// extract::{self,Extension,Path,Query},
|
||||
// extract::{Extension,Path},
|
||||
http::{
|
||||
header::{HeaderMap,HeaderName,HeaderValue},
|
||||
// Request, StatusCode,
|
||||
},
|
||||
// body::{Bytes, Body},
|
||||
response::{IntoResponse, Headers},
|
||||
};
|
||||
|
||||
// use crate::defs::{DataDBs};
|
||||
// use crate::utils::reqenv::ReqEnv;
|
||||
|
||||
const CHECK_HEADER: &'static str = "x-ext-authz";
|
||||
const ALLOWED_VALUE: &'static str = "allow";
|
||||
const RESULT_HEADER: &'static str = "x-ext-authz-check-result";
|
||||
const RECEIVED_HEADER: &'static str = "x-ext-authz-check-received";
|
||||
const OVERRIDE_HEADER: &'static str = "x-ext-authz-additional-header-override";
|
||||
// const OVERRIDE_GRPC_VALUE: &'static str = "grpc-additional-header-override-value";
|
||||
const RESULT_ALLOWED: &'static str = "allowed";
|
||||
const RESULT_DENIED: &'static str = "denied";
|
||||
|
||||
// pub fn create_headers(is_allowed: bool, str_head: &str, id: &str,token: &str,csrf_token: &str, cookie: &str) -> HeaderMap {
|
||||
// let mut headers = HeaderMap::new();
|
||||
// if is_allowed {
|
||||
// headers.insert(RESULT_HEADER,
|
||||
// HeaderValue::from_str(RESULT_ALLOWED).unwrap_or(HeaderValue::from_static(""))
|
||||
// );
|
||||
// } else {
|
||||
// headers.insert(RESULT_HEADER,
|
||||
// HeaderValue::from_str(RESULT_DENIED).unwrap_or(HeaderValue::from_static(""))
|
||||
// );
|
||||
// }
|
||||
// headers.insert(OVERRIDE_HEADER,
|
||||
// HeaderValue::from_str(OVERRIDE_HEADER).unwrap_or(HeaderValue::from_static(""))
|
||||
// );
|
||||
// headers.insert(RECEIVED_HEADER,
|
||||
// HeaderValue::from_str(str_head).unwrap_or(HeaderValue::from_static(""))
|
||||
// );
|
||||
// headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
|
||||
// headers.insert(ACCEPT, HeaderValue::from_static("application/json"));
|
||||
// if cookie != "" {
|
||||
// headers.insert(COOKIE, HeaderValue::from_str(cookie)
|
||||
// .unwrap_or(HeaderValue::from_static(""))
|
||||
// );
|
||||
// // headers.insert(SET_COOKIE, HeaderValue::from_str(cookie)
|
||||
// // .unwrap_or(HeaderValue::from_static(""))
|
||||
// // );
|
||||
// }
|
||||
// if token != "" {
|
||||
// headers.insert(AUTHORIZATION, HeaderValue::from_str(&format!("Bearer {}",token))
|
||||
// .unwrap_or(HeaderValue::from_static(""))
|
||||
// );
|
||||
// }
|
||||
// if csrf_token != "" {
|
||||
// headers.insert("X-CSRF-Token",
|
||||
// HeaderValue::from_str(csrf_token).unwrap_or(HeaderValue::from_static(""))
|
||||
// );
|
||||
// }
|
||||
// if id != "" {
|
||||
// headers.insert("x-kratos-authenticated-identity-id",
|
||||
// HeaderValue::from_str(id).unwrap_or(HeaderValue::from_static(""))
|
||||
// );
|
||||
// }
|
||||
// dbg!("{:#?}",&headers);
|
||||
// dbg!("{:#?}",&headers);
|
||||
// headers
|
||||
// }
|
||||
// pub async fn authz_handler(header: HeaderMap, req: Request<()> ) -> impl IntoResponse {
|
||||
pub async fn authz_handler(header: HeaderMap) -> impl IntoResponse {
|
||||
dbg!("{:#?}",&header);
|
||||
let result: &str;
|
||||
if let Some(check) = &header.get(CHECK_HEADER) {
|
||||
match check.to_str() {
|
||||
Ok(check_val) =>
|
||||
if ALLOWED_VALUE == check_val {
|
||||
result = RESULT_ALLOWED;
|
||||
} else {
|
||||
result = RESULT_DENIED;
|
||||
},
|
||||
Err(_) => result = RESULT_DENIED,
|
||||
}
|
||||
} else {
|
||||
result = RESULT_DENIED;
|
||||
}
|
||||
//let headers = create_headers("",token,csrf_token,cookie);
|
||||
// body, err := io.ReadAll(request.Body)
|
||||
// if err != nil {
|
||||
// log.Printf("[HTTP] read body failed: %v", err)
|
||||
// }
|
||||
// format!("%s %s%s, headers: %v, body: [%s]\n", request.Method, request.Host, request.URL, request.Header, body);
|
||||
let str_head = format!("head");
|
||||
// let headers = create_headers(is_allowed,&str_head,"","","","");
|
||||
let res_headers: Vec<(HeaderName, HeaderValue)> = vec![
|
||||
(HeaderName::from_static(RESULT_HEADER), HeaderValue::from_static(result)),
|
||||
(HeaderName::from_static(OVERRIDE_HEADER), HeaderValue::from_static(OVERRIDE_HEADER)),
|
||||
(HeaderName::from_static(RECEIVED_HEADER), HeaderValue::from_str(&str_head).unwrap_or(HeaderValue::from_static(""))),
|
||||
];
|
||||
// if is_allowed {
|
||||
// response.WriteHeader(StatusCode::OK)
|
||||
// } else {
|
||||
// response.WriteHeader(http.StatusForbidden)
|
||||
// response.Write([]byte(denyBody))
|
||||
// }
|
||||
dbg!("{:#?}",&res_headers);
|
||||
Headers(res_headers)
|
||||
// let html = format!(
|
||||
// r#"
|
||||
// <div>Done: {} </div>
|
||||
// "#,RESULT_ALLOWED);
|
||||
// Html(html)
|
||||
}
|
||||
// pub async fn alive_handler() -> Html<&'static str> {
|
||||
// Html("ok")
|
||||
// }
|
||||
// pub async fn ready_handler() -> Html<&'static str> {
|
||||
// Html("ok")
|
||||
// }
|
||||
// pub fn router_handlers(web_router: Router) -> Router {
|
||||
// web_router
|
||||
// .route("/authz", get(authz_handler))
|
||||
// }
|
@ -17,7 +17,10 @@ use axum::{
|
||||
response::IntoResponse,
|
||||
extract::{Extension,Path,Query},
|
||||
//http::{Request, header::HeaderMap, Method,StatusCode},
|
||||
http::{header::HeaderMap,StatusCode},
|
||||
http::{
|
||||
header::{HeaderMap,HeaderName,HeaderValue},
|
||||
StatusCode,
|
||||
},
|
||||
// body::{Bytes, Body},
|
||||
};
|
||||
// use serde::{Deserialize, Serialize};
|
||||
@ -115,7 +118,7 @@ pub async fn registration_handler(header: HeaderMap, Extension(dbs): Extension<D
|
||||
<h1>Register</h1>
|
||||
<a href='{}/login'>login</a>
|
||||
<div>Status: {} </div>
|
||||
"#,&reqenv.websrvr_url(),res.status);
|
||||
"#,&reqenv.public_url(),res.status);
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("{}",e);
|
||||
@ -162,6 +165,8 @@ pub async fn login_handler(header: HeaderMap, Extension(dbs): Extension<DataDBs>
|
||||
let flow = String::from("self-service/login");
|
||||
let query = String::from("/api?refresh=false&aal=&return_to=");
|
||||
let root_url = get_root_url(reqenv.websrvr().signin.protocol,reqenv.websrvr().signin.root,reqenv.websrvr().signin.port);
|
||||
let mut headers = HeaderMap::new();
|
||||
let ret_status: StatusCode;
|
||||
let mut user_data = HashMap::new();
|
||||
user_data.insert("password".to_string(),"19Ting22".to_string());
|
||||
user_data.insert("password_identifier".to_string(),"jesuspl".to_string());
|
||||
@ -183,6 +188,11 @@ pub async fn login_handler(header: HeaderMap, Extension(dbs): Extension<DataDBs>
|
||||
// res.session_resp.session_token);
|
||||
// return html.to_owned();
|
||||
if res.status == StatusCode::OK {
|
||||
headers.insert(
|
||||
HeaderName::from_static("x-authz"),
|
||||
HeaderValue::from_str(&format!("{}:tk:{}",res.session_resp.session.identity.id, res.session_resp.session_token)).unwrap_or(HeaderValue::from_static("")),
|
||||
);
|
||||
ret_status = StatusCode::OK;
|
||||
html = format!(
|
||||
r#"
|
||||
<h1>Login</h1>
|
||||
@ -190,39 +200,46 @@ pub async fn login_handler(header: HeaderMap, Extension(dbs): Extension<DataDBs>
|
||||
<div><a href='{}/logout/{}?token={}'>logout</a></div>
|
||||
<div>Status: {} </div>
|
||||
"#,
|
||||
&reqenv.websrvr_url(),res.session_resp.session.identity.id, res.session_resp.session_token,
|
||||
&reqenv.websrvr_url(),res.session_resp.session.identity.id, res.session_resp.session_token,
|
||||
&reqenv.public_url(),res.session_resp.session.identity.id, res.session_resp.session_token,
|
||||
&reqenv.public_url(),res.session_resp.session.identity.id, res.session_resp.session_token,
|
||||
res.status);
|
||||
} else {
|
||||
ret_status = StatusCode::OK;
|
||||
html = format!(
|
||||
r#"
|
||||
<h1>Login</h1>
|
||||
<div>Status: {} </div>
|
||||
<div><a href='{}/registration'>Registration</a></div>
|
||||
"#,res.status,&reqenv.websrvr_url());
|
||||
"#,res.status,&reqenv.public_url());
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("{}",e);
|
||||
// ret_status = StatusCode::FORBIDDEN;
|
||||
ret_status = StatusCode::NOT_FOUND;
|
||||
html = format!(
|
||||
r#"
|
||||
<h1>Login</h1>
|
||||
<div><a href='{}/registration'>Registration</a></div>
|
||||
<div>Error: {} </div>
|
||||
"#,&reqenv.websrvr_url(),e);
|
||||
"#,&reqenv.public_url(),e);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("{}",e);
|
||||
ret_status = StatusCode::BAD_REQUEST;
|
||||
// ret_status = StatusCode::UNAUTHORIZED;
|
||||
html = format!(
|
||||
r#"
|
||||
<h1>Login</h1>
|
||||
<div>Error: {} </div>
|
||||
"#,e);
|
||||
<div>Error: No Login Found </div>
|
||||
"#);
|
||||
},
|
||||
};
|
||||
Html(html)
|
||||
(ret_status, headers, Html(html))
|
||||
// (StatusCode, HeaderMap, &'static str)
|
||||
//Html(html)
|
||||
}
|
||||
pub async fn recovery_handler() -> Html<&'static str> {
|
||||
Html("<h1>Hello, World!</h1>")
|
||||
@ -255,14 +272,14 @@ pub async fn whoami(id: String, token: String,
|
||||
<div>Status: {}</div>
|
||||
<div><a href='{}/logout/{}?token={}'>logout</a></div>
|
||||
"#,res.status,
|
||||
&reqenv.websrvr_url(),id,token)
|
||||
&reqenv.public_url(),id,token)
|
||||
} else {
|
||||
html = format!(
|
||||
r#"
|
||||
<h1>whoami</h1>
|
||||
<div>Status: {}</div>
|
||||
<div><a href='{}/login'>login</a></div>
|
||||
"#,res.status, &reqenv.websrvr_url())
|
||||
"#,res.status, &reqenv.public_url())
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
@ -272,7 +289,7 @@ pub async fn whoami(id: String, token: String,
|
||||
<h1>whoami</h1>
|
||||
<div><a href='{}/login'>Login</a></div>
|
||||
<div>Error: {} </div>
|
||||
"#,&reqenv.websrvr_url(),e);
|
||||
"#,&reqenv.public_url(),e);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -308,8 +325,9 @@ pub async fn whoami_handler(Path(id): Path<String>, query: Query<QueryToken>,
|
||||
println!("flow: {}",&reqid.flow);
|
||||
println!("csrf_token: {}",&reqid.csrf);
|
||||
println!("cookie: {}",&reqid.cookie);
|
||||
let flow_logout = String::from("self-service/logout");
|
||||
let query_id = format!("/api?{}&flow={}",&urlquery.token,&reqid.flow);
|
||||
let reg_url=format!("{}/{}{}",&root_url,flow,query_id);
|
||||
let reg_url=format!("{}/{}{}",&root_url,flow_logout,query_id);
|
||||
// match on_kratos_user(reqenv.websrvr().signin,&reqid.csrf,&id,®_url,user).await {
|
||||
match logout_kratos_user(&id,&urlquery.token.to_string(),reqenv.websrvr().signin,&req_cli,&reqid.csrf,&reqid.cookie,®_url).await {
|
||||
Ok(res) => {
|
||||
@ -319,7 +337,7 @@ pub async fn whoami_handler(Path(id): Path<String>, query: Query<QueryToken>,
|
||||
<h1>Logout</h1>
|
||||
<a href='{}/login'>login</a>
|
||||
<div>Status: {}</div>
|
||||
"#,reqenv.websrvr_url(),res.status);
|
||||
"#,reqenv.public_url(),res.status);
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("{}",e);
|
||||
|
@ -21,6 +21,15 @@ use std::{
|
||||
use crate::defs::{DataDBs};
|
||||
use crate::utils::reqenv::ReqEnv;
|
||||
|
||||
use app_env::{
|
||||
// AppStore,
|
||||
// appenv::AppEnv,
|
||||
// appinfo::AppInfo,
|
||||
// appdata::AppData,
|
||||
//config::{WebServer,SigninServer,SigninAuthzRoutes,AuthzMode},
|
||||
config::{SigninAuthzRoute,AuthzMode},
|
||||
};
|
||||
|
||||
// pub async fn html_handler(Path(path): Path<String>,query: Option<Query<String>>, Extension(dbs): Extension<DataDBs>) -> Html<&'static str> {
|
||||
// pub async fn html_handler(Path(path): Path<String>,Extension(dbs): Extension<DataDBs>) -> Html<&'static str> {
|
||||
pub async fn html_handler(header: HeaderMap, Path(name): Path<String>,Extension(dbs): Extension<DataDBs>) -> Html<&'static str> {
|
||||
@ -66,3 +75,32 @@ pub fn router_handlers(web_router: Router) -> Router {
|
||||
.route("/health/alive", get(alive_handler))
|
||||
.route("/health/ready", get(ready_handler))
|
||||
}
|
||||
// These are to implement configuration defined signin authz routes
|
||||
// using authz-route "path" ,"mode"(AuthMode) and "handler"
|
||||
//
|
||||
fn add_kratos_handler(web_router: Router,route: SigninAuthzRoute) -> Router {
|
||||
let mut webrouter = web_router.to_owned();
|
||||
if route.path.is_empty() {
|
||||
return webrouter;
|
||||
}
|
||||
match route.handler.as_str() {
|
||||
// TODO Add handlers for Kratos. This should be moved from String to Enum type in SinginAuthRoute
|
||||
"headers" => webrouter = webrouter.route(route.path.as_str(), get(crate::handlers::extauthz::authz_handler)),
|
||||
_ => {
|
||||
println!("Kratos signin authz route ({}) path ({}) with handler ({}) use authz_handler",route.id,route.path,route.handler);
|
||||
webrouter = webrouter.route(route.path.as_str(), get(crate::handlers::extauthz::authz_handler));
|
||||
},
|
||||
};
|
||||
webrouter
|
||||
}
|
||||
pub fn router_authz_handlers(web_router: Router,signin_auth_routes: Vec<SigninAuthzRoute>) -> Router {
|
||||
let mut webrouter = web_router.to_owned();
|
||||
for route in signin_auth_routes {
|
||||
match route.mode {
|
||||
AuthzMode::Kratos => webrouter = add_kratos_handler(webrouter,route),
|
||||
// TODO Add new AuthMode
|
||||
_ => eprintln!("Signin authz route {} undefined mode {}",route.id,route.mode),
|
||||
}
|
||||
}
|
||||
webrouter
|
||||
}
|
@ -241,6 +241,7 @@ async fn up_web_server(webpos: usize) -> Result<()> { // WebSettings> {
|
||||
println!("Web services: done {} __________ ",chrono::Utc::now().timestamp());
|
||||
}
|
||||
let mut web_router = Router::new();
|
||||
web_router = crate::handlers::router::router_authz_handlers(web_router,config.signin.authz_routes);
|
||||
web_router = crate::handlers::router::router_handlers(web_router);
|
||||
if !config.html_path.is_empty() {
|
||||
web_router = web_router.nest(
|
||||
|
@ -114,6 +114,15 @@ impl ReqEnv {
|
||||
let config=self.req.config().websrvrs[self.req.env().curr_web].to_owned();
|
||||
format!("{}://{}:{}", config.srv_protocol, config.srv_host, config.srv_port)
|
||||
}
|
||||
#[must_use]
|
||||
pub fn public_url(&self) -> String {
|
||||
let config=self.req.config().websrvrs[self.req.env().curr_web].to_owned();
|
||||
if config.public_url.is_empty() {
|
||||
format!("{}://{}:{}", config.srv_protocol, config.srv_host, config.srv_port)
|
||||
} else {
|
||||
config.public_url
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
pub fn module(&self) -> Module {
|
||||
self.req.module()
|
||||
|
Loading…
Reference in New Issue
Block a user