client-api: Add support for refresh tokens
According to MSC2918
This commit is contained in:
parent
1605fcc027
commit
90cef5a50b
@ -5,6 +5,10 @@ Breaking changes:
|
||||
* Remove `PartialEq` implementations for a number of types
|
||||
* If the lack of such an `impl` causes problems, please open a GitHub issue
|
||||
|
||||
Improvements:
|
||||
|
||||
* Add unstable support for refresh tokens (MSC2918)
|
||||
|
||||
# 0.14.1
|
||||
|
||||
Improvements:
|
||||
|
@ -23,6 +23,7 @@ unstable-msc2448 = []
|
||||
unstable-msc2654 = []
|
||||
unstable-msc2676 = []
|
||||
unstable-msc2677 = []
|
||||
unstable-msc2918 = []
|
||||
unstable-msc3440 = []
|
||||
unstable-msc3488 = []
|
||||
client = []
|
||||
|
@ -7,6 +7,9 @@ pub mod v3 {
|
||||
//!
|
||||
//! [spec]: https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3register
|
||||
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_common::{api::ruma_api, DeviceId, OwnedDeviceId, OwnedUserId};
|
||||
|
||||
use super::{LoginType, RegistrationKind};
|
||||
@ -81,12 +84,24 @@ pub mod v3 {
|
||||
/// [admin]: https://spec.matrix.org/v1.2/application-service-api/#server-admin-style-permissions
|
||||
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
|
||||
pub login_type: Option<&'a LoginType>,
|
||||
|
||||
/// If set to `true`, the client supports refresh tokens.
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "ruma_common::serde::is_default",
|
||||
rename = "org.matrix.msc2918.refresh_token",
|
||||
alias = "refresh_token",
|
||||
)]
|
||||
pub refresh_token: bool,
|
||||
}
|
||||
|
||||
response: {
|
||||
/// An access token for the account.
|
||||
///
|
||||
/// This access token can then be used to authorize other requests.
|
||||
///
|
||||
/// Required if the request's `inhibit_login` was set to `false`.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub access_token: Option<String>,
|
||||
|
||||
@ -96,7 +111,37 @@ pub mod v3 {
|
||||
/// ID of the registered device.
|
||||
///
|
||||
/// Will be the same as the corresponding parameter in the request, if one was specified.
|
||||
///
|
||||
/// Required if the request's `inhibit_login` was set to `false`.
|
||||
pub device_id: Option<OwnedDeviceId>,
|
||||
|
||||
/// A refresh token for the account.
|
||||
///
|
||||
/// This token can be used to obtain a new access token when it expires by calling the
|
||||
/// `/refresh` endpoint.
|
||||
///
|
||||
/// Omitted if the request's `inhibit_login` was set to `true`.
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub refresh_token: Option<String>,
|
||||
|
||||
/// The lifetime of the access token, in milliseconds.
|
||||
///
|
||||
/// Once the access token has expired, a new access token can be obtained by using the
|
||||
/// provided refresh token. If no refresh token is provided, the client will need to
|
||||
/// re-login to obtain a new access token.
|
||||
///
|
||||
/// If this is `None`, the client can assume that the access token will not expire.
|
||||
///
|
||||
/// Omitted if the request's `inhibit_login` was set to `true`.
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
#[serde(
|
||||
with = "ruma_common::serde::duration::opt_ms",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
rename = "expires_in_ms",
|
||||
)]
|
||||
pub expires_in: Option<Duration>,
|
||||
}
|
||||
|
||||
error: UiaaResponse
|
||||
@ -112,7 +157,15 @@ pub mod v3 {
|
||||
impl Response {
|
||||
/// Creates a new `Response` with the given user ID.
|
||||
pub fn new(user_id: OwnedUserId) -> Self {
|
||||
Self { access_token: None, user_id, device_id: None }
|
||||
Self {
|
||||
access_token: None,
|
||||
user_id,
|
||||
device_id: None,
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
refresh_token: None,
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
expires_in: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,5 +5,7 @@ pub mod login;
|
||||
pub mod login_fallback;
|
||||
pub mod logout;
|
||||
pub mod logout_all;
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
pub mod refresh_token;
|
||||
pub mod sso_login;
|
||||
pub mod sso_login_with_provider;
|
||||
|
@ -5,6 +5,9 @@ pub mod v3 {
|
||||
//!
|
||||
//! [spec]: https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3login
|
||||
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_common::{
|
||||
api::ruma_api,
|
||||
serde::{Incoming, JsonObject},
|
||||
@ -44,6 +47,16 @@ pub mod v3 {
|
||||
/// Ignored if `device_id` corresponds to a known device.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub initial_device_display_name: Option<&'a str>,
|
||||
|
||||
/// If set to `true`, the client supports refresh tokens.
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "ruma_common::serde::is_default",
|
||||
rename = "org.matrix.msc2918.refresh_token",
|
||||
alias = "refresh_token",
|
||||
)]
|
||||
pub refresh_token: bool,
|
||||
}
|
||||
|
||||
response: {
|
||||
@ -71,6 +84,30 @@ pub mod v3 {
|
||||
/// If present, clients SHOULD use the provided object to reconfigure themselves.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub well_known: Option<DiscoveryInfo>,
|
||||
|
||||
/// A refresh token for the account.
|
||||
///
|
||||
/// This token can be used to obtain a new access token when it expires by calling the
|
||||
/// `/refresh` endpoint.
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub refresh_token: Option<String>,
|
||||
|
||||
/// The lifetime of the access token, in milliseconds.
|
||||
///
|
||||
/// Once the access token has expired, a new access token can be obtained by using the
|
||||
/// provided refresh token. If no refresh token is provided, the client will need to
|
||||
/// re-login to obtain a new access token.
|
||||
///
|
||||
/// If this is `None`, the client can assume that the access token will not expire.
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
#[serde(
|
||||
with = "ruma_common::serde::duration::opt_ms",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
rename = "expires_in_ms",
|
||||
)]
|
||||
pub expires_in: Option<Duration>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
@ -79,14 +116,30 @@ pub mod v3 {
|
||||
impl<'a> Request<'a> {
|
||||
/// Creates a new `Request` with the given login info.
|
||||
pub fn new(login_info: LoginInfo<'a>) -> Self {
|
||||
Self { login_info, device_id: None, initial_device_display_name: None }
|
||||
Self {
|
||||
login_info,
|
||||
device_id: None,
|
||||
initial_device_display_name: None,
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
refresh_token: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Response {
|
||||
/// Creates a new `Response` with the given user ID, access token and device ID.
|
||||
pub fn new(user_id: OwnedUserId, access_token: String, device_id: OwnedDeviceId) -> Self {
|
||||
Self { user_id, access_token, home_server: None, device_id, well_known: None }
|
||||
Self {
|
||||
user_id,
|
||||
access_token,
|
||||
home_server: None,
|
||||
device_id,
|
||||
well_known: None,
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
refresh_token: None,
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
expires_in: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,6 +427,8 @@ pub mod v3 {
|
||||
login_info: LoginInfo::Token(Token { token: "0xdeadbeef" }),
|
||||
device_id: None,
|
||||
initial_device_display_name: Some("test"),
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
refresh_token: false,
|
||||
}
|
||||
.try_into_http_request(
|
||||
"https://homeserver.tld",
|
||||
@ -402,6 +457,8 @@ pub mod v3 {
|
||||
}),
|
||||
device_id: None,
|
||||
initial_device_display_name: Some("test"),
|
||||
#[cfg(feature = "unstable-msc2918")]
|
||||
refresh_token: false,
|
||||
}
|
||||
.try_into_http_request(
|
||||
"https://homeserver.tld",
|
||||
|
84
crates/ruma-client-api/src/session/refresh_token.rs
Normal file
84
crates/ruma-client-api/src/session/refresh_token.rs
Normal file
@ -0,0 +1,84 @@
|
||||
//! `POST /_matrix/client/*/refresh`
|
||||
//!
|
||||
//! Refresh an access token.
|
||||
//!
|
||||
//! Clients should use the returned access token when making subsequent API
|
||||
//! calls, and store the returned refresh token (if given) in order to refresh
|
||||
//! the new access token when necessary.
|
||||
//!
|
||||
//! After an access token has been refreshed, a server can choose to invalidate
|
||||
//! the old access token immediately, or can choose not to, for example if the
|
||||
//! access token would expire soon anyways. Clients should not make any
|
||||
//! assumptions about the old access token still being valid, and should use the
|
||||
//! newly provided access token instead.
|
||||
//!
|
||||
//! The old refresh token remains valid until the new access token or refresh
|
||||
//! token is used, at which point the old refresh token is revoked.
|
||||
//!
|
||||
//! Note that this endpoint does not require authentication via an access token.
|
||||
//! Authentication is provided via the refresh token.
|
||||
//!
|
||||
//! Application Service identity assertion is disabled for this endpoint.
|
||||
|
||||
pub mod unstable {
|
||||
//! `/unstable/` (MSC2918)
|
||||
//!
|
||||
//! [MSC2918]: https://github.com/matrix-org/matrix-spec-proposals/pull/2918
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_common::api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata: {
|
||||
description: "Refresh an access token.",
|
||||
method: POST,
|
||||
name: "refresh",
|
||||
unstable_path: "/_matrix/client/unstable/org.matrix.msc2918/refresh",
|
||||
rate_limited: true,
|
||||
authentication: None,
|
||||
}
|
||||
|
||||
request: {
|
||||
/// The refresh token.
|
||||
pub refresh_token: String,
|
||||
}
|
||||
|
||||
response: {
|
||||
/// The new access token to use.
|
||||
pub access_token: String,
|
||||
|
||||
/// The new refresh token to use when the access token needs to be refreshed again.
|
||||
///
|
||||
/// If this is `None`, the old refresh token can be re-used.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub refresh_token: Option<String>,
|
||||
|
||||
/// The lifetime of the access token, in milliseconds.
|
||||
///
|
||||
/// If this is `None`, the client can assume that the access token will not expire.
|
||||
#[serde(
|
||||
with = "ruma_common::serde::duration::opt_ms",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub expires_in_ms: Option<Duration>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
impl Request {
|
||||
/// Creates a new `Request` with the given refresh token.
|
||||
pub fn new(refresh_token: String) -> Self {
|
||||
Self { refresh_token }
|
||||
}
|
||||
}
|
||||
|
||||
impl Response {
|
||||
/// Creates a new `Response` with the given access token.
|
||||
pub fn new(access_token: String) -> Self {
|
||||
Self { access_token, refresh_token: None, expires_in_ms: None }
|
||||
}
|
||||
}
|
||||
}
|
@ -135,6 +135,7 @@ unstable-msc2677 = [
|
||||
]
|
||||
unstable-msc2746 = ["ruma-common/unstable-msc2746"]
|
||||
unstable-msc2870 = ["ruma-signatures?/unstable-msc2870"]
|
||||
unstable-msc2918 = ["ruma-client-api?/unstable-msc2918"]
|
||||
unstable-msc3245 = ["ruma-common/unstable-msc3245"]
|
||||
unstable-msc3246 = ["ruma-common/unstable-msc3246"]
|
||||
unstable-msc3381 = ["ruma-common/unstable-msc3381"]
|
||||
@ -165,6 +166,7 @@ __ci = [
|
||||
"unstable-msc2677",
|
||||
"unstable-msc2746",
|
||||
"unstable-msc2870",
|
||||
"unstable-msc2918",
|
||||
"unstable-msc3245",
|
||||
"unstable-msc3246",
|
||||
"unstable-msc3381",
|
||||
|
Loading…
x
Reference in New Issue
Block a user