diff options
author | Jesse Luehrs <doy@tozt.net> | 2020-04-12 03:44:48 -0400 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2020-04-12 03:44:48 -0400 |
commit | 201d2d40cac8760fb69b9282ba2a4f9f7ec82d47 (patch) | |
tree | 0c1cfd3986e28e7be2b73cdcba11e9ebbbb7c2fa /src/api.rs | |
parent | bcae263e4e888274f399a75ec5b171ee25edf894 (diff) | |
download | rbw-201d2d40cac8760fb69b9282ba2a4f9f7ec82d47.tar.gz rbw-201d2d40cac8760fb69b9282ba2a4f9f7ec82d47.zip |
implement refresh token handling
Diffstat (limited to 'src/api.rs')
-rw-r--r-- | src/api.rs | 60 |
1 files changed, 54 insertions, 6 deletions
@@ -14,7 +14,7 @@ struct PreloginRes { } #[derive(serde::Serialize, Debug)] -struct ConnectReq { +struct ConnectPasswordReq { grant_type: String, username: String, password: String, @@ -30,8 +30,25 @@ struct ConnectReq { device_push_token: String, } +#[derive(serde::Serialize, Debug)] +struct ConnectRefreshTokenReq { + grant_type: String, + client_id: String, + refresh_token: String, +} + +#[derive(serde::Deserialize, Debug)] +struct ConnectPasswordRes { + access_token: String, + expires_in: u32, + token_type: String, + refresh_token: String, + #[serde(rename = "Key")] + key: String, +} + #[derive(serde::Deserialize, Debug)] -struct ConnectRes { +struct ConnectRefreshTokenRes { access_token: String, expires_in: u32, token_type: String, @@ -105,7 +122,7 @@ impl Client { email: &str, master_password_hash: &crate::locked::PasswordHash, ) -> Result<(String, String, String)> { - let connect_req = ConnectReq { + let connect_req = ConnectPasswordReq { grant_type: "password".to_string(), username: email.to_string(), password: base64::encode(master_password_hash.hash()), @@ -125,7 +142,7 @@ impl Client { .send() .await .context(crate::error::Reqwest)?; - let connect_res: ConnectRes = + let connect_res: ConnectPasswordRes = res.json().await.context(crate::error::Reqwest)?; Ok(( connect_res.access_token, @@ -145,9 +162,40 @@ impl Client { .send() .await .context(crate::error::Reqwest)?; - let sync_res: SyncRes = + match res.status() { + reqwest::StatusCode::OK => { + let sync_res: SyncRes = + res.json().await.context(crate::error::Reqwest)?; + Ok((sync_res.profile.key, sync_res.ciphers)) + } + reqwest::StatusCode::UNAUTHORIZED => { + Err(Error::RequestUnauthorized) + } + _ => Err(Error::RequestFailed { + status: res.status().as_u16(), + }), + } + } + + pub async fn exchange_refresh_token( + &self, + refresh_token: &str, + ) -> Result<String> { + let connect_req = ConnectRefreshTokenReq { + grant_type: "refresh_token".to_string(), + client_id: "desktop".to_string(), + refresh_token: refresh_token.to_string(), + }; + let client = reqwest::Client::new(); + let res = client + .post(&self.identity_url("/connect/token")) + .form(&connect_req) + .send() + .await + .context(crate::error::Reqwest)?; + let connect_res: ConnectRefreshTokenRes = res.json().await.context(crate::error::Reqwest)?; - Ok((sync_res.profile.key, sync_res.ciphers)) + Ok(connect_res.access_token) } fn api_url(&self, path: &str) -> String { |