tuwunel_api_client/session/
refresh.rs1use axum::extract::State;
2use ruma::api::client::session::refresh_token::v3::{Request, Response};
3use tuwunel_core::{Err, Result, debug_info, err};
4
5use crate::{ClientIp, Ruma};
6
7#[tracing::instrument(skip_all, fields(%client), name = "refresh_token")]
13pub(crate) async fn refresh_token_route(
14 State(services): State<crate::State>,
15 ClientIp(client): ClientIp,
16 body: Ruma<Request>,
17) -> Result<Response> {
18 let refresh_token_claim = body.body.refresh_token;
19
20 if !refresh_token_claim.starts_with("refresh_") {
21 return Err!(Request(Forbidden("Refresh token is malformed.")));
22 }
23
24 let token = services
25 .users
26 .classify_refresh_token(&refresh_token_claim)
27 .await;
28
29 let (user_id, device_id) = token
30 .owner()
31 .ok_or_else(|| err!(Request(Forbidden("Refresh token is unrecognized."))))?;
32
33 let (access_token, expires_in_ms) = services.users.generate_access_token(true);
34 let refresh_token = services
35 .users
36 .rotate_refresh_token(
37 &token,
38 &refresh_token_claim,
39 (&access_token, expires_in_ms),
40 services.users.locked_check(user_id),
41 )
42 .await?;
43
44 debug_info!(?user_id, ?device_id, ?expires_in_ms, "refreshed their access_token");
45
46 Ok(Response {
47 access_token,
48 refresh_token: Some(refresh_token),
49 expires_in_ms,
50 })
51}