From f7f57e92e3d14c233b736951853c4863b624b831 Mon Sep 17 00:00:00 2001 From: nullishamy Date: Thu, 1 May 2025 23:23:29 +0100 Subject: [PATCH] feat: oauth --- ferri-server/src/endpoints/api/apps.rs | 4 +- ferri-server/src/endpoints/oauth.rs | 69 ++++++++++++++++++++++---- ferri-server/src/lib.rs | 1 + ferri-server/templates/authorize.html | 46 +++++++++++++++++ 4 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 ferri-server/templates/authorize.html diff --git a/ferri-server/src/endpoints/api/apps.rs b/ferri-server/src/endpoints/api/apps.rs index 7b566d2..a798f0c 100644 --- a/ferri-server/src/endpoints/api/apps.rs +++ b/ferri-server/src/endpoints/api/apps.rs @@ -27,8 +27,8 @@ pub async fn new_app( VALUES (?1, ?2, ?3) "#, app.client_name, - app.scopes, - secret + secret, + app.scopes ) .execute(&mut **db) .await diff --git a/ferri-server/src/endpoints/oauth.rs b/ferri-server/src/endpoints/oauth.rs index 6d0391e..49f728c 100644 --- a/ferri-server/src/endpoints/oauth.rs +++ b/ferri-server/src/endpoints/oauth.rs @@ -1,23 +1,41 @@ use crate::Db; +use askama::Template; +use tracing::error; + use rocket::{ FromForm, form::Form, get, post, response::Redirect, + response::status::BadRequest, + response::content::RawHtml, serde::{Deserialize, Serialize, json::Json}, }; + use rocket_db_pools::Connection; -#[get("/oauth/authorize?&&&")] -pub async fn authorize( - client_id: &str, - scope: &str, - redirect_uri: &str, - response_type: &str, +struct AuthorizeClient { + id: String +} + +#[derive(Template)] +#[template(path = "authorize.html")] +struct AuthorizeTemplate { + client: AuthorizeClient, + scopes: Vec, + scope_raw: String, + redirect_uri: String, + user_id: String +} + +#[post("/oauth/accept?&&")] +pub async fn accept( mut db: Connection, -) -> Redirect { - // For now, we will always authorize the request and assign it to an admin user - let user_id = "9b9d497b-2731-435f-a929-e609ca69dac9"; + id: &str, + client_id: &str, + scope: &str +) -> RawHtml { + let user_id = id; let code = main::gen_token(15); // This will act as a token for the user, but we will in future say that it expires very shortly @@ -52,7 +70,38 @@ pub async fn authorize( .await .unwrap(); - Redirect::temporary(format!("{}?code={}", redirect_uri, code)) + // HACK: Until we are storing oauth stuff more properly we will hardcode phanpy + RawHtml(format!(r#" + + "#, "https://phanpy.social?code=", code)) +} + +#[get("/oauth/authorize?&&&")] +pub async fn authorize( + client_id: &str, + scope: &str, + redirect_uri: &str, + response_type: &str, + mut db: Connection, +) -> Result, BadRequest> { + if response_type != "code" { + error!("unknown response type {}", response_type); + return Err( + BadRequest(format!("unknown response type {}", response_type)) + ) + } + + let tmpl = AuthorizeTemplate { + client: AuthorizeClient { + id: client_id.to_string() + }, + scope_raw: scope.to_string(), + scopes: scope.split(" ").map(|s| s.to_string()).collect(), + redirect_uri: redirect_uri.to_string(), + user_id: "9b9d497b-2731-435f-a929-e609ca69dac9".to_string() + }; + + Ok(RawHtml(tmpl.render().unwrap())) } #[derive(Serialize, Deserialize, Debug)] diff --git a/ferri-server/src/lib.rs b/ferri-server/src/lib.rs index c8cfb9a..adf3a21 100644 --- a/ferri-server/src/lib.rs +++ b/ferri-server/src/lib.rs @@ -140,6 +140,7 @@ pub fn launch(cfg: Config) -> Rocket { user::following, user::post, oauth::authorize, + oauth::accept, oauth::new_token, cors::options_req, activity_endpoint, diff --git a/ferri-server/templates/authorize.html b/ferri-server/templates/authorize.html new file mode 100644 index 0000000..bba0a95 --- /dev/null +++ b/ferri-server/templates/authorize.html @@ -0,0 +1,46 @@ + + + + + + + + + Ferri Test + + + + + + + +
+

Authorization request

+ + + App '{{ client.id }}' would like to access the following scopes in your account + + +
    + {% for scope in scopes %} +
  • {{ scope }}
  • + {% endfor %} +
+ + +
+ +