mirror of
https://github.com/adriankumpf/tesla_auth.git
synced 2026-02-27 09:54:03 +08:00
Use custom protocol based page to show tokens
This commit is contained in:
+1
-1
@@ -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
@@ -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
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user