ezidam, openid: refactor check app in method, verifying and send POST as well

This commit is contained in:
Philippe Loctaux 2023-03-16 21:38:32 +01:00
parent 8ae0c59a25
commit eb93cbd7ec
7 changed files with 76 additions and 22 deletions

1
Cargo.lock generated
View file

@ -86,6 +86,7 @@ dependencies = [
"database", "database",
"hash", "hash",
"id", "id",
"openid",
"thiserror", "thiserror",
"url", "url",
] ]

View file

@ -12,3 +12,4 @@ url = { workspace = true }
id = { path = "../id" } id = { path = "../id" }
database = { path = "../database" } database = { path = "../database" }
hash = { path = "../hash" } hash = { path = "../hash" }
openid = { path = "../openid" }

View file

@ -42,11 +42,11 @@ impl App {
} }
/// App needs to be not archived /// App needs to be not archived
pub async fn get_one( pub(crate) async fn get_one(
conn: impl SqliteExecutor<'_>, conn: impl SqliteExecutor<'_>,
id: &str, id: &str,
redirect: &str, redirect: &str,
) -> Result<Option<Self>, Error> { ) -> Result<Option<Self>, database::Error> {
Ok(DatabaseApps::get_one(conn, id, redirect) Ok(DatabaseApps::get_one(conn, id, redirect)
.await? .await?
.map(Self::from)) .map(Self::from))

View file

@ -0,0 +1,42 @@
// error
#[derive(thiserror::Error)]
// the rest
#[derive(Debug)]
pub enum Error {
#[error("Database: {0}")]
Database(#[from] database::Error),
#[error("Bad response types")]
ResponseTypes,
#[error("Invalid scopes")]
Scopes,
#[error("Invalid application")]
Application,
}
use super::App;
use database::sqlx::SqliteExecutor;
impl App {
pub async fn get_valid_app(
conn: impl SqliteExecutor<'_>,
response_type: &str,
scope: &str,
client_id: &str,
redirect_uri: &str,
) -> Result<App, Error> {
// Check for valid response types
openid::parse_response_types(response_type).ok_or_else(|| Error::ResponseTypes)?;
// Check for supported scopes
if !openid::SupportedScopes::check_supported_scopes(scope) {
return Err(Error::Scopes);
}
Self::get_one(conn, client_id, redirect_uri)
.await?
.ok_or_else(|| Error::Application)
}
}

View file

@ -1,10 +1,12 @@
mod database; mod database;
mod error; mod error;
mod get_valid;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use id::AppID; use id::AppID;
pub use crate::error::Error; pub use crate::error::Error;
pub use get_valid::Error as GetValidError;
#[derive(Debug)] #[derive(Debug)]
pub struct App { pub struct App {

View file

@ -57,3 +57,14 @@ impl From<apps::Error> for Error {
Error::internal_server_error(e) Error::internal_server_error(e)
} }
} }
impl From<apps::GetValidError> for Error {
fn from(e: apps::GetValidError) -> Self {
match e {
apps::GetValidError::Database(e) => Error::internal_server_error(e),
apps::GetValidError::ResponseTypes
| apps::GetValidError::Scopes
| apps::GetValidError::Application => Error::bad_request(e),
}
}
}

View file

@ -28,25 +28,17 @@ async fn authorize_page(
flash: Option<FlashMessage<'_>>, flash: Option<FlashMessage<'_>>,
auth_request: AuthenticationRequest<'_>, auth_request: AuthenticationRequest<'_>,
) -> Result<Template> { ) -> Result<Template> {
// Check for valid response types
openid::parse_response_types(auth_request.response_type)
.ok_or_else(|| Error::bad_request("Bad response types"))?;
// Check for supported scopes
if !openid::SupportedScopes::check_supported_scopes(auth_request.scope) {
return Err(Error::bad_request("Invalid scopes"));
}
let mut transaction = db.begin().await?; let mut transaction = db.begin().await?;
// TODO: wrap checking in function?
let app = App::get_one( // Get app info
let app = App::get_valid_app(
&mut transaction, &mut transaction,
auth_request.response_type,
auth_request.scope,
auth_request.client_id, auth_request.client_id,
auth_request.redirect_uri, auth_request.redirect_uri,
) )
.await? .await?;
.ok_or_else(|| Error::bad_request("Invalid application"))?;
let settings = Settings::get(&mut transaction).await?; let settings = Settings::get(&mut transaction).await?;
@ -118,16 +110,23 @@ async fn authorize(
mut db: Connection<Database>, mut db: Connection<Database>,
auth_request: AuthenticationRequest<'_>, auth_request: AuthenticationRequest<'_>,
) -> Result<Either<Redirect, Flash<Redirect>>> { ) -> Result<Either<Redirect, Flash<Redirect>>> {
// TODO: check app and stuff before doing anything AGAIN, this is important let mut transaction = db.begin().await?;
// TODO: check if request uri matches
// Get app info
let app = App::get_valid_app(
&mut transaction,
auth_request.response_type,
auth_request.scope,
auth_request.client_id,
auth_request.redirect_uri,
)
.await?;
if form.login.is_empty() { if form.login.is_empty() {
return Ok(Either::Right(invalid_form(auth_request))); return Ok(Either::Right(invalid_form(auth_request)));
} }
let form = form.into_inner(); let form = form.into_inner();
let mut transaction = db.begin().await?;
// Get user // Get user
let Some(user) = User::get_by_login(&mut transaction, form.login).await? else { let Some(user) = User::get_by_login(&mut transaction, form.login).await? else {
return Ok(Either::Right(invalid_credentials(form.login, auth_request))); return Ok(Either::Right(invalid_credentials(form.login, auth_request)));
@ -154,9 +153,7 @@ async fn authorize(
// TODO: refresh token + jwt // TODO: refresh token + jwt
// TODO: put more data // TODO: put more data
Ok(Either::Left(Redirect::to( Ok(Either::Left(Redirect::to(app.redirect_uri().to_string())))
auth_request.redirect_uri.to_string(),
)))
} }
// TODO: oauth redirect route for ezidam // TODO: oauth redirect route for ezidam