mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
feat: allow switch between spn and name for claims (#1043)
This commit is contained in:
parent
5c0a99ba34
commit
2b11ad0ad5
|
@ -1755,6 +1755,29 @@ impl KanidmClient {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn idm_oauth2_rs_prefer_short_username(&self, id: &str) -> Result<(), ClientError> {
|
||||||
|
let mut update_oauth2_rs = Entry {
|
||||||
|
attrs: BTreeMap::new(),
|
||||||
|
};
|
||||||
|
update_oauth2_rs.attrs.insert(
|
||||||
|
"oauth2_prefer_short_username".to_string(),
|
||||||
|
vec!["true".to_string()],
|
||||||
|
);
|
||||||
|
self.perform_patch_request(format!("/v1/oauth2/{}", id).as_str(), update_oauth2_rs)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
pub async fn idm_oauth2_rs_prefer_spn_username(&self, id: &str) -> Result<(), ClientError> {
|
||||||
|
let mut update_oauth2_rs = Entry {
|
||||||
|
attrs: BTreeMap::new(),
|
||||||
|
};
|
||||||
|
update_oauth2_rs.attrs.insert(
|
||||||
|
"oauth2_prefer_short_username".to_string(),
|
||||||
|
vec!["false".to_string()],
|
||||||
|
);
|
||||||
|
self.perform_patch_request(format!("/v1/oauth2/{}", id).as_str(), update_oauth2_rs)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
// ==== recycle bin
|
// ==== recycle bin
|
||||||
pub async fn recycle_bin_list(&self) -> Result<Vec<Entry>, ClientError> {
|
pub async fn recycle_bin_list(&self) -> Result<Vec<Entry>, ClientError> {
|
||||||
self.perform_get_request("/v1/recycle_bin").await
|
self.perform_get_request("/v1/recycle_bin").await
|
||||||
|
|
|
@ -333,7 +333,7 @@ pub struct UserAuthToken {
|
||||||
// may depend on the client application.
|
// may depend on the client application.
|
||||||
pub expiry: time::OffsetDateTime,
|
pub expiry: time::OffsetDateTime,
|
||||||
pub uuid: Uuid,
|
pub uuid: Uuid,
|
||||||
// pub name: String,
|
pub name: String,
|
||||||
pub displayname: String,
|
pub displayname: String,
|
||||||
pub spn: String,
|
pub spn: String,
|
||||||
pub mail_primary: Option<String>,
|
pub mail_primary: Option<String>,
|
||||||
|
|
|
@ -16,6 +16,8 @@ impl Oauth2Opt {
|
||||||
Oauth2Opt::DisablePkce(nopt) => nopt.copt.debug,
|
Oauth2Opt::DisablePkce(nopt) => nopt.copt.debug,
|
||||||
Oauth2Opt::EnableLegacyCrypto(nopt) => nopt.copt.debug,
|
Oauth2Opt::EnableLegacyCrypto(nopt) => nopt.copt.debug,
|
||||||
Oauth2Opt::DisableLegacyCrypto(nopt) => nopt.copt.debug,
|
Oauth2Opt::DisableLegacyCrypto(nopt) => nopt.copt.debug,
|
||||||
|
Oauth2Opt::PreferShortUsername(nopt) => nopt.copt.debug,
|
||||||
|
Oauth2Opt::PreferSPNUsername(nopt) => nopt.copt.debug,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +174,26 @@ impl Oauth2Opt {
|
||||||
Err(e) => error!("Error -> {:?}", e),
|
Err(e) => error!("Error -> {:?}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Oauth2Opt::PreferShortUsername(nopt) => {
|
||||||
|
let client = nopt.copt.to_client().await;
|
||||||
|
match client
|
||||||
|
.idm_oauth2_rs_prefer_short_username(nopt.name.as_str())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => println!("Success"),
|
||||||
|
Err(e) => error!("Error -> {:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Oauth2Opt::PreferSPNUsername(nopt) => {
|
||||||
|
let client = nopt.copt.to_client().await;
|
||||||
|
match client
|
||||||
|
.idm_oauth2_rs_prefer_spn_username(nopt.name.as_str())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => println!("Success"),
|
||||||
|
Err(e) => error!("Error -> {:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,13 +239,17 @@ pub enum ServiceAccountPosix {
|
||||||
pub struct PersonUpdateOpt {
|
pub struct PersonUpdateOpt {
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
aopts: AccountCommonOpt,
|
aopts: AccountCommonOpt,
|
||||||
#[clap(long, short, help="Set the legal name for the person.")]
|
#[clap(long, short, help = "Set the legal name for the person.")]
|
||||||
legalname: Option<String>,
|
legalname: Option<String>,
|
||||||
#[clap(long, short, help="Set the account name for the person.")]
|
#[clap(long, short, help = "Set the account name for the person.")]
|
||||||
newname: Option<String>,
|
newname: Option<String>,
|
||||||
#[clap(long, short='i', help="Set the display name for the person.")]
|
#[clap(long, short = 'i', help = "Set the display name for the person.")]
|
||||||
displayname: Option<String>,
|
displayname: Option<String>,
|
||||||
#[clap(long, short, help="Set the mail address, can be set multiple times for multiple addresses. The first listed mail address is the 'primary'")]
|
#[clap(
|
||||||
|
long,
|
||||||
|
short,
|
||||||
|
help = "Set the mail address, can be set multiple times for multiple addresses. The first listed mail address is the 'primary'"
|
||||||
|
)]
|
||||||
mail: Option<Vec<String>>,
|
mail: Option<Vec<String>>,
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
copt: CommonOpt,
|
copt: CommonOpt,
|
||||||
|
@ -339,11 +343,19 @@ pub enum ServiceAccountCredential {
|
||||||
pub struct ServiceAccountUpdateOpt {
|
pub struct ServiceAccountUpdateOpt {
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
aopts: AccountCommonOpt,
|
aopts: AccountCommonOpt,
|
||||||
#[clap(long, short, help="Set the account name for the service account.")]
|
#[clap(long, short, help = "Set the account name for the service account.")]
|
||||||
newname: Option<String>,
|
newname: Option<String>,
|
||||||
#[clap(long, short='i', help="Set the display name for the service account.")]
|
#[clap(
|
||||||
|
long,
|
||||||
|
short = 'i',
|
||||||
|
help = "Set the display name for the service account."
|
||||||
|
)]
|
||||||
displayname: Option<String>,
|
displayname: Option<String>,
|
||||||
#[clap(long, short, help="Set the mail address, can be set multiple times for multiple addresses. The first listed mail address is the 'primary'")]
|
#[clap(
|
||||||
|
long,
|
||||||
|
short,
|
||||||
|
help = "Set the mail address, can be set multiple times for multiple addresses. The first listed mail address is the 'primary'"
|
||||||
|
)]
|
||||||
mail: Option<Vec<String>>,
|
mail: Option<Vec<String>>,
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
copt: CommonOpt,
|
copt: CommonOpt,
|
||||||
|
@ -575,10 +587,16 @@ pub enum Oauth2Opt {
|
||||||
/// Disable legacy signing crypto on this oauth2 resource server. This is the default.
|
/// Disable legacy signing crypto on this oauth2 resource server. This is the default.
|
||||||
#[clap(name = "disable_legacy_crypto")]
|
#[clap(name = "disable_legacy_crypto")]
|
||||||
DisableLegacyCrypto(Named),
|
DisableLegacyCrypto(Named),
|
||||||
|
#[clap(name = "prefer_short_username")]
|
||||||
|
/// Use the 'name' attribute instead of 'spn' for the preferred_username
|
||||||
|
PreferShortUsername(Named),
|
||||||
|
#[clap(name = "prefer_spn_username")]
|
||||||
|
/// Use the 'spn' attribute instead of 'name' for the preferred_username
|
||||||
|
PreferSPNUsername(Named),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
pub struct OptSetDomainDisplayName{
|
pub struct OptSetDomainDisplayName {
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
copt: CommonOpt,
|
copt: CommonOpt,
|
||||||
#[clap(name = "new_display_Name")]
|
#[clap(name = "new_display_Name")]
|
||||||
|
@ -636,7 +654,7 @@ pub enum KanidmClientOpt {
|
||||||
/// Actions to manage and view person (user) accounts
|
/// Actions to manage and view person (user) accounts
|
||||||
Person {
|
Person {
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
commands: PersonOpt
|
commands: PersonOpt,
|
||||||
},
|
},
|
||||||
/// Actions to manage groups
|
/// Actions to manage groups
|
||||||
Group {
|
Group {
|
||||||
|
@ -666,9 +684,7 @@ pub enum KanidmClientOpt {
|
||||||
commands: RawOpt,
|
commands: RawOpt,
|
||||||
},
|
},
|
||||||
/// Print the program version and exit
|
/// Print the program version and exit
|
||||||
Version {
|
Version {},
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, clap::Parser)]
|
#[derive(Debug, clap::Parser)]
|
||||||
|
|
|
@ -1183,7 +1183,8 @@ pub const JSON_IDM_HP_ACP_OAUTH2_MANAGE_PRIV_V1: &str = r#"{
|
||||||
"es256_private_key_der",
|
"es256_private_key_der",
|
||||||
"oauth2_allow_insecure_client_disable_pkce",
|
"oauth2_allow_insecure_client_disable_pkce",
|
||||||
"rs256_private_key_der",
|
"rs256_private_key_der",
|
||||||
"oauth2_jwt_legacy_crypto_enable"
|
"oauth2_jwt_legacy_crypto_enable",
|
||||||
|
"oauth2_prefer_short_username"
|
||||||
],
|
],
|
||||||
"acp_modify_removedattr": [
|
"acp_modify_removedattr": [
|
||||||
"description",
|
"description",
|
||||||
|
@ -1197,7 +1198,8 @@ pub const JSON_IDM_HP_ACP_OAUTH2_MANAGE_PRIV_V1: &str = r#"{
|
||||||
"es256_private_key_der",
|
"es256_private_key_der",
|
||||||
"oauth2_allow_insecure_client_disable_pkce",
|
"oauth2_allow_insecure_client_disable_pkce",
|
||||||
"rs256_private_key_der",
|
"rs256_private_key_der",
|
||||||
"oauth2_jwt_legacy_crypto_enable"
|
"oauth2_jwt_legacy_crypto_enable",
|
||||||
|
"oauth2_prefer_short_username"
|
||||||
],
|
],
|
||||||
"acp_modify_presentattr": [
|
"acp_modify_presentattr": [
|
||||||
"description",
|
"description",
|
||||||
|
@ -1207,7 +1209,8 @@ pub const JSON_IDM_HP_ACP_OAUTH2_MANAGE_PRIV_V1: &str = r#"{
|
||||||
"oauth2_rs_scope_map",
|
"oauth2_rs_scope_map",
|
||||||
"oauth2_rs_implicit_scopes",
|
"oauth2_rs_implicit_scopes",
|
||||||
"oauth2_allow_insecure_client_disable_pkce",
|
"oauth2_allow_insecure_client_disable_pkce",
|
||||||
"oauth2_jwt_legacy_crypto_enable"
|
"oauth2_jwt_legacy_crypto_enable",
|
||||||
|
"oauth2_prefer_short_username"
|
||||||
],
|
],
|
||||||
"acp_modify_class": [],
|
"acp_modify_class": [],
|
||||||
"acp_create_attr": [
|
"acp_create_attr": [
|
||||||
|
@ -1219,7 +1222,8 @@ pub const JSON_IDM_HP_ACP_OAUTH2_MANAGE_PRIV_V1: &str = r#"{
|
||||||
"oauth2_rs_scope_map",
|
"oauth2_rs_scope_map",
|
||||||
"oauth2_rs_implicit_scopes",
|
"oauth2_rs_implicit_scopes",
|
||||||
"oauth2_allow_insecure_client_disable_pkce",
|
"oauth2_allow_insecure_client_disable_pkce",
|
||||||
"oauth2_jwt_legacy_crypto_enable"
|
"oauth2_jwt_legacy_crypto_enable",
|
||||||
|
"oauth2_prefer_short_username"
|
||||||
],
|
],
|
||||||
"acp_create_class": ["oauth2_resource_server", "oauth2_resource_server_basic", "object"]
|
"acp_create_class": ["oauth2_resource_server", "oauth2_resource_server_basic", "object"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1018,6 +1018,35 @@ pub const JSON_SCHEMA_ATTR_DYNGROUP_FILTER: &str = r#"{
|
||||||
}
|
}
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
|
pub const JSON_SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME: &str = r#"{
|
||||||
|
"attrs": {
|
||||||
|
"class": [
|
||||||
|
"object",
|
||||||
|
"system",
|
||||||
|
"attributetype"
|
||||||
|
],
|
||||||
|
"description": [
|
||||||
|
"Use 'name' instead of 'spn' in the preferred_username claim"
|
||||||
|
],
|
||||||
|
"index": [],
|
||||||
|
"unique": [
|
||||||
|
"false"
|
||||||
|
],
|
||||||
|
"multivalue": [
|
||||||
|
"false"
|
||||||
|
],
|
||||||
|
"attributename": [
|
||||||
|
"oauth2_prefer_short_username"
|
||||||
|
],
|
||||||
|
"syntax": [
|
||||||
|
"BOOLEAN"
|
||||||
|
],
|
||||||
|
"uuid": [
|
||||||
|
"00000000-0000-0000-0000-ffff00000109"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"#;
|
||||||
|
|
||||||
// === classes ===
|
// === classes ===
|
||||||
|
|
||||||
pub const JSON_SCHEMA_CLASS_PERSON: &str = r#"
|
pub const JSON_SCHEMA_CLASS_PERSON: &str = r#"
|
||||||
|
@ -1344,7 +1373,8 @@ pub const JSON_SCHEMA_CLASS_OAUTH2_RS: &str = r#"
|
||||||
"oauth2_rs_implicit_scopes",
|
"oauth2_rs_implicit_scopes",
|
||||||
"oauth2_allow_insecure_client_disable_pkce",
|
"oauth2_allow_insecure_client_disable_pkce",
|
||||||
"rs256_private_key_der",
|
"rs256_private_key_der",
|
||||||
"oauth2_jwt_legacy_crypto_enable"
|
"oauth2_jwt_legacy_crypto_enable",
|
||||||
|
"oauth2_prefer_short_username"
|
||||||
],
|
],
|
||||||
"systemmust": [
|
"systemmust": [
|
||||||
"oauth2_rs_name",
|
"oauth2_rs_name",
|
||||||
|
|
|
@ -184,6 +184,8 @@ pub const UUID_SCHEMA_ATTR_SCOPE: Uuid = uuid!("00000000-0000-0000-0000-ffff0000
|
||||||
pub const UUID_SCHEMA_CLASS_SERVICE_ACCOUNT: Uuid = uuid!("00000000-0000-0000-0000-ffff00000106");
|
pub const UUID_SCHEMA_CLASS_SERVICE_ACCOUNT: Uuid = uuid!("00000000-0000-0000-0000-ffff00000106");
|
||||||
pub const _UUID_SCHEMA_CLASS_DYNGROUP: Uuid = uuid!("00000000-0000-0000-0000-ffff00000107");
|
pub const _UUID_SCHEMA_CLASS_DYNGROUP: Uuid = uuid!("00000000-0000-0000-0000-ffff00000107");
|
||||||
pub const _UUID_SCHEMA_ATTR_DYNGROUP_FILTER: Uuid = uuid!("00000000-0000-0000-0000-ffff00000108");
|
pub const _UUID_SCHEMA_ATTR_DYNGROUP_FILTER: Uuid = uuid!("00000000-0000-0000-0000-ffff00000108");
|
||||||
|
pub const _UUID_SCHEMA_ATTR_OAUTH2_PREFERR_SHORT_USERNAME: Uuid =
|
||||||
|
uuid!("00000000-0000-0000-0000-ffff00000109");
|
||||||
|
|
||||||
// System and domain infos
|
// System and domain infos
|
||||||
// I'd like to strongly criticise william of the past for making poor choices about these allocations.
|
// I'd like to strongly criticise william of the past for making poor choices about these allocations.
|
||||||
|
|
|
@ -202,7 +202,7 @@ impl Account {
|
||||||
auth_type,
|
auth_type,
|
||||||
expiry,
|
expiry,
|
||||||
uuid: self.uuid,
|
uuid: self.uuid,
|
||||||
// name: self.name.clone(),
|
name: self.name.clone(),
|
||||||
displayname: self.displayname.clone(),
|
displayname: self.displayname.clone(),
|
||||||
spn: self.spn.clone(),
|
spn: self.spn.clone(),
|
||||||
mail_primary: self.mail_primary.clone(),
|
mail_primary: self.mail_primary.clone(),
|
||||||
|
|
|
@ -205,6 +205,7 @@ pub struct Oauth2RS {
|
||||||
userinfo_endpoint: Url,
|
userinfo_endpoint: Url,
|
||||||
jwks_uri: Url,
|
jwks_uri: Url,
|
||||||
scopes_supported: Vec<String>,
|
scopes_supported: Vec<String>,
|
||||||
|
prefer_short_username: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for Oauth2RS {
|
impl std::fmt::Debug for Oauth2RS {
|
||||||
|
@ -367,6 +368,10 @@ impl<'a> Oauth2ResourceServersWriteTransaction<'a> {
|
||||||
.map(|e| !e)
|
.map(|e| !e)
|
||||||
.unwrap_or(true);
|
.unwrap_or(true);
|
||||||
|
|
||||||
|
let prefer_short_username = ent
|
||||||
|
.get_ava_single_bool("oauth2_prefer_short_username")
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
let mut authorization_endpoint = self.inner.origin.clone();
|
let mut authorization_endpoint = self.inner.origin.clone();
|
||||||
authorization_endpoint.set_path("/ui/oauth2");
|
authorization_endpoint.set_path("/ui/oauth2");
|
||||||
|
|
||||||
|
@ -408,6 +413,7 @@ impl<'a> Oauth2ResourceServersWriteTransaction<'a> {
|
||||||
userinfo_endpoint,
|
userinfo_endpoint,
|
||||||
jwks_uri,
|
jwks_uri,
|
||||||
scopes_supported,
|
scopes_supported,
|
||||||
|
prefer_short_username,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((client_id, rscfg))
|
Ok((client_id, rscfg))
|
||||||
|
@ -935,6 +941,13 @@ impl Oauth2ResourceServersReadTransaction {
|
||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
admin_warn!("prefer_short_username: {:?}", o2rs.prefer_short_username);
|
||||||
|
let preferred_username = if o2rs.prefer_short_username {
|
||||||
|
Some(code_xchg.uat.name.clone())
|
||||||
|
} else {
|
||||||
|
Some(code_xchg.uat.spn.clone())
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: If max_age was requested in the request, we MUST provide auth_time.
|
// TODO: If max_age was requested in the request, we MUST provide auth_time.
|
||||||
|
|
||||||
// amr == auth method
|
// amr == auth method
|
||||||
|
@ -963,10 +976,10 @@ impl Oauth2ResourceServersReadTransaction {
|
||||||
// Map from displayname
|
// Map from displayname
|
||||||
name: Some(code_xchg.uat.displayname.clone()),
|
name: Some(code_xchg.uat.displayname.clone()),
|
||||||
// Map from spn
|
// Map from spn
|
||||||
preferred_username: Some(code_xchg.uat.spn.clone()),
|
|
||||||
scopes: code_xchg.scopes.clone(),
|
scopes: code_xchg.scopes.clone(),
|
||||||
email,
|
email,
|
||||||
email_verified,
|
email_verified,
|
||||||
|
preferred_username,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
claims: Default::default(),
|
claims: Default::default(),
|
||||||
|
|
|
@ -2646,6 +2646,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
JSON_SCHEMA_CLASS_OAUTH2_RS,
|
JSON_SCHEMA_CLASS_OAUTH2_RS,
|
||||||
JSON_SCHEMA_CLASS_OAUTH2_RS_BASIC,
|
JSON_SCHEMA_CLASS_OAUTH2_RS_BASIC,
|
||||||
JSON_SCHEMA_ATTR_NSUNIQUEID,
|
JSON_SCHEMA_ATTR_NSUNIQUEID,
|
||||||
|
JSON_SCHEMA_ATTR_OAUTH2_PREFER_SHORT_USERNAME,
|
||||||
];
|
];
|
||||||
|
|
||||||
let r = idm_schema
|
let r = idm_schema
|
||||||
|
|
Loading…
Reference in a new issue