1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Make the compat login use the new password manager

This commit is contained in:
Quentin Gliech
2022-12-14 15:49:26 +01:00
parent 533cabe005
commit a475a9a164
6 changed files with 106 additions and 140 deletions

View File

@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use anyhow::Context;
use argon2::{Argon2, PasswordHash};
use chrono::{DateTime, Duration, Utc};
use mas_data_model::{
CompatAccessToken, CompatRefreshToken, CompatSession, CompatSsoLogin, CompatSsoLoginState,
@ -21,7 +19,6 @@ use mas_data_model::{
};
use rand::Rng;
use sqlx::{Acquire, PgExecutor, Postgres, QueryBuilder};
use tokio::task;
use tracing::{info_span, Instrument};
use ulid::Ulid;
use url::Url;
@ -29,7 +26,6 @@ use uuid::Uuid;
use crate::{
pagination::{process_page, QueryBuilderExt},
user::lookup_user_by_username,
Clock, DatabaseError, DatabaseInconsistencyError, LookupResultExt,
};
@ -284,91 +280,6 @@ pub async fn lookup_active_compat_refresh_token(
Ok(Some((refresh_token, access_token, session)))
}
#[tracing::instrument(
skip_all,
fields(
user.username = username,
user.id,
compat_session.id,
compat_session.device.id = device.as_str(),
),
err(Debug),
)]
pub async fn compat_login(
conn: impl Acquire<'_, Database = Postgres> + Send,
mut rng: impl Rng + Send,
clock: &Clock,
username: &str,
password: &str,
device: Device,
) -> Result<CompatSession, anyhow::Error> {
// TODO: that should be split and not verify the password hash here
let mut txn = conn.begin().await.context("could not start transaction")?;
// First, lookup the user
let user = lookup_user_by_username(&mut txn, username)
.await?
.context("Could not lookup username")?;
tracing::Span::current().record("user.id", tracing::field::display(user.id));
// Now, fetch the hashed password from the user associated with that session
let hashed_password: String = sqlx::query_scalar!(
r#"
SELECT up.hashed_password
FROM user_passwords up
WHERE up.user_id = $1
ORDER BY up.created_at DESC
LIMIT 1
"#,
Uuid::from(user.id),
)
.fetch_one(&mut txn)
.instrument(tracing::info_span!("Lookup hashed password"))
.await?;
// TODO: pass verifiers list as parameter
// Verify the password in a blocking thread to avoid blocking the async executor
let password = password.to_owned();
task::spawn_blocking(move || {
let context = Argon2::default();
let hasher = PasswordHash::new(&hashed_password)?;
hasher.verify_password(&[&context], &password)
})
.instrument(tracing::info_span!("Verify hashed password"))
.await??;
let created_at = clock.now();
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
tracing::Span::current().record("compat_session.id", tracing::field::display(id));
sqlx::query!(
r#"
INSERT INTO compat_sessions
(compat_session_id, user_id, device_id, created_at)
VALUES ($1, $2, $3, $4)
"#,
Uuid::from(id),
Uuid::from(user.id),
device.as_str(),
created_at,
)
.execute(&mut txn)
.instrument(tracing::info_span!("Insert compat session"))
.await
.context("could not insert compat session")?;
let session = CompatSession {
id,
user,
device,
created_at,
finished_at: None,
};
txn.commit().await.context("could not commit transaction")?;
Ok(session)
}
#[tracing::instrument(
skip_all,
fields(
@ -895,6 +806,48 @@ pub async fn get_compat_sso_login_by_token(
Ok(Some(res.try_into()?))
}
#[tracing::instrument(
skip_all,
fields(
%user.id,
compat_session.id,
compat_session.device.id = device.as_str(),
),
err,
)]
pub async fn start_compat_session(
executor: impl PgExecutor<'_>,
mut rng: impl Rng + Send,
clock: &Clock,
user: User,
device: Device,
) -> Result<CompatSession, DatabaseError> {
let created_at = clock.now();
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
tracing::Span::current().record("compat_session.id", tracing::field::display(id));
sqlx::query!(
r#"
INSERT INTO compat_sessions (compat_session_id, user_id, device_id, created_at)
VALUES ($1, $2, $3, $4)
"#,
Uuid::from(id),
Uuid::from(user.id),
device.as_str(),
created_at,
)
.execute(executor)
.await?;
Ok(CompatSession {
id,
user,
device,
created_at,
finished_at: None,
})
}
#[tracing::instrument(
skip_all,
fields(
@ -920,31 +873,7 @@ pub async fn fullfill_compat_sso_login(
let mut txn = conn.begin().await?;
let created_at = clock.now();
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
tracing::Span::current().record("compat_session.id", tracing::field::display(id));
sqlx::query!(
r#"
INSERT INTO compat_sessions (compat_session_id, user_id, device_id, created_at)
VALUES ($1, $2, $3, $4)
"#,
Uuid::from(id),
Uuid::from(user.id),
device.as_str(),
created_at,
)
.execute(&mut txn)
.instrument(tracing::info_span!("Insert compat session"))
.await?;
let session = CompatSession {
id,
user,
device,
created_at,
finished_at: None,
};
let session = start_compat_session(&mut txn, &mut rng, clock, user, device).await?;
let fulfilled_at = clock.now();
sqlx::query!(