aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-11-26 05:06:02 -0500
committerJesse Luehrs <doy@tozt.net>2019-11-26 05:10:01 -0500
commitff4ed4c72e9a841971563b98cd89839f59bc790c (patch)
treed33344909f50dc972189bb4810b6948b3e5c197c
parentea8beb985247aac4345ecefc8ec551f52f5f1a24 (diff)
downloadteleterm-ff4ed4c72e9a841971563b98cd89839f59bc790c.tar.gz
teleterm-ff4ed4c72e9a841971563b98cd89839f59bc790c.zip
pass oauth login urls along to the browser
-rw-r--r--teleterm/src/cmd/web.rs14
-rw-r--r--teleterm/src/protocol.rs20
-rw-r--r--teleterm/src/server.rs11
-rw-r--r--teleterm/src/web.rs55
4 files changed, 89 insertions, 11 deletions
diff --git a/teleterm/src/cmd/web.rs b/teleterm/src/cmd/web.rs
index e292288..637d1ff 100644
--- a/teleterm/src/cmd/web.rs
+++ b/teleterm/src/cmd/web.rs
@@ -4,6 +4,19 @@ use crate::prelude::*;
pub struct Config {
#[serde(default)]
web: crate::config::Web,
+
+ #[serde(
+ rename = "oauth",
+ deserialize_with = "crate::config::oauth_configs",
+ default
+ )]
+ oauth_configs: std::collections::HashMap<
+ crate::protocol::AuthType,
+ std::collections::HashMap<
+ crate::protocol::AuthClient,
+ crate::oauth::Config,
+ >,
+ >,
}
impl crate::config::Config for Config {
@@ -22,6 +35,7 @@ impl crate::config::Config for Config {
self.web.public_address.clone(),
self.web.server_address.clone(),
self.web.allowed_login_methods.clone(),
+ self.oauth_configs.clone(),
))
}
}
diff --git a/teleterm/src/protocol.rs b/teleterm/src/protocol.rs
index 130e52d..5633b8e 100644
--- a/teleterm/src/protocol.rs
+++ b/teleterm/src/protocol.rs
@@ -139,6 +139,26 @@ impl AuthType {
.take_while(std::result::Result::is_ok)
.map(std::result::Result::unwrap)
}
+
+ pub fn oauth_client(
+ self,
+ config: &crate::oauth::Config,
+ id: Option<&str>,
+ ) -> Option<Box<dyn crate::oauth::Oauth + Send>> {
+ match self {
+ Self::RecurseCenter => {
+ Some(Box::new(crate::oauth::RecurseCenter::new(
+ config.clone(),
+ &id.map_or_else(
+ || format!("{}", uuid::Uuid::new_v4()),
+ std::string::ToString::to_string,
+ ),
+ )))
+ }
+ ty if !ty.is_oauth() => None,
+ _ => unreachable!(),
+ }
+ }
}
impl std::convert::TryFrom<u8> for AuthType {
diff --git a/teleterm/src/server.rs b/teleterm/src/server.rs
index e36f3fc..5c846ed 100644
--- a/teleterm/src/server.rs
+++ b/teleterm/src/server.rs
@@ -399,12 +399,11 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
)?;
(
id.is_some(),
- Box::new(crate::oauth::RecurseCenter::new(
- config.clone(),
- &id.clone().unwrap_or_else(|| {
- format!("{}", uuid::Uuid::new_v4())
- }),
- )),
+ ty.oauth_client(
+ config,
+ id.as_ref().map(std::string::String::as_str),
+ )
+ .unwrap(),
)
}
_ => unreachable!(),
diff --git a/teleterm/src/web.rs b/teleterm/src/web.rs
index ed887a5..690d8a3 100644
--- a/teleterm/src/web.rs
+++ b/teleterm/src/web.rs
@@ -11,12 +11,19 @@ use crate::prelude::*;
use gotham::router::builder::{DefineSingleRoute as _, DrawRoutes as _};
use gotham::state::FromState as _;
-#[derive(Clone, serde::Serialize, gotham_derive::StateData)]
+#[derive(Clone, gotham_derive::StateData)]
struct Config {
server_address: (String, std::net::SocketAddr),
public_address: String,
allowed_login_methods:
std::collections::HashSet<crate::protocol::AuthType>,
+ oauth_configs: std::collections::HashMap<
+ crate::protocol::AuthType,
+ std::collections::HashMap<
+ crate::protocol::AuthClient,
+ crate::oauth::Config,
+ >,
+ >,
}
#[derive(Default, serde::Deserialize, serde::Serialize)]
@@ -30,18 +37,35 @@ struct WebConfig<'a> {
public_address: &'a str,
allowed_login_methods:
&'a std::collections::HashSet<crate::protocol::AuthType>,
+ oauth_login_urls:
+ std::collections::HashMap<crate::protocol::AuthType, String>,
}
impl<'a> WebConfig<'a> {
- fn new(config: &'a Config, session: &'a SessionData) -> Self {
- Self {
+ fn new(config: &'a Config, session: &'a SessionData) -> Result<Self> {
+ let mut oauth_login_urls = std::collections::HashMap::new();
+ for ty in crate::protocol::AuthType::iter().filter(|ty| {
+ ty.is_oauth() && config.allowed_login_methods.contains(ty)
+ }) {
+ let oauth_config = config
+ .oauth_configs
+ .get(&ty)
+ .and_then(|configs| {
+ configs.get(&crate::protocol::AuthClient::Web)
+ })
+ .context(crate::error::AuthTypeMissingOauthConfig { ty })?;
+ let client = ty.oauth_client(oauth_config, None).unwrap();
+ oauth_login_urls.insert(ty, client.generate_authorize_url());
+ }
+ Ok(Self {
username: session
.username
.as_ref()
.map(std::string::String::as_str),
public_address: &config.public_address,
allowed_login_methods: &config.allowed_login_methods,
- }
+ oauth_login_urls,
+ })
}
}
@@ -57,11 +81,19 @@ impl Server {
allowed_login_methods: std::collections::HashSet<
crate::protocol::AuthType,
>,
+ oauth_configs: std::collections::HashMap<
+ crate::protocol::AuthType,
+ std::collections::HashMap<
+ crate::protocol::AuthClient,
+ crate::oauth::Config,
+ >,
+ >,
) -> Self {
let data = Config {
server_address,
public_address,
allowed_login_methods,
+ oauth_configs,
};
Self {
server: Box::new(gotham::init_server(
@@ -146,7 +178,20 @@ fn serve_template(
let session = gotham::middleware::session::SessionData::<
crate::web::SessionData,
>::borrow_from(&state);
- let web_config = WebConfig::new(config, session);
+ let web_config = match WebConfig::new(config, session) {
+ Ok(config) => config,
+ Err(e) => {
+ // this means that the server configuration is incorrect, and
+ // there's nothing the client can do about it
+ return (
+ state,
+ hyper::Response::builder()
+ .status(hyper::StatusCode::INTERNAL_SERVER_ERROR)
+ .body(hyper::Body::from(format!("{}", e)))
+ .unwrap(),
+ );
+ }
+ };
let rendered = view::HANDLEBARS.render(name, &web_config).unwrap();
let response = hyper::Response::builder()
.header("Content-Type", content_type)