Use custom protocol based page to show tokens

This commit is contained in:
Adrian Kumpf
2021-09-16 22:57:26 +02:00
parent fdc6600f17
commit e41237faf9
4 changed files with 61 additions and 38 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ reqwest = { version = "0.11.4" , default-features = false, features = ["json", "
serde = "1.0.130"
serde_json = "1.0.67"
simple_logger = { version = "1.13.0", default-features = false, features = ["colors", "stderr"] }
wry = { version = "0.12", default-features = false, features = [] }
wry = { version = "0.12", default-features = false, features = ["protocol"] }
[profile.release]
lto = true
+2 -1
View File
@@ -83,7 +83,8 @@ impl Client {
assert_eq!(&state, csrf_token.secret());
}
pub fn retrieve_tokens(&mut self, code: AuthorizationCode) -> Tokens {
pub fn retrieve_tokens(&mut self, code: &str) -> Tokens {
let code = AuthorizationCode::new(code.to_string());
let pkce_verifier = self.pkce_verifier.take().unwrap();
let tokens = self
+40 -36
View File
@@ -4,15 +4,15 @@ use std::collections::HashMap;
use std::sync::mpsc::channel;
use std::thread;
use log::{info, LevelFilter};
use log::{debug, info, LevelFilter};
use simple_logger::SimpleLogger;
use oauth2::url::Url;
use oauth2::AuthorizationCode;
use wry::application::event::{Event, WindowEvent};
use wry::application::event_loop::{ControlFlow, EventLoop};
use wry::application::window::{Window, WindowBuilder};
use wry::http::ResponseBuilder;
use wry::webview::{RpcRequest, WebViewBuilder};
use wry::Value;
@@ -66,6 +66,7 @@ fn main() -> wry::Result<()> {
while let Ok(url) = rx.recv() {
if !auth::is_redirect_url(&url) || tokens_retrieved {
debug!("URL changed: {}", &url);
continue;
}
@@ -76,7 +77,6 @@ fn main() -> wry::Result<()> {
client.verify_csrf_state(state.to_string());
let code = AuthorizationCode::new(code.to_string());
let tokens = client.retrieve_tokens(code);
tokens_retrieved = true;
@@ -88,47 +88,51 @@ fn main() -> wry::Result<()> {
let webview = WebViewBuilder::new(window)
.unwrap()
.with_initialization_script(INITIALIZATION_SCRIPT)
.with_custom_protocol("wry".into(), move |request| {
let url: Url = request.uri().parse()?;
match url.domain() {
Some("index.html") => {
let query = url.query_pairs().collect::<HashMap<_, _>>();
let (access, refresh) =
(query.get("access").unwrap(), query.get("refresh").unwrap());
let content = include_str!("../views/index.html")
.replace("{access_token}", access)
.replace("{refresh_token}", refresh);
ResponseBuilder::new()
.mimetype("text/html")
.body(content.as_bytes().to_vec())
}
_ => unimplemented!(),
}
})
.with_url(auth_url.as_str())?
.with_rpc_handler(handler)
.build()?;
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
Event::UserEvent(CustomEvent::Tokens(tokens)) => {
info!("Received tokens: {:?}", tokens);
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
Event::UserEvent(CustomEvent::Tokens(tokens)) => {
info!("Received tokens: {:#?}", tokens);
webview.evaluate_script(&r#"
(function () {
var body = `
<!DOCTYPE html>
<html lang="en">
<body>
<form action='#' method='POST'>
<label for='access_token'>Access Token:</label><br />
<input type='text' id='access_token' name='access_token' value='{access_token}' /><br />
<label for='refresh_token'>Refresh Token:</label><br />
<input type='text' id='refresh_token' name='refresh_token' value='{refresh_token}' /><br /><br />
</form>
</body>
</html>
`;
let url = format!(
"location.replace('wry://index.html?access={}&refresh={}');",
tokens.access, tokens.refresh
);
document.open();
document.write(body);
document.close();
})();
"#
.replace("{access_token}", &tokens.access)
.replace("{refresh_token}", &tokens.refresh)
).unwrap();
}
_ => (),
webview.evaluate_script(&url).unwrap();
}
_ => (),
}
});
}
@@ -136,5 +140,5 @@ fn main() -> wry::Result<()> {
fn parse_url(params: Value) -> Url {
let args = serde_json::from_value::<Vec<String>>(params).unwrap();
let url = args.first().unwrap();
Url::parse(&url).expect("Invalid URL")
Url::parse(url).expect("Invalid URL")
}
+18
View File
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<h1>Tokens generated!</h1>
<form>
<label for="access_token">Access Token:</label><br />
<input type="text" name="access_token" value="{access_token}" />
<label for="refresh_token">Refresh Token:</label><br />
<input type="text" name="refresh_token" value="{refresh_token}" />
</form>
</body>
</html>