Skip to main content

tuwunel_api/client/session/
token.rs

1use std::time::Duration;
2
3use axum::extract::State;
4use ruma::{
5	OwnedUserId,
6	api::client::session::{
7		get_login_token,
8		login::v3::{Request, Token},
9	},
10};
11use tuwunel_core::{Err, Result, utils::random_string};
12use tuwunel_service::Services;
13
14use super::TOKEN_LENGTH;
15use crate::{ClientIp, Ruma, router::auth_uiaa};
16
17pub(super) async fn handle_login(
18	services: &Services,
19	_body: &Ruma<Request>,
20	info: &Token,
21) -> Result<OwnedUserId> {
22	let Token { token } = info;
23
24	if !services.config.login_via_token {
25		return Err!(Request(Unknown("Token login is not enabled.")));
26	}
27
28	services.users.find_from_login_token(token).await
29}
30
31/// # `POST /_matrix/client/v1/login/get_token`
32///
33/// Allows a logged-in user to get a short-lived token which can be used
34/// to log in with the m.login.token flow.
35///
36/// <https://spec.matrix.org/v1.13/client-server-api/#post_matrixclientv1loginget_token>
37#[tracing::instrument(skip_all, fields(%client), name = "login_token")]
38pub(crate) async fn login_token_route(
39	State(services): State<crate::State>,
40	ClientIp(client): ClientIp,
41	body: Ruma<get_login_token::v1::Request>,
42) -> Result<get_login_token::v1::Response> {
43	if !services.config.login_via_existing_session || !services.config.login_via_token {
44		return Err!(Request(Forbidden("Login via an existing session is not enabled")));
45	}
46
47	let sender_user = auth_uiaa(&services, &body).await?;
48	if !services.users.is_active_local(&sender_user).await {
49		return Err!(Request(UserDeactivated("This user has been deactivated.")));
50	}
51
52	let login_token = random_string(TOKEN_LENGTH);
53	let expires_in = services
54		.users
55		.create_login_token(&sender_user, &login_token);
56
57	Ok(get_login_token::v1::Response {
58		expires_in: Duration::from_millis(expires_in),
59		login_token,
60	})
61}