mirror of
https://github.com/nullishamy/ferri.git
synced 2025-06-28 00:54:17 +00:00
feat: oauth
This commit is contained in:
parent
4167a2f8bb
commit
f7f57e92e3
4 changed files with 108 additions and 12 deletions
|
@ -27,8 +27,8 @@ pub async fn new_app(
|
||||||
VALUES (?1, ?2, ?3)
|
VALUES (?1, ?2, ?3)
|
||||||
"#,
|
"#,
|
||||||
app.client_name,
|
app.client_name,
|
||||||
app.scopes,
|
secret,
|
||||||
secret
|
app.scopes
|
||||||
)
|
)
|
||||||
.execute(&mut **db)
|
.execute(&mut **db)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -1,23 +1,41 @@
|
||||||
use crate::Db;
|
use crate::Db;
|
||||||
|
use askama::Template;
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
FromForm,
|
FromForm,
|
||||||
form::Form,
|
form::Form,
|
||||||
get, post,
|
get, post,
|
||||||
response::Redirect,
|
response::Redirect,
|
||||||
|
response::status::BadRequest,
|
||||||
|
response::content::RawHtml,
|
||||||
serde::{Deserialize, Serialize, json::Json},
|
serde::{Deserialize, Serialize, json::Json},
|
||||||
};
|
};
|
||||||
|
|
||||||
use rocket_db_pools::Connection;
|
use rocket_db_pools::Connection;
|
||||||
|
|
||||||
#[get("/oauth/authorize?<client_id>&<scope>&<redirect_uri>&<response_type>")]
|
struct AuthorizeClient {
|
||||||
pub async fn authorize(
|
id: String
|
||||||
client_id: &str,
|
}
|
||||||
scope: &str,
|
|
||||||
redirect_uri: &str,
|
#[derive(Template)]
|
||||||
response_type: &str,
|
#[template(path = "authorize.html")]
|
||||||
|
struct AuthorizeTemplate {
|
||||||
|
client: AuthorizeClient,
|
||||||
|
scopes: Vec<String>,
|
||||||
|
scope_raw: String,
|
||||||
|
redirect_uri: String,
|
||||||
|
user_id: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/oauth/accept?<id>&<client_id>&<scope>")]
|
||||||
|
pub async fn accept(
|
||||||
mut db: Connection<Db>,
|
mut db: Connection<Db>,
|
||||||
) -> Redirect {
|
id: &str,
|
||||||
// For now, we will always authorize the request and assign it to an admin user
|
client_id: &str,
|
||||||
let user_id = "9b9d497b-2731-435f-a929-e609ca69dac9";
|
scope: &str
|
||||||
|
) -> RawHtml<String> {
|
||||||
|
let user_id = id;
|
||||||
let code = main::gen_token(15);
|
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
|
// 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
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Redirect::temporary(format!("{}?code={}", redirect_uri, code))
|
// HACK: Until we are storing oauth stuff more properly we will hardcode phanpy
|
||||||
|
RawHtml(format!(r#"
|
||||||
|
<script>window.location.href="{}{}"</script>
|
||||||
|
"#, "https://phanpy.social?code=", code))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/oauth/authorize?<client_id>&<scope>&<redirect_uri>&<response_type>")]
|
||||||
|
pub async fn authorize(
|
||||||
|
client_id: &str,
|
||||||
|
scope: &str,
|
||||||
|
redirect_uri: &str,
|
||||||
|
response_type: &str,
|
||||||
|
mut db: Connection<Db>,
|
||||||
|
) -> Result<RawHtml<String>, BadRequest<String>> {
|
||||||
|
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)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
@ -140,6 +140,7 @@ pub fn launch(cfg: Config) -> Rocket<Build> {
|
||||||
user::following,
|
user::following,
|
||||||
user::post,
|
user::post,
|
||||||
oauth::authorize,
|
oauth::authorize,
|
||||||
|
oauth::accept,
|
||||||
oauth::new_token,
|
oauth::new_token,
|
||||||
cors::options_req,
|
cors::options_req,
|
||||||
activity_endpoint,
|
activity_endpoint,
|
||||||
|
|
46
ferri-server/templates/authorize.html
Normal file
46
ferri-server/templates/authorize.html
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<base href="https://ferri.amy.mov/admin/">
|
||||||
|
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<title>Ferri Test</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://raw.githubusercontent.com/tailwindlabs/tailwindcss/dbc8023a08964f513c20796e170cb91ce891df3f/packages/tailwindcss/preflight.css">
|
||||||
|
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<h1>Authorization request</h1>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
App '{{ client.id }}' would like to access the following scopes in your account
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for scope in scopes %}
|
||||||
|
<li>{{ scope }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<button
|
||||||
|
hx-post="/oauth/accept?id={{ user_id }}&client_id={{ client.id }}&scope={{ scope_raw }}"
|
||||||
|
>
|
||||||
|
Accept and return to {{ redirect_uri }}?
|
||||||
|
</button>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue