1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#![allow(non_snake_case)]
use std::io::{BufRead, BufReader, Write};
use std::net::TcpListener;
pub use oauth2::Config;
use rand::Rng;
use url::Url;
use webbrowser;
pub struct Authenticator {
oauthConfig: oauth2::Config,
port: u16,
}
impl Authenticator {
pub fn new(oauthConfig: oauth2::Config) -> Self {
Authenticator {
oauthConfig: oauthConfig
.set_redirect_url("http://localhost:14565/oauth/callback".to_string()),
port: 14565,
}
}
pub fn set_port(mut self, port: u16) -> Self {
self.port = port;
self
}
pub fn set_redirect_url(mut self, redirect_url: String) -> Self {
self.oauthConfig = self.oauthConfig.set_redirect_url::<&str>(&redirect_url);
self
}
pub fn authenticate(mut self) -> Result<(), Box<std::error::Error>> {
self.oauthConfig = self
.oauthConfig
.set_state(rand::thread_rng().gen::<u16>().to_string());
let authorize_url = self.oauthConfig.authorize_url();
if webbrowser::open(&authorize_url.to_string()).is_ok() {
println!("{}", &authorize_url.to_string())
}
let mut code = String::new();
let listener = TcpListener::bind(format!("127.0.0.1:{}", self.port)).unwrap();
for stream in listener.incoming() {
match stream {
Ok(mut stream) => {
{
let mut reader = BufReader::new(&stream);
let mut request_line = String::new();
reader.read_line(&mut request_line).unwrap();
let redirect_url = request_line.split_whitespace().nth(1).unwrap();
let url =
Url::parse(&("http://localhost".to_string() + redirect_url)).unwrap();
let code_pair = url
.query_pairs()
.find(|pair| {
let &(ref key, _) = pair;
key == "code"
})
.unwrap();
let (_, value) = code_pair;
code = value.into_owned();
}
let message = "Go back to your terminal :)";
let response = format!(
"HTTP/1.1 200 OK\r\ncontent-length: {}\r\n\r\n{}",
message.len(),
message
);
stream.write_all(response.as_bytes()).unwrap();
break;
}
Err(e) => println!("{}", e),
}
}
let token = self.oauthConfig.exchange_code(code);
println!("Google returned the following token:\n{:?}\n", token);
Ok(())
}
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}