Support JWT authentication on deactivate route.
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
20
Cargo.lock
generated
20
Cargo.lock
generated
@@ -3478,7 +3478,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma"
|
name = "ruma"
|
||||||
version = "0.12.6"
|
version = "0.12.6"
|
||||||
source = "git+https://github.com/matrix-construct/ruma?rev=93f28d777073e60687e8013e59d8d16b5adbdf9a#93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
source = "git+https://github.com/matrix-construct/ruma?rev=5682b88cf1bcaf0f47805d614b476b242ef075d4#5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assign",
|
"assign",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -3497,7 +3497,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-appservice-api"
|
name = "ruma-appservice-api"
|
||||||
version = "0.12.2"
|
version = "0.12.2"
|
||||||
source = "git+https://github.com/matrix-construct/ruma?rev=93f28d777073e60687e8013e59d8d16b5adbdf9a#93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
source = "git+https://github.com/matrix-construct/ruma?rev=5682b88cf1bcaf0f47805d614b476b242ef075d4#5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -3509,7 +3509,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-client-api"
|
name = "ruma-client-api"
|
||||||
version = "0.20.4"
|
version = "0.20.4"
|
||||||
source = "git+https://github.com/matrix-construct/ruma?rev=93f28d777073e60687e8013e59d8d16b5adbdf9a#93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
source = "git+https://github.com/matrix-construct/ruma?rev=5682b88cf1bcaf0f47805d614b476b242ef075d4#5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"assign",
|
"assign",
|
||||||
@@ -3532,7 +3532,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-common"
|
name = "ruma-common"
|
||||||
version = "0.15.4"
|
version = "0.15.4"
|
||||||
source = "git+https://github.com/matrix-construct/ruma?rev=93f28d777073e60687e8013e59d8d16b5adbdf9a#93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
source = "git+https://github.com/matrix-construct/ruma?rev=5682b88cf1bcaf0f47805d614b476b242ef075d4#5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"base64",
|
"base64",
|
||||||
@@ -3565,7 +3565,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-events"
|
name = "ruma-events"
|
||||||
version = "0.30.5"
|
version = "0.30.5"
|
||||||
source = "git+https://github.com/matrix-construct/ruma?rev=93f28d777073e60687e8013e59d8d16b5adbdf9a#93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
source = "git+https://github.com/matrix-construct/ruma?rev=5682b88cf1bcaf0f47805d614b476b242ef075d4#5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
@@ -3591,7 +3591,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-federation-api"
|
name = "ruma-federation-api"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
source = "git+https://github.com/matrix-construct/ruma?rev=93f28d777073e60687e8013e59d8d16b5adbdf9a#93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
source = "git+https://github.com/matrix-construct/ruma?rev=5682b88cf1bcaf0f47805d614b476b242ef075d4#5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"headers",
|
"headers",
|
||||||
@@ -3613,7 +3613,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identifiers-validation"
|
name = "ruma-identifiers-validation"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
source = "git+https://github.com/matrix-construct/ruma?rev=93f28d777073e60687e8013e59d8d16b5adbdf9a#93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
source = "git+https://github.com/matrix-construct/ruma?rev=5682b88cf1bcaf0f47805d614b476b242ef075d4#5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"thiserror 2.0.16",
|
"thiserror 2.0.16",
|
||||||
@@ -3622,7 +3622,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-macros"
|
name = "ruma-macros"
|
||||||
version = "0.15.2"
|
version = "0.15.2"
|
||||||
source = "git+https://github.com/matrix-construct/ruma?rev=93f28d777073e60687e8013e59d8d16b5adbdf9a#93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
source = "git+https://github.com/matrix-construct/ruma?rev=5682b88cf1bcaf0f47805d614b476b242ef075d4#5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
@@ -3637,7 +3637,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-push-gateway-api"
|
name = "ruma-push-gateway-api"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
source = "git+https://github.com/matrix-construct/ruma?rev=93f28d777073e60687e8013e59d8d16b5adbdf9a#93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
source = "git+https://github.com/matrix-construct/ruma?rev=5682b88cf1bcaf0f47805d614b476b242ef075d4#5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -3649,7 +3649,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-signatures"
|
name = "ruma-signatures"
|
||||||
version = "0.17.1"
|
version = "0.17.1"
|
||||||
source = "git+https://github.com/matrix-construct/ruma?rev=93f28d777073e60687e8013e59d8d16b5adbdf9a#93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
source = "git+https://github.com/matrix-construct/ruma?rev=5682b88cf1bcaf0f47805d614b476b242ef075d4#5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ default-features = false
|
|||||||
|
|
||||||
[workspace.dependencies.ruma]
|
[workspace.dependencies.ruma]
|
||||||
git = "https://github.com/matrix-construct/ruma"
|
git = "https://github.com/matrix-construct/ruma"
|
||||||
rev = "93f28d777073e60687e8013e59d8d16b5adbdf9a"
|
rev = "5682b88cf1bcaf0f47805d614b476b242ef075d4"
|
||||||
features = [
|
features = [
|
||||||
"__compat",
|
"__compat",
|
||||||
"appservice-api-c",
|
"appservice-api-c",
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ use ruma::api::client::{
|
|||||||
request_3pid_management_token_via_email, request_3pid_management_token_via_msisdn,
|
request_3pid_management_token_via_email, request_3pid_management_token_via_msisdn,
|
||||||
whoami,
|
whoami,
|
||||||
},
|
},
|
||||||
uiaa::{AuthFlow, AuthType, UiaaInfo},
|
uiaa::{AuthData, AuthFlow, AuthType, Jwt, UiaaInfo},
|
||||||
};
|
};
|
||||||
use tuwunel_core::{Err, Error, Result, err, info, utils, utils::ReadyExt};
|
use tuwunel_core::{Err, Error, Result, err, info, utils, utils::ReadyExt};
|
||||||
|
|
||||||
use super::SESSION_ID_LENGTH;
|
use super::{SESSION_ID_LENGTH, session::jwt::validate_user};
|
||||||
use crate::Ruma;
|
use crate::Ruma;
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/account/password`
|
/// # `POST /_matrix/client/r0/account/password`
|
||||||
@@ -140,20 +140,29 @@ pub(crate) async fn deactivate_route(
|
|||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
body: Ruma<deactivate::v3::Request>,
|
body: Ruma<deactivate::v3::Request>,
|
||||||
) -> Result<deactivate::v3::Response> {
|
) -> Result<deactivate::v3::Response> {
|
||||||
// Authentication for this endpoint was made optional, but we need
|
let pass_flow = AuthFlow { stages: vec![AuthType::Password] };
|
||||||
// authentication currently
|
let jwt_flow = AuthFlow { stages: vec![AuthType::Jwt] };
|
||||||
let sender_user = body
|
|
||||||
.sender_user
|
|
||||||
.as_ref()
|
|
||||||
.ok_or_else(|| err!(Request(MissingToken("Missing access token."))))?;
|
|
||||||
|
|
||||||
let mut uiaainfo = UiaaInfo {
|
let mut uiaainfo = UiaaInfo {
|
||||||
flows: vec![AuthFlow { stages: vec![AuthType::Password] }],
|
flows: [pass_flow, jwt_flow].into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
match &body.auth {
|
let sender_user = match &body.auth {
|
||||||
|
| Some(AuthData::Jwt(Jwt { token, .. })) => {
|
||||||
|
let sender_user = validate_user(&services, token)?;
|
||||||
|
if !services.users.exists(&sender_user).await {
|
||||||
|
return Err!(Request(NotFound("User {sender_user} is not registered.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success!
|
||||||
|
sender_user
|
||||||
|
},
|
||||||
| Some(auth) => {
|
| Some(auth) => {
|
||||||
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_deref()
|
||||||
|
.ok_or_else(|| err!(Request(MissingToken("Missing access token."))))?;
|
||||||
|
|
||||||
let (worked, uiaainfo) = services
|
let (worked, uiaainfo) = services
|
||||||
.uiaa
|
.uiaa
|
||||||
.try_auth(sender_user, body.sender_device(), auth, &uiaainfo)
|
.try_auth(sender_user, body.sender_device(), auth, &uiaainfo)
|
||||||
@@ -162,10 +171,17 @@ pub(crate) async fn deactivate_route(
|
|||||||
if !worked {
|
if !worked {
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err(Error::Uiaa(uiaainfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success!
|
// Success!
|
||||||
|
sender_user.to_owned()
|
||||||
},
|
},
|
||||||
| _ => match body.json_body {
|
| _ => match body.json_body {
|
||||||
| Some(ref json) => {
|
| Some(ref json) => {
|
||||||
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.ok_or_else(|| err!(Request(MissingToken("Missing access token."))))?;
|
||||||
|
|
||||||
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||||
services
|
services
|
||||||
.uiaa
|
.uiaa
|
||||||
@@ -177,11 +193,11 @@ pub(crate) async fn deactivate_route(
|
|||||||
return Err!(Request(NotJson("JSON body is not valid")));
|
return Err!(Request(NotJson("JSON body is not valid")));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
services
|
services
|
||||||
.deactivate
|
.deactivate
|
||||||
.full_deactivate(sender_user)
|
.full_deactivate(&sender_user)
|
||||||
.boxed()
|
.boxed()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -22,20 +22,9 @@ pub(super) async fn handle_login(
|
|||||||
_body: &Ruma<Request>,
|
_body: &Ruma<Request>,
|
||||||
info: &Token,
|
info: &Token,
|
||||||
) -> Result<OwnedUserId> {
|
) -> Result<OwnedUserId> {
|
||||||
let config = &services.config.jwt;
|
let user_id = validate_user(services, &info.token)?;
|
||||||
|
|
||||||
if !config.enable {
|
|
||||||
return Err!(Request(Unknown("JWT login is not enabled.")));
|
|
||||||
}
|
|
||||||
|
|
||||||
let claim = validate(config, &info.token)?;
|
|
||||||
let local = claim.sub.to_lowercase();
|
|
||||||
let server = &services.server.name;
|
|
||||||
let user_id = UserId::parse_with_server_name(local, server).map_err(|e| {
|
|
||||||
err!(Request(InvalidUsername("JWT subject is not a valid user MXID: {e}")))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if !services.users.exists(&user_id).await {
|
if !services.users.exists(&user_id).await {
|
||||||
|
let config = &services.config.jwt;
|
||||||
if !config.register_user {
|
if !config.register_user {
|
||||||
return Err!(Request(NotFound("User {user_id} is not registered on this server.")));
|
return Err!(Request(NotFound("User {user_id} is not registered on this server.")));
|
||||||
}
|
}
|
||||||
@@ -49,6 +38,22 @@ pub(super) async fn handle_login(
|
|||||||
Ok(user_id)
|
Ok(user_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn validate_user(services: &Services, token: &str) -> Result<OwnedUserId> {
|
||||||
|
let config = &services.config.jwt;
|
||||||
|
if !config.enable {
|
||||||
|
return Err!(Request(Unauthorized("JWT login is not enabled.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
let claim = validate(config, token)?;
|
||||||
|
let local = claim.sub.to_lowercase();
|
||||||
|
let server = &services.server.name;
|
||||||
|
let user_id = UserId::parse_with_server_name(local, server).map_err(|e| {
|
||||||
|
err!(Request(InvalidUsername("JWT subject is not a valid user MXID: {e}")))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(user_id)
|
||||||
|
}
|
||||||
|
|
||||||
fn validate(config: &JwtConfig, token: &str) -> Result<Claim> {
|
fn validate(config: &JwtConfig, token: &str) -> Result<Claim> {
|
||||||
let verifier = init_verifier(config)?;
|
let verifier = init_verifier(config)?;
|
||||||
let validator = init_validator(config)?;
|
let validator = init_validator(config)?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
mod appservice;
|
mod appservice;
|
||||||
mod jwt;
|
pub(crate) mod jwt;
|
||||||
mod ldap;
|
mod ldap;
|
||||||
mod logout;
|
mod logout;
|
||||||
mod password;
|
mod password;
|
||||||
|
|||||||
Reference in New Issue
Block a user