1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-20 12:02:22 +03:00

Better data-model for compat sessions & devices

This commit is contained in:
Quentin Gliech
2022-05-18 14:03:14 +02:00
parent 33204b7cf8
commit c4fa87e457
9 changed files with 212 additions and 163 deletions

View File

@@ -15,11 +15,12 @@
use axum::{response::IntoResponse, Extension, Json};
use hyper::StatusCode;
use mas_config::MatrixConfig;
use mas_data_model::TokenType;
use mas_data_model::{Device, TokenType};
use mas_storage::compat::compat_login;
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use rand::thread_rng;
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use thiserror::Error;
use super::MatrixError;
@@ -69,13 +70,19 @@ pub enum Identifier {
#[derive(Debug, Serialize)]
pub struct ResponseBody {
access_token: String,
device_id: String,
device_id: Device,
user_id: String,
}
#[derive(Debug, Error)]
pub enum RouteError {
#[error(transparent)]
Internal(Box<dyn std::error::Error + Send + Sync + 'static>),
#[error("unsupported login method")]
Unsupported,
#[error("login failed")]
LoginFailed,
}
@@ -108,6 +115,7 @@ impl IntoResponse for RouteError {
}
}
#[tracing::instrument(skip_all, err)]
pub(crate) async fn post(
Extension(pool): Extension<PgPool>,
Extension(config): Extension<MatrixConfig>,
@@ -124,26 +132,22 @@ pub(crate) async fn post(
}
};
let (token, device_id) = {
let (token, device) = {
let mut rng = thread_rng();
let token = TokenType::CompatAccessToken.generate(&mut rng);
let device_id: String = rng
.sample_iter(&Alphanumeric)
.take(10)
.map(char::from)
.collect();
(token, device_id)
let device = Device::generate(&mut rng);
(token, device)
};
let (token, user) = compat_login(&mut conn, &username, &password, device_id, token)
let (token, session) = compat_login(&mut conn, &username, &password, device, token)
.await
.map_err(|_| RouteError::LoginFailed)?;
let user_id = format!("@{}:{}", user.username, config.homeserver);
let user_id = format!("@{}:{}", session.user.username, config.homeserver);
Ok(Json(ResponseBody {
access_token: token.token,
device_id: token.device_id,
device_id: session.device,
user_id,
}))
}

View File

@@ -21,7 +21,7 @@ use axum_extra::extract::PrivateCookieJar;
use hyper::StatusCode;
use mas_axum_utils::SessionInfoExt;
use mas_config::Encrypter;
use mas_data_model::{AuthorizationCode, Pkce};
use mas_data_model::{AuthorizationCode, Device, Pkce};
use mas_iana::oauth::OAuthAuthorizationEndpointResponseType;
use mas_router::{PostAuthAction, Route};
use mas_storage::oauth2::{
@@ -38,7 +38,6 @@ use oauth2_types::{
pkce,
prelude::*,
requests::{AuthorizationRequest, GrantType, Prompt, ResponseMode},
scope::ScopeToken,
};
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use serde::Deserialize;
@@ -252,15 +251,8 @@ pub(crate) async fn get(
};
// Generate the device ID
// TODO: this should probably be done somewhere else?
let device_id: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(10)
.map(char::from)
.collect();
let device_scope: ScopeToken = format!("urn:matrix:device:{}", device_id)
.parse()
.context("could not parse generated device scope")?;
let device = Device::generate(&mut thread_rng());
let device_scope = device.to_scope_token();
let scope = {
let mut s = params.auth.scope.clone();

View File

@@ -26,10 +26,7 @@ use mas_storage::{
refresh_token::{lookup_active_refresh_token, RefreshTokenLookupError},
},
};
use oauth2_types::{
requests::{IntrospectionRequest, IntrospectionResponse},
scope::ScopeToken,
};
use oauth2_types::requests::{IntrospectionRequest, IntrospectionResponse};
use sqlx::PgPool;
use thiserror::Error;
@@ -217,28 +214,29 @@ pub(crate) async fn post(
}
}
TokenType::CompatAccessToken => {
let (token, user) = lookup_active_compat_access_token(&mut conn, token).await?;
let (token, session) = lookup_active_compat_access_token(&mut conn, token).await?;
let device_scope: ScopeToken = format!("urn:matrix:device:{}", token.device_id)
.parse()
.unwrap();
let device_scope = session.device.to_scope_token();
let scope = [device_scope].into_iter().collect();
IntrospectionResponse {
active: true,
scope: Some(scope),
client_id: Some("legacy".into()),
username: Some(user.username),
username: Some(session.user.username),
token_type: Some(OAuthTokenTypeHint::AccessToken),
exp: None,
exp: token.exp(),
iat: Some(token.created_at),
nbf: Some(token.created_at),
sub: Some(user.sub),
sub: Some(session.user.sub),
aud: None,
iss: None,
jti: None,
}
}
TokenType::CompatRefreshToken => {
todo!()
}
};
Ok(Json(reply))