mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
parent
ba82b1aeaf
commit
c4153c96bb
|
@ -32,7 +32,7 @@ members = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "1.2.1"
|
version = "1.2.2"
|
||||||
authors = [
|
authors = [
|
||||||
"William Brown <william@blackhats.net.au>",
|
"William Brown <william@blackhats.net.au>",
|
||||||
"James Hodgkinson <james@terminaloutcomes.com>",
|
"James Hodgkinson <james@terminaloutcomes.com>",
|
||||||
|
|
|
@ -589,7 +589,17 @@ impl LogoutOpt {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn exec(&self) {
|
pub async fn exec(&self) {
|
||||||
|
let mut tokens = read_tokens(&self.copt.get_token_cache_path()).unwrap_or_else(|_| {
|
||||||
|
error!("Error retrieving authentication token store");
|
||||||
|
std::process::exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
let instance_name = &self.copt.instance;
|
let instance_name = &self.copt.instance;
|
||||||
|
let n_lookup = instance_name.clone().unwrap_or_default();
|
||||||
|
let Some(token_instance) = tokens.instances.get_mut(&n_lookup) else {
|
||||||
|
println!("No sessions for instance {}", n_lookup);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let spn: String = if self.local_only {
|
let spn: String = if self.local_only {
|
||||||
// For now we just remove this from the token store.
|
// For now we just remove this from the token store.
|
||||||
|
@ -624,61 +634,63 @@ impl LogoutOpt {
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Parse it for the username.
|
|
||||||
|
|
||||||
if let Err(e) = client.logout().await {
|
|
||||||
error!("Failed to logout - {:?}", e);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Server acked the logout, lets proceed with the local cleanup now.
|
|
||||||
|
|
||||||
|
// Parse it for the SPN. Annoying but it's what we have to do
|
||||||
|
// because we don't know what token was used in the lower to client calls.
|
||||||
let jwsc = match JwsCompact::from_str(&token) {
|
let jwsc = match JwsCompact::from_str(&token) {
|
||||||
Ok(j) => j,
|
Ok(j) => j,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(?err, "Unable to parse token");
|
error!(?err, "Unable to parse token");
|
||||||
|
info!("The token can be removed locally with `--local-only`");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let jws_verifier = if let Some(pub_jwk) = jwsc.get_jwk_pubkey() {
|
let Some(key_id) = jwsc.kid() else {
|
||||||
match JwsEs256Verifier::try_from(pub_jwk) {
|
error!("Invalid token, missing KeyID");
|
||||||
|
info!("The token can be removed locally with `--local-only`");
|
||||||
|
std::process::exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(pub_jwk) = token_instance.keys().get(key_id) else {
|
||||||
|
error!("Invalid instance, no signing keys are available");
|
||||||
|
info!("The token can be removed locally with `--local-only`");
|
||||||
|
std::process::exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
let jws_verifier = match JwsEs256Verifier::try_from(pub_jwk) {
|
||||||
Ok(verifier) => verifier,
|
Ok(verifier) => verifier,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(?err, "Unable to configure jws verifier");
|
error!(?err, "Unable to configure jws verifier");
|
||||||
|
info!("The token can be removed locally with `--local-only`");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error!("Unable to access token public key");
|
|
||||||
std::process::exit(1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let uat = match jws_verifier.verify(&jwsc).and_then(|jws| {
|
let uat = match jws_verifier.verify(&jwsc).and_then(|jws| {
|
||||||
jws.from_json::<UserAuthToken>().map_err(|serde_err| {
|
jws.from_json::<UserAuthToken>().map_err(|serde_err| {
|
||||||
error!(?serde_err);
|
error!(?serde_err);
|
||||||
|
info!("The token can be removed locally with `--local-only`");
|
||||||
JwtError::InvalidJwt
|
JwtError::InvalidJwt
|
||||||
})
|
})
|
||||||
}) {
|
}) {
|
||||||
Ok(uat) => uat,
|
Ok(uat) => uat,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!(?e, "Unable to verify token signature, may be corrupt");
|
error!(?e, "Unable to verify token signature, may be corrupt");
|
||||||
|
info!("The token can be removed locally with `--local-only`");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
uat.spn
|
// Now we know we have a valid(ish) token, call the server to do the logout.
|
||||||
};
|
if let Err(e) = client.logout().await {
|
||||||
|
error!("Failed to logout - {:?}", e);
|
||||||
let mut tokens = read_tokens(&self.copt.get_token_cache_path()).unwrap_or_else(|_| {
|
|
||||||
error!("Error retrieving authentication token store");
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
});
|
}
|
||||||
|
|
||||||
let n_lookup = instance_name.clone().unwrap_or_else(|| "".to_string());
|
// Server acked the logout, lets proceed with the local cleanup now, return
|
||||||
let Some(token_instance) = tokens.instances.get_mut(&n_lookup) else {
|
// the spn so the outer parts know what to remove.
|
||||||
println!("No sessions for {}", spn);
|
uat.spn
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove our old one
|
// Remove our old one
|
||||||
|
|
|
@ -782,8 +782,8 @@ pub struct ReauthOpt {
|
||||||
pub struct LogoutOpt {
|
pub struct LogoutOpt {
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
copt: CommonOpt,
|
copt: CommonOpt,
|
||||||
#[clap(short, long, hide = true)]
|
#[clap(short, long)]
|
||||||
/// Do not send the logout to the server - only remove the session token locally
|
/// Do not send a logout request to the server - only remove the session token locally.
|
||||||
local_only: bool,
|
local_only: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue