Skip to content

Commit 9889658

Browse files
committed
feat(oauth): POST form back, instead of redirect
1 parent a0e8709 commit 9889658

File tree

1 file changed

+76
-40
lines changed

1 file changed

+76
-40
lines changed

src/api/v1/oauth.rs

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use axum::extract::State;
2-
use axum::response::{Html, IntoResponse, Redirect};
2+
use axum::response::{Html, IntoResponse};
33
use axum::routing::get;
44
use axum::{Form, Router};
55
use radicle::crypto::{PublicKey, Signature};
@@ -35,41 +35,13 @@ async fn oauth_page_handler(
3535
State(ctx): State<Context>,
3636
Query(prms): Query<OauthPageParams>,
3737
) -> impl IntoResponse {
38-
let alias = &ctx.profile.config.node.alias.to_string();
39-
let nid = &ctx.profile.public_key.to_string();
4038
if prms.callback_url.is_none() {
4139
return Html(String::from("Invalid callback URL"));
4240
}
41+
let alias = &ctx.profile.config.node.alias.to_string();
42+
let nid = &ctx.profile.public_key.to_string();
4343
let cb = prms.callback_url.unwrap_or_default();
44-
Html(String::from(
45-
"<!DOCTYPE html><html lang=\"en\">
46-
<head>
47-
<title>$alias Radicle HTTP API OAuth Page</title>
48-
</head>
49-
<body style=\"background-color:#0a0d10;margin:0;\">
50-
<form method=\"POST\">
51-
<div style=\"background-image:url('https://app.radicle.xyz/images/default-seed-header.png');border-bottom:1px solid;height:18rem;background-position:center;background-size:cover;\"></div>
52-
<div style=\"max-width:500px;margin-left:auto;margin-right:auto;margin-top:25px;\">
53-
<div style=\"height:12rem;border:1px solid #2e2f38;border-radius:4px;background-color:#14151a;padding:.75rem 1rem;position:relative;display:flex;flex-direction:column;justify-content:space-between;overflow:hidden;\">
54-
<div class=\"title\" style=\"display:flex;flex-direction:column;gap:.125rem;position:relative;\">
55-
<div class=\"headline-and-badges\" style=\"display:flex;justify-content:space-between;gap:.5rem;\">
56-
<h4 style=\"margin:0;color:rgb(249,249,251);line-clamp:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;\">Radicle HTTP API</h4>
57-
<img width=\"24\" height=\"24\" class=\"logo\" alt=\"Radicle logo\" src=\"https://app.radicle.xyz/radicle.svg\" style=\"margin:0px 0.5rem;\">
58-
</div>
59-
<p class=\"txt-small\" style=\"margin:0;color:#9b9bb1;\">Running on $alias</p>
60-
<p class=\"txt-small\" style=\"margin:0;color:#9b9bb1;\">$nid</p>
61-
</div>
62-
<div class=\"wrapper\" style=\"display:flex;flex-direction:column;margin:25px 0 0 0;position:relative;flex:1;align-items:start;height:2.5rem;\">
63-
<label for=\"session_id\" class=\"txt-small\" style=\"margin:0;color:#9b9bb1;\">Fill in your session ID</label>
64-
<input type=\"text\" id=\"session_id\" name=\"session_id\" placeholder=\"Your session ID...\" autocomplete=\"off\" required spellcheck=\"false\" style=\"background:#000;font-family:inherit;font-size:0.857rem;color:#f9f9fb;border:1px solid #24252d;border-radius:2px;line-height:1.6;outline:none;text-overflow:ellipsis;width:95%;height:auto;margin:10px 0 0 0;padding:0 10px;\" />
65-
<input type=\"hidden\" id=\"callback_url\" name=\"callback_url\" value=\"$cb\" />
66-
<input type=\"submit\" value=\"Submit\" style=\"margin-top:10px;\" />
67-
</div>
68-
</div>
69-
</div>
70-
</form>
71-
</body>
72-
</html>").replace("$alias", alias).replace("$nid", nid).replace("$cb", &cb))
44+
Html(oauth_page_html(alias.to_owned(), nid.to_owned(), cb, None))
7345
}
7446

7547
#[derive(Debug, Serialize, Deserialize)]
@@ -83,16 +55,80 @@ struct OauthSubmitParams {
8355

8456
/// Submit oauth page and redirect back to original
8557
/// `POST /oauth`
86-
async fn oauth_submit_handler(Form(form): Form<OauthSubmitParams>) -> impl IntoResponse {
87-
let mut redir_url = form.callback_url;
88-
if redir_url.contains("?") {
89-
redir_url.push('^');
58+
async fn oauth_submit_handler(
59+
State(ctx): State<Context>,
60+
Form(form): Form<OauthSubmitParams>,
61+
) -> impl IntoResponse {
62+
let res = crate::api::auth::validate(&ctx, &form.session_id).await;
63+
if res.is_err() {
64+
let alias = &ctx.profile.config.node.alias.to_string();
65+
let nid = &ctx.profile.public_key.to_string();
66+
Html(oauth_page_html(
67+
alias.to_owned(),
68+
nid.to_owned(),
69+
form.callback_url,
70+
Some("The Session ID you entered was invalid".to_string()),
71+
))
9072
} else {
91-
redir_url.push('?');
73+
Html(oauth_auto_submit_form(form.callback_url, form.session_id))
9274
}
93-
redir_url.push_str("session_id=");
94-
redir_url.push_str(&form.session_id);
95-
Redirect::temporary(&redir_url)
75+
}
76+
77+
fn oauth_page_html(alias: String, nid: String, cb: String, err: Option<String>) -> String {
78+
let err_msg = err.unwrap_or("".to_string());
79+
format!(
80+
r#"
81+
<!DOCTYPE html><html lang="en">
82+
<head>
83+
<title>{alias} Radicle HTTP API OAuth Page</title>
84+
</head>
85+
<body style="background-color:#0a0d10;margin:0;">
86+
<form method="POST">
87+
<div style="background-image:url('https://app.radicle.xyz/images/default-seed-header.png');border-bottom:1px solid;height:18rem;background-position:center;background-size:cover;"></div>
88+
<div style="max-width:500px;margin-left:auto;margin-right:auto;margin-top:25px;">
89+
<div style="/*height:12rem;*/border:1px solid #2e2f38;border-radius:4px;background-color:#14151a;padding:.75rem 1rem;position:relative;display:flex;flex-direction:column;justify-content:space-between;overflow:hidden;">
90+
<div class="title" style="display:flex;flex-direction:column;gap:.125rem;position:relative;">
91+
<div class="headline-and-badges" style="display:flex;justify-content:space-between;gap:.5rem;">
92+
<h4 style="margin:0;color:rgb(249,249,251);line-clamp:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">Radicle HTTP API</h4>
93+
<img width="24" height="24" class="logo" alt="Radicle logo" src="https://app.radicle.xyz/radicle.svg" style="margin:0px 0.5rem;">
94+
</div>
95+
<p class="txt-small" style="margin:0;color:#9b9bb1;">Running on {alias}</p>
96+
<p class="txt-small" style="margin:0;color:#9b9bb1;">{nid}</p>
97+
</div>
98+
<div class="err" style="margin:25px 0 0 0;color:#Fb9b91;">
99+
{err_msg}
100+
</div>
101+
<div class="wrapper" style="display:flex;flex-direction:column;margin:25px 0 0 0;position:relative;flex:1;align-items:start;height:2.5rem;">
102+
<label for="session_id" class="txt-small" style="margin:0;color:#9b9bb1;">Fill in your session ID</label>
103+
<input type="text" id="session_id" name="session_id" placeholder="Your session ID..." autocomplete="off" required spellcheck="false" style="background:#000;font-family:inherit;font-size:0.857rem;color:#f9f9fb;border:1px solid #24252d;border-radius:2px;line-height:1.6;outline:none;text-overflow:ellipsis;width:95%;height:auto;margin:10px 0 0 0;padding:0 10px;">
104+
<input type="hidden" id="callback_url" name="callback_url" value="{cb}" />
105+
<input type="submit" value="Submit" style="margin-top:10px;">
106+
</div>
107+
</div>
108+
</div>
109+
</form>
110+
</body>
111+
</html>
112+
"#,
113+
)
114+
}
115+
116+
fn oauth_auto_submit_form(cb: String, session_id: String) -> String {
117+
format!(
118+
r#"
119+
<html>
120+
<head>
121+
<title>Radicle HTTP API OAuth</title>
122+
<meta http-equiv="refresh" content="0; URL=#" />
123+
</head>
124+
<body onload="document.frm.submit()">
125+
<form name="frm" action="{cb}" method="POST" style="display:none;">
126+
<input type="hidden" name="code" value="{session_id}" />
127+
</form>
128+
</body>
129+
</html>
130+
"#,
131+
)
96132
}
97133

98134
#[cfg(test)]

0 commit comments

Comments
 (0)