#[macro_use]
extern crate rouille;
extern crate oxide_auth;
extern crate url;
#[path = "support/rouille.rs"]
mod support;
use std::sync::Mutex;
use std::thread;
use oxide_auth::endpoint::{AuthorizationFlow, AccessTokenFlow, OwnerConsent, PreGrant, RefreshFlow, ResourceFlow};
use oxide_auth::frontends::rouille::{FnSolicitor, GenericEndpoint};
use oxide_auth::primitives::prelude::*;
use rouille::{Request, Response, ResponseBody, Server};
pub fn main() {
let registrar = {
let mut clients = ClientMap::new();
let client = Client::public("LocalClient", "http://localhost:8021/endpoint".parse().unwrap(), "default".parse().unwrap()); clients.register_client(client);
clients
};
let authorizer = AuthMap::new(RandomGenerator::new(16));
let issuer = TokenMap::new(RandomGenerator::new(32));
let endpoint = Mutex::new(GenericEndpoint {
registrar,
authorizer,
issuer,
solicitor: FnSolicitor(solicitor),
scopes: vec!["default".parse::<Scope>().unwrap()],
response: Response::empty_404,
});
let server = Server::new(("localhost", 8020), move |request| {
router!(request,
(GET) ["/"] => {
let mut locked = endpoint.lock().unwrap();
if let Err(err) = ResourceFlow::prepare(&mut *locked)
.expect("Can not fail")
.execute(request)
{ let mut response = err.unwrap_or_else(|_| Response::empty_400());
let text = "<html>
This page should be accessed via an oauth token from the client in the example. Click
<a href=\"http://localhost:8020/authorize?response_type=code&client_id=LocalClient\">
here</a> to begin the authorization process.
</html>
";
response.data = ResponseBody::from_string(text);
response.with_unique_header("Content-Type", "text/html; charset=utf8")
} else { Response::text("Hello world!")
}
},
(GET) ["/authorize"] => {
let mut locked = endpoint.lock().unwrap();
AuthorizationFlow::prepare(&mut *locked)
.expect("Can not fail")
.execute(request)
.unwrap_or_else(|_| Response::empty_400())
},
(POST) ["/authorize"] => {
let mut locked = endpoint.lock().unwrap();
AuthorizationFlow::prepare(&mut *locked)
.expect("Can not fail")
.execute(request)
.unwrap_or_else(|_| Response::empty_400())
},
(POST) ["/token"] => {
let mut locked = endpoint.lock().unwrap();
AccessTokenFlow::prepare(&mut *locked)
.expect("Can not fail")
.execute(request)
.unwrap_or_else(|_| Response::empty_400())
},
(POST) ["/refresh"] => {
let mut locked = endpoint.lock().unwrap();
RefreshFlow::prepare(&mut *locked)
.expect("Can not fail")
.execute(request)
.unwrap_or_else(|_| Response::empty_400())
},
_ => Response::empty_404()
)
});
let join = thread::spawn(move ||
server.expect("Failed to start server")
.run()
);
let client = thread::spawn(||
Server::new(("localhost", 8021), support::dummy_client())
.expect("Failed to start client")
.run()
);
support::open_in_browser();
join.join().expect("Failed to run");
client.join().expect("Failed to run client");
}
fn solicitor(request: &mut &Request, grant: &PreGrant) -> OwnerConsent<Response> {
if request.method() == "GET" {
let text = support::consent_page_html("/authorize".into(), grant);
let response = Response::html(text);
OwnerConsent::InProgress(response)
} else if request.method() == "POST" {
if let Some(_) = request.get_param("allow") {
OwnerConsent::Authorized("dummy user".to_string())
} else {
OwnerConsent::Denied
}
} else {
unreachable!("Authorization only mounted on GET and POST")
}
}