Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fd2a74f

Browse files
chore: Redefined error message upon failed login
1 parent d1330ea commit fd2a74f

File tree

8 files changed

+187
-183
lines changed

8 files changed

+187
-183
lines changed

‎Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ reqwest = { version = "0.11.18", default-features = false, features = ["json", "
3333
rand = { version = "0.8", features = ["std_rng"] }
3434
thiserror = "1"
3535
anyhow = "1"
36-
base64 = "0.13.0"
3736
argon2 = { version = "0.3", features = ["std"] }
3837
urlencoding = "2"
3938
htmlescape = "0.3"
4039
hmac = { version = "0.12", features = ["std"] }
4140
sha2 = "0.10"
4241
hex = "0.4"
42+
base64 = "0.21.0"
4343

4444
[dev-dependencies]
4545
once_cell = "1"

‎src/authentication.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use anyhow::Context;
2+
use argon2::{Argon2, PasswordHash, PasswordVerifier};
3+
use secrecy::{ExposeSecret, Secret};
4+
use sqlx::PgPool;
5+
6+
use crate::telemetry::spawn_blocking_with_tracing;
7+
8+
#[derive(thiserror::Error, Debug)]
9+
pub enum AuthError {
10+
#[error("Invalid credentials.")]
11+
InvalidCredentials(#[source] anyhow::Error),
12+
#[error(transparent)]
13+
UnexpectedError(#[from] anyhow::Error),
14+
}
15+
16+
pub struct Credentials {
17+
pub username: String,
18+
pub password: Secret<String>,
19+
}
20+
21+
#[tracing::instrument(name = "Get stored credentials", skip(username, pool))]
22+
async fn get_stored_credentials(
23+
username: &str,
24+
pool: &PgPool,
25+
) -> Result<Option<(uuid::Uuid, Secret<String>)>, anyhow::Error> {
26+
let row = sqlx::query!(
27+
r#"
28+
SELECT user_id, password_hash
29+
FROM users
30+
WHERE username = 1ドル
31+
"#,
32+
username,
33+
)
34+
.fetch_optional(pool)
35+
.await
36+
.context("Failed to performed a query to retrieve stored credentials.")?
37+
.map(|row| (row.user_id, Secret::new(row.password_hash)));
38+
Ok(row)
39+
}
40+
41+
#[tracing::instrument(name = "Validate credentials", skip(credentials, pool))]
42+
pub async fn validate_credentials(
43+
credentials: Credentials,
44+
pool: &PgPool,
45+
) -> Result<uuid::Uuid, AuthError> {
46+
let mut user_id = None;
47+
let mut expected_password_hash = Secret::new(
48+
"$argon2id$v=19$m=15000,t=2,p=1$\
49+
gZiV/M1gPc22ElAH/Jh1Hw$\
50+
CWOrkoo7oJBQ/iyh7uJ0LO2aLEfrHwTWllSAxT0zRno"
51+
.to_string(),
52+
);
53+
54+
if let Some((stored_user_id, stored_password_hash)) =
55+
get_stored_credentials(&credentials.username, pool).await?
56+
{
57+
user_id = Some(stored_user_id);
58+
expected_password_hash = stored_password_hash;
59+
}
60+
61+
spawn_blocking_with_tracing(move || {
62+
verify_password_hash(expected_password_hash, credentials.password)
63+
})
64+
.await
65+
.context("Failed to spawn blocking task.")??;
66+
67+
user_id
68+
.ok_or_else(|| anyhow::anyhow!("Unknown username."))
69+
.map_err(AuthError::InvalidCredentials)
70+
}
71+
72+
#[tracing::instrument(
73+
name = "Validate credentials",
74+
skip(expected_password_hash, password_candidate)
75+
)]
76+
fn verify_password_hash(
77+
expected_password_hash: Secret<String>,
78+
password_candidate: Secret<String>,
79+
) -> Result<(), AuthError> {
80+
let expected_password_hash = PasswordHash::new(expected_password_hash.expose_secret())
81+
.context("Failed to parse hash in PHC string format.")?;
82+
83+
Argon2::default()
84+
.verify_password(
85+
password_candidate.expose_secret().as_bytes(),
86+
&expected_password_hash,
87+
)
88+
.context("Invalid password.")
89+
.map_err(AuthError::InvalidCredentials)
90+
}

‎src/configuration.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub struct ApplicationSettings {
1919
pub port: u16,
2020
pub host: String,
2121
pub base_url: String,
22+
pub hmac_secret: Secret<String>,
2223
}
2324

2425
#[derive(serde::Deserialize, Clone)]

‎src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ pub mod configuration;
33
pub mod domain;
44
pub mod email_client;
55
pub mod routes;
6-
pub mod session_state;
76
pub mod startup;
87
pub mod telemetry;
98
pub mod utils;

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /