Skip to content

Commit

Permalink
Added password hashing
Browse files Browse the repository at this point in the history
  • Loading branch information
sganis committed Oct 7, 2023
1 parent e8dc542 commit 37f76da
Show file tree
Hide file tree
Showing 11 changed files with 391 additions and 152 deletions.
33 changes: 33 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ serde_json = { version = "1.0", features = ["arbitrary_precision"] }
jsonwebtoken = "8.3"
once_cell = "1.18"
dotenvy = "0.15.7"
argon2 = "0.5.2"

9 changes: 8 additions & 1 deletion frontend/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import Working from './lib/Working.svelte';
import Stats from './routes/Stats.svelte';
import Order from './routes/Order.svelte';
import Profile from './routes/Profile.svelte';
const routes = {
Expand All @@ -26,6 +27,7 @@
'/logout': Logout,
'/order/:id?': Order,
'/stats': Stats,
'/profile': Profile,
// Catch-all
'*': NotFound,
Expand All @@ -50,6 +52,11 @@
Stats
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/profile" use:link >
Profile
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/logout" use:link >
Logout
Expand All @@ -71,7 +78,7 @@

<div class="container">

<Error message={$apierror} />
<Error error={$apierror} />

<Router {routes} restoreScrollState={true} />

Expand Down
6 changes: 3 additions & 3 deletions frontend/src/lib/Error.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script>
export let message;
export let error;
</script>

{#if message}
{#if error}
<div class="row alert alert-danger">
{message}
{error}
</div>
{/if}
2 changes: 1 addition & 1 deletion frontend/src/routes/Order.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@
<div class="col h2">Order:</div>
</div>

<Error message={error} />
<Error {error} />

<form on:submit|preventDefault={saveOrder}
class="needs-validation" novalidate>
Expand Down
94 changes: 94 additions & 0 deletions frontend/src/routes/Profile.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<script>
import Error from '../lib/Error.svelte';
import Info from '../lib/Info.svelte';
import { state, working } from '../lib/store';
import { push } from 'svelte-spa-router';
let error;
let info;
let password;
let newpassword;
let newpassword2;
let url = `${import.meta.env.VITE_PUBLIC_BASE_URL}password`;
const onSubmit = async (e) => {
try {
$working = true;
console.log('logging in...');
const r = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({username: $state.username, password, newpassword}),
});
const js = await r.json();
console.log(js);
if (r.status === 200) {
info = js.result;
} else {
error = js.detail;
}
}
catch (err) {
console.log(err)
}
finally {
$working = false;
}
}
</script>
<div class="row">
User: {$state.username}
</div>
<br>
<div class="login">
<form class="form" on:submit|preventDefault={onSubmit}>
<div class="mb-3">
<label class="form-label" for="password">Current password</label>
<input
bind:value={password}
class="form-control"
id="password"
name="password"
type="password"
required
disabled={$working}/>
</div>
<div class="mb-3">
<label class="form-label" for="newpassword">New password</label>
<input
bind:value={newpassword}
class="form-control"
id="newpassword"
name="newpassword"
type="password"
required
disabled={$working} />
</div>
<div class="mb-3">
<label class="form-label" for="newpassword2">Repeat new passord</label>
<input
bind:value={newpassword2}
class="form-control"
id="newpassword2"
name="newpassword2"
type="password"
required
disabled={$working} />
</div>
<button class="btn btn-primary"
type="submit"
disabled={$working}>
Change Password
</button>
</form>
</div>
<br>
<Info {info} />
<Error {error} />
1 change: 1 addition & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
max_width = 80
100 changes: 30 additions & 70 deletions src/auth.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
use serde::{Deserialize, Serialize};
use jsonwebtoken::{decode, DecodingKey, EncodingKey, Validation};
use once_cell::sync::Lazy;
use serde_json::json;
use std::fmt::Display;
use axum::http::{request::Parts, StatusCode};
use axum::{
async_trait,
extract::FromRequestParts,
response::{IntoResponse, Response},
Json, RequestPartsExt,
headers::{authorization::Bearer, Authorization},
TypedHeader,
};
use axum::http::{
request::Parts,
StatusCode,
response::{IntoResponse, Response},
Json, RequestPartsExt, TypedHeader,
};
use jsonwebtoken::{decode, DecodingKey, EncodingKey, Validation};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::fmt::Display;


#[derive(Deserialize, sqlx::FromRow)]
pub struct AuthPayload {
#[derive(Deserialize, sqlx::FromRow, Debug, Clone)]
pub struct AuthData {
pub username: String,
pub password: String,
pub newpassword: Option<String>,
}

#[derive(Deserialize, Serialize)]
Expand Down Expand Up @@ -48,30 +44,35 @@ pub static KEYS: Lazy<Keys> = Lazy::new(|| {
Keys::new(secret.as_bytes())
});


impl Display for Claims {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "username: {} expiration: {}", self.sub, self.exp)
}
}


#[async_trait]
impl<S> FromRequestParts<S> for Claims
where
S: Send + Sync,
{
type Rejection = AuthError;

async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
async fn from_request_parts(
parts: &mut Parts,
_state: &S,
) -> Result<Self, Self::Rejection> {
// Extract the token from the authorization header
let TypedHeader(Authorization(bearer)) = parts
.extract::<TypedHeader<Authorization<Bearer>>>()
.await
.map_err(|_| AuthError::InvalidToken)?;
// Decode the user data
let token_data = decode::<Claims>(bearer.token(), &KEYS.decoding, &Validation::default())
.map_err(|_| AuthError::InvalidToken)?;
let token_data = decode::<Claims>(
bearer.token(),
&KEYS.decoding,
&Validation::default(),
)
.map_err(|_| AuthError::InvalidToken)?;

Ok(token_data.claims)
}
Expand All @@ -80,10 +81,14 @@ where
impl IntoResponse for AuthError {
fn into_response(self) -> Response {
let (status, error_message) = match self {
AuthError::WrongCredentials => (StatusCode::UNAUTHORIZED, "Wrong credentials"),
AuthError::MissingCredentials => (StatusCode::BAD_REQUEST, "Missing credentials"),
AuthError::TokenCreation => (StatusCode::INTERNAL_SERVER_ERROR, "Token creation error"),
AuthError::InvalidToken => (StatusCode::BAD_REQUEST, "Invalid token"),
//AuthError::WrongCredentials => (StatusCode::UNAUTHORIZED, "Wrong credentials"),
//AuthError::MissingCredentials => (StatusCode::BAD_REQUEST, "Missing credentials"),
AuthError::TokenCreation => {
(StatusCode::INTERNAL_SERVER_ERROR, "Token creation error")
}
AuthError::InvalidToken => {
(StatusCode::BAD_REQUEST, "Invalid token")
}
};
let body = Json(json!({
"detail": error_message,
Expand All @@ -92,53 +97,8 @@ impl IntoResponse for AuthError {
}
}

// pub struct Keys {
// pub encoding: EncodingKey,
// pub decoding: DecodingKey,
// }

// impl Keys {
// pub fn new(secret: &[u8]) -> Self {
// Self {
// encoding: EncodingKey::from_secret(secret),
// decoding: DecodingKey::from_secret(secret),
// }
// }
// }

// #[derive(Debug, Serialize, Deserialize)]
// pub struct Claims {
// pub sub: String,
// pub exp: usize,
// }

// #[derive(Debug, Serialize)]
// pub struct AuthBody {
// pub access_token: String,
// pub token_type: String,
// pub username: String,
// }

// #[derive(Debug, Deserialize)]
// pub struct AuthPayload {
// pub username: String,
// pub password: String,
// }

// impl AuthBody {
// pub fn new(access_token: String, username: String) -> Self {
// Self {
// access_token,
// token_type: "Bearer".to_string(),
// username,
// }
// }
// }

#[derive(Debug)]
pub enum AuthError {
WrongCredentials,
MissingCredentials,
TokenCreation,
InvalidToken,
}
}
Loading

0 comments on commit 37f76da

Please sign in to comment.