forked from meli/meli
1
Fork 0

melib/jmap: Implement Bearer token authentication

Fastmail now uses an API token in a http header for authentication.

This can be used either as a server_password or provided by a
server_password_command like oauth2.
duesee/experiment/use_imap_codec
Manos Pitsidianakis 2023-04-06 14:56:52 +03:00
parent d9c07def0f
commit d679a74450
Signed by: Manos Pitsidianakis
GPG Key ID: 7729C7707F7E09D0
2 changed files with 34 additions and 7 deletions

View File

@ -89,6 +89,7 @@ pub struct JmapServerConf {
pub server_url: String,
pub server_username: String,
pub server_password: String,
pub use_token: bool,
pub danger_accept_invalid_certs: bool,
pub timeout: Option<Duration>,
}
@ -123,10 +124,22 @@ macro_rules! get_conf_val {
impl JmapServerConf {
pub fn new(s: &AccountSettings) -> Result<Self> {
let use_token: bool = get_conf_val!(s["use_token"], false)?;
if use_token
&& !(s.extra.contains_key("server_password_command")
^ s.extra.contains_key("server_password"))
{
return Err(Error::new(format!(
"({}) `use_token` use requires either the `server_password_command` set with a command that returns an Bearer token of your account, or `server_password` with the API Bearer token as a string. Consult documentation for guidance.",
s.name,
)));
}
Ok(JmapServerConf {
server_url: get_conf_val!(s["server_url"])?.to_string(),
server_username: get_conf_val!(s["server_username"])?.to_string(),
server_password: s.server_password()?,
use_token,
danger_accept_invalid_certs: get_conf_val!(s["danger_accept_invalid_certs"], false)?,
timeout: get_conf_val!(s["timeout"], 16_u64).map(|t| {
if t == 0 {
@ -919,6 +932,7 @@ impl JmapType {
get_conf_val!(s["server_url"])?;
get_conf_val!(s["server_username"])?;
get_conf_val!(s["use_token"], false)?;
// either of these two needed
get_conf_val!(s["server_password"]).or(get_conf_val!(s["server_password_command"]))?;

View File

@ -36,13 +36,26 @@ impl JmapConnection {
pub fn new(server_conf: &JmapServerConf, store: Arc<Store>) -> Result<Self> {
let client = HttpClient::builder()
.timeout(std::time::Duration::from_secs(10))
.redirect_policy(RedirectPolicy::Limit(10))
.authentication(isahc::auth::Authentication::basic())
.credentials(isahc::auth::Credentials::new(
&server_conf.server_username,
&server_conf.server_password,
))
.build()?;
.connection_cache_size(8)
.connection_cache_ttl(std::time::Duration::from_secs(30 * 60))
.default_header("Content-Type", "application/json")
.redirect_policy(RedirectPolicy::Limit(10));
let client = if server_conf.use_token {
client
.authentication(isahc::auth::Authentication::none())
.default_header(
"Authorization",
format!("Bearer {}", &server_conf.server_password),
)
} else {
client
.authentication(isahc::auth::Authentication::basic())
.credentials(isahc::auth::Credentials::new(
&server_conf.server_username,
&server_conf.server_password,
))
};
let client = client.build()?;
let server_conf = server_conf.clone();
Ok(JmapConnection {
session: Arc::new(Mutex::new(Default::default())),