Compare commits

..

2 Commits

4 changed files with 58 additions and 13 deletions

10
API.md
View File

@ -27,7 +27,7 @@ The verification request was sent.
##### 400 - Error: Bad Request ##### 400 - Error: Bad Request
The request was malformed. The request was malformed.
##### 403 - Error: Forbidden ##### 403 - Error: Forbidden
The password is not matching the requirements. Blocked for security reasons.
##### 409 - Error: Conflict ##### 409 - Error: Conflict
The requested username or email is already taken. The requested username or email is already taken.
@ -58,6 +58,8 @@ The account was verified. You can login now.
##### 400 - Error: Bad Request ##### 400 - Error: Bad Request
The request was malformed. The request was malformed.
##### 403 - Error: Forbidden ##### 403 - Error: Forbidden
Blocked for security reasons.
##### 404 - Error: Forbidden
The provided token is unknown. The provided token is unknown.
### `/account/authenticate` - POST ### `/account/authenticate` - POST
@ -85,8 +87,10 @@ __Content - JSON:__
##### 400 - Error: Bad Request ##### 400 - Error: Bad Request
The request was malformed. The request was malformed.
##### 403 - Error: Forbidden ##### 401 - Error: Unauthorized
The provided password was wrong. The provided password was wrong.
##### 403 - Error: Forbidden
Blocked for security reasons.
##### 404 - Error: Not Found ##### 404 - Error: Not Found
The provided username was not found. The provided username was not found.
@ -103,3 +107,5 @@ Deletes the account.
The account was deleted. The account was deleted.
##### 401 - Error: Unauthorized ##### 401 - Error: Unauthorized
The provided token doesn't allow you to perform this operation. The provided token doesn't allow you to perform this operation.
##### 403 - Error: Forbidden
Blocked for security reasons.

View File

@ -12,9 +12,9 @@ async fn register(
match handlers::register(body.into_inner()).await { match handlers::register(body.into_inner()).await {
Ok(resp) => match resp { Ok(resp) => match resp {
data::RegisterResponse::Success => HttpResponse::Ok().finish(), data::RegisterResponse::Success => HttpResponse::Ok().finish(),
data::RegisterResponse::PasswordTooWeak => HttpResponse::Forbidden().finish(),
data::RegisterResponse::Conflict(b) => HttpResponse::Conflict().json(web::Json(b)), data::RegisterResponse::Conflict(b) => HttpResponse::Conflict().json(web::Json(b)),
data::RegisterResponse::MalformedEmail => HttpResponse::UnprocessableEntity().finish(), data::RegisterResponse::MalformedEmail => HttpResponse::UnprocessableEntity().finish(),
data::RegisterResponse::Blocked => HttpResponse::Forbidden().finish(),
}, },
Err(e) => { Err(e) => {
error!("While handling register request: {e}"); error!("While handling register request: {e}");
@ -28,7 +28,8 @@ async fn verify(data: web::Data<ApiState>, body: web::Json<data::VerifyRequest>)
match handlers::verify(body.into_inner()).await { match handlers::verify(body.into_inner()).await {
Ok(resp) => match resp { Ok(resp) => match resp {
data::VerifyResponse::Success => HttpResponse::Ok().finish(), data::VerifyResponse::Success => HttpResponse::Ok().finish(),
data::VerifyResponse::TokenUnknown => HttpResponse::Forbidden().finish(), data::VerifyResponse::TokenUnknown => HttpResponse::NotFound().finish(),
data::VerifyResponse::Blocked => HttpResponse::Forbidden().finish(),
}, },
Err(e) => { Err(e) => {
error!("While handling verify request: {e}"); error!("While handling verify request: {e}");
@ -45,8 +46,9 @@ async fn authenticate(
match handlers::authenticate(body.into_inner()).await { match handlers::authenticate(body.into_inner()).await {
Ok(resp) => match resp { Ok(resp) => match resp {
data::AuthenticateResponse::Success(b) => HttpResponse::Ok().json(web::Json(b)), data::AuthenticateResponse::Success(b) => HttpResponse::Ok().json(web::Json(b)),
data::AuthenticateResponse::WrongPassword => HttpResponse::Forbidden().finish(), data::AuthenticateResponse::WrongPassword => HttpResponse::Unauthorized().finish(),
data::AuthenticateResponse::UserNotFound => HttpResponse::NotFound().finish(), data::AuthenticateResponse::UserNotFound => HttpResponse::NotFound().finish(),
data::AuthenticateResponse::Blocked => HttpResponse::Forbidden().finish(),
}, },
Err(e) => { Err(e) => {
error!("While handling authenticate request: {e}"); error!("While handling authenticate request: {e}");
@ -61,6 +63,7 @@ async fn delete(data: web::Data<ApiState>, auth: BearerAuth) -> impl Responder {
Ok(resp) => match resp { Ok(resp) => match resp {
data::DeleteResponse::Success => HttpResponse::Ok().finish(), data::DeleteResponse::Success => HttpResponse::Ok().finish(),
data::DeleteResponse::Unauthorized => HttpResponse::Unauthorized().finish(), data::DeleteResponse::Unauthorized => HttpResponse::Unauthorized().finish(),
data::DeleteResponse::Blocked => HttpResponse::Forbidden().finish(),
}, },
Err(e) => { Err(e) => {
error!("While handling delete request: {e}"); error!("While handling delete request: {e}");

View File

@ -2,9 +2,9 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct RegisterRequest { pub struct RegisterRequest {
username: String, pub username: String,
password: String, pub password: String,
email: String, pub email: String,
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
@ -17,26 +17,27 @@ pub enum RegisterConflict {
#[derive(Debug)] #[derive(Debug)]
pub enum RegisterResponse { pub enum RegisterResponse {
Success, Success,
PasswordTooWeak,
Conflict(RegisterConflict), Conflict(RegisterConflict),
MalformedEmail, MalformedEmail,
Blocked,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct VerifyRequest { pub struct VerifyRequest {
token: String, pub token: String,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum VerifyResponse { pub enum VerifyResponse {
Success, Success,
Blocked,
TokenUnknown, TokenUnknown,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct AuthenticateRequest { pub struct AuthenticateRequest {
username: String, pub username: String,
password: String, pub password: String,
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
@ -49,10 +50,12 @@ pub enum AuthenticateResponse {
Success(AuthenticateSuccess), Success(AuthenticateSuccess),
WrongPassword, WrongPassword,
UserNotFound, UserNotFound,
Blocked,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum DeleteResponse { pub enum DeleteResponse {
Success, Success,
Blocked,
Unauthorized, Unauthorized,
} }

View File

@ -2,17 +2,46 @@ use crate::api::account::data;
use anyhow::Result; use anyhow::Result;
use log::info; use log::info;
fn is_sql_injection(string: &String) -> bool {
match libinjection::sqli(string) {
Some((is_injection, _)) => is_injection,
None => true, // this could be a false positive, but that would be better than an SQLi
}
}
trait AlphaExt {
fn is_alpha(&self) -> bool;
}
impl AlphaExt for String {
fn is_alpha(&self) -> bool {
self.chars().all(|c| c.is_alphanumeric())
}
}
pub async fn register(request: data::RegisterRequest) -> Result<data::RegisterResponse> { pub async fn register(request: data::RegisterRequest) -> Result<data::RegisterResponse> {
if is_sql_injection(&request.username) || is_sql_injection(&request.email) {
return Ok(data::RegisterResponse::Blocked);
}
Ok(data::RegisterResponse::Success) Ok(data::RegisterResponse::Success)
} }
pub async fn verify(request: data::VerifyRequest) -> Result<data::VerifyResponse> { pub async fn verify(request: data::VerifyRequest) -> Result<data::VerifyResponse> {
if !request.token.is_alpha() {
return Ok(data::VerifyResponse::Blocked);
}
Ok(data::VerifyResponse::Success) Ok(data::VerifyResponse::Success)
} }
pub async fn authenticate( pub async fn authenticate(
request: data::AuthenticateRequest, request: data::AuthenticateRequest,
) -> Result<data::AuthenticateResponse> { ) -> Result<data::AuthenticateResponse> {
if is_sql_injection(&request.username) {
return Ok(data::AuthenticateResponse::Blocked);
}
Ok(data::AuthenticateResponse::Success( Ok(data::AuthenticateResponse::Success(
data::AuthenticateSuccess { data::AuthenticateSuccess {
token: "not_a_valid_token".to_string(), token: "not_a_valid_token".to_string(),
@ -21,6 +50,10 @@ pub async fn authenticate(
} }
pub async fn delete(token: String) -> Result<data::DeleteResponse> { pub async fn delete(token: String) -> Result<data::DeleteResponse> {
if !token.is_alpha() {
return Ok(data::DeleteResponse::Blocked);
}
info!("Token: {}", token); info!("Token: {}", token);
Ok(data::DeleteResponse::Success) Ok(data::DeleteResponse::Success)
} }