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

Add the user_id directly on oauth2_sessions and make the scope a text list

This commit is contained in:
Quentin Gliech
2023-08-29 12:32:22 +02:00
parent feb59344f3
commit 438a10332a
21 changed files with 186 additions and 127 deletions

View File

@@ -18,13 +18,13 @@ use mas_axum_utils::{
client_authorization::{ClientAuthorization, CredentialsVerificationError},
http_client_factory::HttpClientFactory,
};
use mas_data_model::{TokenFormatError, TokenType};
use mas_data_model::{TokenFormatError, TokenType, User};
use mas_iana::oauth::{OAuthClientAuthenticationMethod, OAuthTokenTypeHint};
use mas_keystore::Encrypter;
use mas_storage::{
compat::{CompatAccessTokenRepository, CompatRefreshTokenRepository, CompatSessionRepository},
oauth2::{OAuth2AccessTokenRepository, OAuth2RefreshTokenRepository, OAuth2SessionRepository},
user::{BrowserSessionRepository, UserRepository},
user::UserRepository,
BoxClock, BoxRepository, Clock,
};
use oauth2_types::{
@@ -184,11 +184,11 @@ pub(crate) async fn post(
// XXX: is that the right error to bubble up?
.ok_or(RouteError::UnknownToken)?;
let browser_session = repo
.browser_session()
.lookup(session.user_session_id)
let user = repo
.user()
.lookup(session.user_id)
.await?
.filter(|b| b.user.is_valid())
.filter(User::is_valid)
// XXX: is that the right error to bubble up?
.ok_or(RouteError::UnknownToken)?;
@@ -196,12 +196,12 @@ pub(crate) async fn post(
active: true,
scope: Some(session.scope),
client_id: Some(session.client_id.to_string()),
username: Some(browser_session.user.username),
username: Some(user.username),
token_type: Some(OAuthTokenTypeHint::AccessToken),
exp: Some(token.expires_at),
iat: Some(token.created_at),
nbf: Some(token.created_at),
sub: Some(browser_session.user.sub),
sub: Some(user.sub),
aud: None,
iss: None,
jti: Some(token.jti()),
@@ -224,11 +224,11 @@ pub(crate) async fn post(
// XXX: is that the right error to bubble up?
.ok_or(RouteError::UnknownToken)?;
let browser_session = repo
.browser_session()
.lookup(session.user_session_id)
let user = repo
.user()
.lookup(session.user_id)
.await?
.filter(|b| b.user.is_valid())
.filter(User::is_valid)
// XXX: is that the right error to bubble up?
.ok_or(RouteError::UnknownToken)?;
@@ -236,12 +236,12 @@ pub(crate) async fn post(
active: true,
scope: Some(session.scope),
client_id: Some(session.client_id.to_string()),
username: Some(browser_session.user.username),
username: Some(user.username),
token_type: Some(OAuthTokenTypeHint::RefreshToken),
exp: None,
iat: Some(token.created_at),
nbf: Some(token.created_at),
sub: Some(browser_session.user.sub),
sub: Some(user.sub),
aud: None,
iss: None,
jti: Some(token.jti()),

View File

@@ -23,7 +23,6 @@ use mas_iana::oauth::OAuthTokenTypeHint;
use mas_keystore::Encrypter;
use mas_storage::{
job::{DeleteDeviceJob, JobRepositoryExt},
user::BrowserSessionRepository,
BoxClock, BoxRepository, RepositoryAccess,
};
use oauth2_types::{
@@ -200,10 +199,10 @@ pub(crate) async fn post(
return Err(RouteError::UnauthorizedClient);
}
// Fetch the user session
let user_session = repo
.browser_session()
.lookup(session.user_session_id)
// Fetch the user
let user = repo
.user()
.lookup(session.user_id)
.await?
.ok_or(RouteError::UnknownToken)?;
@@ -217,7 +216,7 @@ pub(crate) async fn post(
if let Some(device) = Device::from_scope_token(scope) {
// Schedule a job to delete the device.
repo.job()
.schedule_job(DeleteDeviceJob::new(&user_session.user, &device))
.schedule_job(DeleteDeviceJob::new(&user, &device))
.await?;
}
}

View File

@@ -296,9 +296,14 @@ async fn authorization_code_grant(
}
};
let Some(user_session_id) = session.user_session_id else {
tracing::warn!("No user session associated with this OAuth2 session");
return Err(RouteError::InvalidGrant);
};
let browser_session = repo
.browser_session()
.lookup(session.user_session_id)
.lookup(user_session_id)
.await?
.ok_or(RouteError::NoSuchBrowserSession)?;

View File

@@ -29,9 +29,7 @@ use mas_jose::{
use mas_keystore::Keystore;
use mas_router::UrlBuilder;
use mas_storage::{
oauth2::OAuth2ClientRepository,
user::{BrowserSessionRepository, UserEmailRepository},
BoxClock, BoxRepository, BoxRng,
oauth2::OAuth2ClientRepository, user::UserEmailRepository, BoxClock, BoxRepository, BoxRng,
};
use oauth2_types::scope;
use serde::Serialize;
@@ -73,8 +71,8 @@ pub enum RouteError {
#[error("failed to load client")]
NoSuchClient,
#[error("failed to load browser session")]
NoSuchBrowserSession,
#[error("failed to load user")]
NoSuchUser,
}
impl_from_error_for_route!(mas_storage::RepositoryError);
@@ -85,10 +83,7 @@ impl IntoResponse for RouteError {
fn into_response(self) -> axum::response::Response {
sentry::capture_error(&self);
match self {
Self::Internal(_)
| Self::InvalidSigningKey
| Self::NoSuchClient
| Self::NoSuchBrowserSession => {
Self::Internal(_) | Self::InvalidSigningKey | Self::NoSuchClient | Self::NoSuchUser => {
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response()
}
Self::AuthorizationVerificationError(_e) => StatusCode::UNAUTHORIZED.into_response(),
@@ -107,13 +102,11 @@ pub async fn get(
) -> Result<Response, RouteError> {
let session = user_authorization.protected(&mut repo, &clock).await?;
let browser_session = repo
.browser_session()
.lookup(session.user_session_id)
let user = repo
.user()
.lookup(session.user_id)
.await?
.ok_or(RouteError::NoSuchBrowserSession)?;
let user = browser_session.user;
.ok_or(RouteError::NoSuchUser)?;
let user_email = if session.scope.contains(&scope::EMAIL) {
repo.user_email().get_primary(&user).await?