mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
Fix oauth2 response value and other wasm goodies (#1135)
This commit is contained in:
parent
a55c0ca68d
commit
6c67041fda
|
@ -328,6 +328,11 @@ async fn oauth2_authorise(
|
|||
res.insert_header("WWW-Authenticate", "Bearer");
|
||||
Ok(res)
|
||||
}
|
||||
Err(Oauth2Error::AccessDenied) => {
|
||||
// If scopes are not available for this account.
|
||||
let res = tide::Response::new(tide::StatusCode::Forbidden);
|
||||
Ok(res)
|
||||
}
|
||||
/*
|
||||
RFC - If the request fails due to a missing, invalid, or mismatching
|
||||
redirection URI, or if the client identifier is missing or invalid,
|
||||
|
@ -428,7 +433,7 @@ async fn oauth2_authorise_permit(
|
|||
// Turns out this instinct was correct:
|
||||
// https://www.proofpoint.com/us/blog/cloud-security/microsoft-and-github-oauth-implementation-vulnerabilities-lead-redirection
|
||||
// Possible to use this with a malicious client configuration to phish / spam.
|
||||
tide::Response::new(500)
|
||||
tide::Response::new(tide::StatusCode::InternalServerError)
|
||||
}
|
||||
};
|
||||
res.insert_header("X-KANIDM-OPID", hvalue);
|
||||
|
|
|
@ -166,15 +166,15 @@ pub(crate) async fn create_ldap_server(
|
|||
if address.starts_with(":::") {
|
||||
// takes :::xxxx to xxxx
|
||||
let port = address.replacen(":::", "", 1);
|
||||
eprintln!("Address '{}' looks like an attempt to wildcard bind with IPv6 on port {} - please try using ldapbindaddress = '[::]:{}'", address, port, port);
|
||||
error!("Address '{}' looks like an attempt to wildcard bind with IPv6 on port {} - please try using ldapbindaddress = '[::]:{}'", address, port, port);
|
||||
};
|
||||
|
||||
let addr = net::SocketAddr::from_str(address).map_err(|e| {
|
||||
eprintln!("Could not parse LDAP server address {} -> {:?}", address, e);
|
||||
error!("Could not parse LDAP server address {} -> {:?}", address, e);
|
||||
})?;
|
||||
|
||||
let listener = TcpListener::bind(&addr).await.map_err(|e| {
|
||||
eprintln!(
|
||||
error!(
|
||||
"Could not bind to LDAP server address {} -> {:?}",
|
||||
address, e
|
||||
);
|
||||
|
@ -182,12 +182,12 @@ pub(crate) async fn create_ldap_server(
|
|||
|
||||
match opt_tls_params {
|
||||
Some(tls_params) => {
|
||||
eprintln!("Starting LDAPS interface ldaps://{} ...", address);
|
||||
info!("Starting LDAPS interface ldaps://{} ...", address);
|
||||
let tls_parms = tls_params.build();
|
||||
tokio::spawn(tls_acceptor(listener, tls_parms, qe_r_ref));
|
||||
}
|
||||
None => {
|
||||
eprintln!("The server won't run without TLS!");
|
||||
error!("The server won't run without TLS!");
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ if [ -z "$KANI_TMP" ]; then
|
|||
fi
|
||||
|
||||
if [ -z "$KANI_CARGO_OPTS" ]; then
|
||||
KANI_CARGO_OPTS=--debug
|
||||
KANI_CARGO_OPTS=""
|
||||
fi
|
||||
|
||||
CONFIG_FILE="../../examples/insecure_server.toml"
|
||||
|
|
|
@ -1894,6 +1894,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
// get the account
|
||||
let account = self.target_to_account(&pwu.target_uuid)?;
|
||||
|
||||
info!(session_id = %pwu.target_uuid, "Processing password hash upgrade");
|
||||
|
||||
// check, does the pw still match?
|
||||
let same = account.check_credential_pw(pwu.existing_password.as_str())?;
|
||||
|
||||
|
@ -1917,6 +1919,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
}
|
||||
|
||||
fn process_unixpwupgrade(&mut self, pwu: &UnixPasswordUpgrade) -> Result<(), OperationError> {
|
||||
info!(session_id = %pwu.target_uuid, "Processing unix password hash upgrade");
|
||||
|
||||
let account = self
|
||||
.qs_write
|
||||
.internal_search_uuid(&pwu.target_uuid)
|
||||
|
@ -1951,6 +1955,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
&mut self,
|
||||
wci: &WebauthnCounterIncrement,
|
||||
) -> Result<(), OperationError> {
|
||||
info!(session_id = %wci.target_uuid, "Processing webauthn counter increment");
|
||||
|
||||
let mut account = self.target_to_account(&wci.target_uuid)?;
|
||||
|
||||
// Generate an optional mod and then attempt to apply it.
|
||||
|
@ -1977,6 +1983,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
&mut self,
|
||||
bcr: &BackupCodeRemoval,
|
||||
) -> Result<(), OperationError> {
|
||||
info!(session_id = %bcr.target_uuid, "Processing backup code removal");
|
||||
|
||||
let account = self.target_to_account(&bcr.target_uuid)?;
|
||||
// Generate an optional mod and then attempt to apply it.
|
||||
let modlist = account
|
||||
|
|
|
@ -125,6 +125,15 @@ function takeObject(idx) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
let cachedBigInt64Memory0 = new BigInt64Array();
|
||||
|
||||
function getBigInt64Memory0() {
|
||||
if (cachedBigInt64Memory0.byteLength === 0) {
|
||||
cachedBigInt64Memory0 = new BigInt64Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedBigInt64Memory0;
|
||||
}
|
||||
|
||||
function debugString(val) {
|
||||
// primitive types
|
||||
const type = typeof val;
|
||||
|
@ -222,9 +231,9 @@ function addBorrowedObject(obj) {
|
|||
heap[--stack_pointer] = obj;
|
||||
return stack_pointer;
|
||||
}
|
||||
function __wbg_adapter_36(arg0, arg1, arg2) {
|
||||
function __wbg_adapter_48(arg0, arg1, arg2) {
|
||||
try {
|
||||
wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hc4597b5e800bc69f(arg0, arg1, addBorrowedObject(arg2));
|
||||
wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha070437c619effa2(arg0, arg1, addBorrowedObject(arg2));
|
||||
} finally {
|
||||
heap[stack_pointer++] = undefined;
|
||||
}
|
||||
|
@ -251,12 +260,12 @@ function makeClosure(arg0, arg1, dtor, f) {
|
|||
|
||||
return real;
|
||||
}
|
||||
function __wbg_adapter_39(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__Fn__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h0a5a9d3730766f31(arg0, arg1, addHeapObject(arg2));
|
||||
function __wbg_adapter_51(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__Fn__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hd36b5f2296664138(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wbg_adapter_42(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h45c01f13304b15cf(arg0, arg1, addHeapObject(arg2));
|
||||
function __wbg_adapter_54(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h83dbed9e96aca169(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -336,14 +345,14 @@ async function load(module, imports) {
|
|||
function getImports() {
|
||||
const imports = {};
|
||||
imports.wbg = {};
|
||||
imports.wbg.__wbindgen_is_bigint = function(arg0) {
|
||||
const ret = typeof(getObject(arg0)) === 'bigint';
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_is_undefined = function(arg0) {
|
||||
const ret = getObject(arg0) === undefined;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_in = function(arg0, arg1) {
|
||||
const ret = getObject(arg0) in getObject(arg1);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_number_get = function(arg0, arg1) {
|
||||
const obj = getObject(arg1);
|
||||
const ret = typeof(obj) === 'number' ? obj : undefined;
|
||||
|
@ -363,6 +372,10 @@ function getImports() {
|
|||
getInt32Memory0()[arg0 / 4 + 1] = len0;
|
||||
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
|
||||
};
|
||||
imports.wbg.__wbindgen_is_bigint = function(arg0) {
|
||||
const ret = typeof(getObject(arg0)) === 'bigint';
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_is_object = function(arg0) {
|
||||
const val = getObject(arg0);
|
||||
const ret = typeof(val) === 'object' && val !== null;
|
||||
|
@ -372,6 +385,18 @@ function getImports() {
|
|||
const ret = typeof(getObject(arg0)) === 'string';
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_bigint_from_i64 = function(arg0) {
|
||||
const ret = arg0;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) {
|
||||
const ret = BigInt.asUintN(64, arg0);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_error_new = function(arg0, arg1) {
|
||||
const ret = new Error(getStringFromWasm0(arg0, arg1));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
|
||||
const ret = getObject(arg0);
|
||||
return addHeapObject(ret);
|
||||
|
@ -380,6 +405,10 @@ function getImports() {
|
|||
const ret = getStringFromWasm0(arg0, arg1);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_jsval_eq = function(arg0, arg1) {
|
||||
const ret = getObject(arg0) === getObject(arg1);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
||||
takeObject(arg0);
|
||||
};
|
||||
|
@ -417,31 +446,15 @@ function getImports() {
|
|||
wasm.__wbindgen_free(arg0, arg1);
|
||||
}
|
||||
};
|
||||
imports.wbg.__wbg_BigInt_d0c7d465bfa30d3b = function(arg0) {
|
||||
const ret = BigInt(arg0);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_BigInt_1fab4952b6c4a499 = function(arg0) {
|
||||
const ret = BigInt(BigInt.asUintN(64, arg0));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_is_null = function(arg0) {
|
||||
const ret = getObject(arg0) === null;
|
||||
imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) {
|
||||
const ret = getObject(arg0) == getObject(arg1);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_BigInt_06819bca5a5bedef = function(arg0) {
|
||||
const ret = BigInt(getObject(arg0));
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_BigInt_67359e71cae1c6c9 = function(arg0) {
|
||||
const ret = BigInt(getObject(arg0));
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_get_2268d91a19a98b92 = function(arg0, arg1) {
|
||||
const ret = getObject(arg0)[takeObject(arg1)];
|
||||
imports.wbg.__wbg_getwithrefkey_15c62c2b8546208d = function(arg0, arg1) {
|
||||
const ret = getObject(arg0)[getObject(arg1)];
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_set_c943d600fa71e4dd = function(arg0, arg1, arg2) {
|
||||
imports.wbg.__wbg_set_20cbc34131e76824 = function(arg0, arg1, arg2) {
|
||||
getObject(arg0)[takeObject(arg1)] = takeObject(arg2);
|
||||
};
|
||||
imports.wbg.__wbg_debug_783a3d4910bc24c7 = function(arg0, arg1) {
|
||||
|
@ -919,10 +932,6 @@ function getImports() {
|
|||
const ret = result;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_new_8d2af00bc1e329ee = function(arg0, arg1) {
|
||||
const ret = new Error(getStringFromWasm0(arg0, arg1));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_message_fe2af63ccc8985bc = function(arg0) {
|
||||
const ret = getObject(arg0).message;
|
||||
return addHeapObject(ret);
|
||||
|
@ -1000,10 +1009,6 @@ function getImports() {
|
|||
const ret = result;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_has_8359f114ce042f5a = function() { return handleError(function (arg0, arg1) {
|
||||
const ret = Reflect.has(getObject(arg0), getObject(arg1));
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_set_bf3f89b92d5a34bf = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2));
|
||||
return ret;
|
||||
|
@ -1012,6 +1017,12 @@ function getImports() {
|
|||
const ret = JSON.stringify(getObject(arg0));
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbindgen_bigint_get_as_i64 = function(arg0, arg1) {
|
||||
const v = getObject(arg1);
|
||||
const ret = typeof(v) === 'bigint' ? v : undefined;
|
||||
getBigInt64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0n : ret;
|
||||
getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||
const ret = debugString(getObject(arg1));
|
||||
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
|
@ -1026,16 +1037,16 @@ function getImports() {
|
|||
const ret = wasm.memory;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper5843 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 1415, __wbg_adapter_36);
|
||||
imports.wbg.__wbindgen_closure_wrapper5891 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 1425, __wbg_adapter_48);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper6004 = function(arg0, arg1, arg2) {
|
||||
const ret = makeClosure(arg0, arg1, 1450, __wbg_adapter_39);
|
||||
imports.wbg.__wbindgen_closure_wrapper6051 = function(arg0, arg1, arg2) {
|
||||
const ret = makeClosure(arg0, arg1, 1460, __wbg_adapter_51);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper6732 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 1712, __wbg_adapter_42);
|
||||
imports.wbg.__wbindgen_closure_wrapper6781 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 1724, __wbg_adapter_54);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
|
||||
|
@ -1049,6 +1060,7 @@ function initMemory(imports, maybe_memory) {
|
|||
function finalizeInit(instance, module) {
|
||||
wasm = instance.exports;
|
||||
init.__wbindgen_wasm_module = module;
|
||||
cachedBigInt64Memory0 = new BigInt64Array();
|
||||
cachedFloat64Memory0 = new Float64Array();
|
||||
cachedInt32Memory0 = new Int32Array();
|
||||
cachedUint32Memory0 = new Uint32Array();
|
||||
|
|
Binary file not shown.
|
@ -30,6 +30,7 @@ enum State {
|
|||
consent_token: String,
|
||||
},
|
||||
ConsentGranted(String),
|
||||
AccessDenied(Option<String>),
|
||||
ErrInvalidRequest,
|
||||
}
|
||||
|
||||
|
@ -48,6 +49,9 @@ pub enum Oauth2Msg {
|
|||
consent_token: String,
|
||||
},
|
||||
Redirect(String),
|
||||
AccessDenied {
|
||||
kopid: Option<String>,
|
||||
},
|
||||
Error {
|
||||
emsg: String,
|
||||
kopid: Option<String>,
|
||||
|
@ -160,6 +164,8 @@ impl Oauth2App {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if status == 403 {
|
||||
Ok(Oauth2Msg::AccessDenied { kopid })
|
||||
} else {
|
||||
let text = JsFuture::from(resp.text()?).await?;
|
||||
let emsg = text.as_string().unwrap_or_else(|| "".to_string());
|
||||
|
@ -380,6 +386,11 @@ impl Component for Oauth2App {
|
|||
// We need to send off fetch task here.
|
||||
true
|
||||
}
|
||||
Oauth2Msg::AccessDenied { kopid } => {
|
||||
console::error!(format!("{:?}", kopid).as_str());
|
||||
self.state = State::AccessDenied(kopid);
|
||||
true
|
||||
}
|
||||
Oauth2Msg::Error { emsg, kopid } => {
|
||||
self.state = State::ErrInvalidRequest;
|
||||
console::error!(format!("{:?}", kopid).as_str());
|
||||
|
@ -505,6 +516,24 @@ impl Component for Oauth2App {
|
|||
</div>
|
||||
}
|
||||
}
|
||||
State::AccessDenied(kopid) => {
|
||||
html! {
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<h1>{ "Access Denied" } </h1>
|
||||
<p>
|
||||
{ "You do not have access to the requested resources." }
|
||||
</p>
|
||||
<p>
|
||||
{ if let Some(opid) = kopid {
|
||||
format!("Operation ID: {}", opid)
|
||||
} else {
|
||||
"Operation ID: -".to_string()
|
||||
}
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
State::ErrInvalidRequest => {
|
||||
html! {
|
||||
<div class="alert alert-danger" role="alert">
|
||||
|
|
|
@ -70,6 +70,7 @@ pub enum AdminRoute {
|
|||
|
||||
enum State {
|
||||
LoginRequired,
|
||||
LoggingOut,
|
||||
Verifying,
|
||||
Authenticated(String),
|
||||
Error { emsg: String, kopid: Option<String> },
|
||||
|
@ -91,6 +92,7 @@ pub struct ViewsApp {
|
|||
pub enum ViewsMsg {
|
||||
Verified(String),
|
||||
Logout,
|
||||
LogoutComplete,
|
||||
ProfileInfoRecieved { uat: UserAuthToken },
|
||||
Error { emsg: String, kopid: Option<String> },
|
||||
}
|
||||
|
@ -159,7 +161,22 @@ impl Component for ViewsApp {
|
|||
true
|
||||
}
|
||||
ViewsMsg::Logout => {
|
||||
match models::get_bearer_token() {
|
||||
Some(tk) => {
|
||||
models::clear_bearer_token();
|
||||
ctx.link().send_future(async {
|
||||
match Self::fetch_logout(tk).await {
|
||||
Ok(v) => v,
|
||||
Err(v) => v.into(),
|
||||
}
|
||||
});
|
||||
self.state = State::LoggingOut;
|
||||
}
|
||||
None => self.state = State::LoginRequired,
|
||||
}
|
||||
true
|
||||
}
|
||||
ViewsMsg::LogoutComplete => {
|
||||
self.state = State::LoginRequired;
|
||||
true
|
||||
}
|
||||
|
@ -199,7 +216,7 @@ impl Component for ViewsApp {
|
|||
.push(Route::Login);
|
||||
html! { <div></div> }
|
||||
}
|
||||
State::Verifying => {
|
||||
State::LoggingOut | State::Verifying => {
|
||||
html! {
|
||||
<main class="text-center form-signin h-100">
|
||||
<div class="vert-center">
|
||||
|
@ -366,7 +383,7 @@ impl ViewsApp {
|
|||
Ok(ViewsMsg::Verified(token))
|
||||
} else if status == 401 {
|
||||
// Not valid, re-auth
|
||||
Ok(ViewsMsg::Logout)
|
||||
Ok(ViewsMsg::LogoutComplete)
|
||||
} else {
|
||||
let headers = resp.headers();
|
||||
let kopid = headers.get("x-kanidm-opid").ok().flatten();
|
||||
|
@ -390,6 +407,38 @@ impl ViewsApp {
|
|||
uat: uat.into_inner(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn fetch_logout(token: String) -> Result<ViewsMsg, FetchError> {
|
||||
let mut opts = RequestInit::new();
|
||||
opts.method("GET");
|
||||
opts.mode(RequestMode::SameOrigin);
|
||||
|
||||
let request = Request::new_with_str_and_init("/v1/logout", &opts)?;
|
||||
|
||||
request
|
||||
.headers()
|
||||
.set("content-type", "application/json")
|
||||
.expect_throw("failed to set header");
|
||||
request
|
||||
.headers()
|
||||
.set("authorization", format!("Bearer {}", token).as_str())
|
||||
.expect_throw("failed to set header");
|
||||
|
||||
let window = utils::window();
|
||||
let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?;
|
||||
let resp: Response = resp_value.dyn_into().expect_throw("Invalid response type");
|
||||
let status = resp.status();
|
||||
|
||||
if status == 200 {
|
||||
Ok(ViewsMsg::LogoutComplete)
|
||||
} else {
|
||||
let headers = resp.headers();
|
||||
let kopid = headers.get("x-kanidm-opid").ok().flatten();
|
||||
let text = JsFuture::from(resp.text()?).await?;
|
||||
let emsg = text.as_string().unwrap_or_else(|| "".to_string());
|
||||
Ok(ViewsMsg::Error { emsg, kopid })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn admin_routes(route: &AdminRoute) -> Html {
|
||||
|
|
Loading…
Reference in a new issue