mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2024-12-29 08:33:23 -05:00
Fix scope
and refresh_token
for API key logins
API key logins use a scope of `api`, not `api offline_access`. Since `offline_access` is not requested, no `refresh_token` is returned either.
This commit is contained in:
parent
69ee4a70b4
commit
8f7900759f
@ -61,13 +61,15 @@ fn _refresh_login(data: ConnectData, conn: DbConn) -> JsonResult {
|
|||||||
// Get device by refresh token
|
// Get device by refresh token
|
||||||
let mut device = Device::find_by_refresh_token(&token, &conn).map_res("Invalid refresh token")?;
|
let mut device = Device::find_by_refresh_token(&token, &conn).map_res("Invalid refresh token")?;
|
||||||
|
|
||||||
// COMMON
|
let scope = "api offline_access";
|
||||||
|
let scope_vec = vec!["api".into(), "offline_access".into()];
|
||||||
|
|
||||||
|
// Common
|
||||||
let user = User::find_by_uuid(&device.user_uuid, &conn).unwrap();
|
let user = User::find_by_uuid(&device.user_uuid, &conn).unwrap();
|
||||||
let orgs = UserOrganization::find_confirmed_by_user(&user.uuid, &conn);
|
let orgs = UserOrganization::find_confirmed_by_user(&user.uuid, &conn);
|
||||||
|
let (access_token, expires_in) = device.refresh_tokens(&user, orgs, scope_vec);
|
||||||
let (access_token, expires_in) = device.refresh_tokens(&user, orgs);
|
|
||||||
|
|
||||||
device.save(&conn)?;
|
device.save(&conn)?;
|
||||||
|
|
||||||
Ok(Json(json!({
|
Ok(Json(json!({
|
||||||
"access_token": access_token,
|
"access_token": access_token,
|
||||||
"expires_in": expires_in,
|
"expires_in": expires_in,
|
||||||
@ -79,7 +81,7 @@ fn _refresh_login(data: ConnectData, conn: DbConn) -> JsonResult {
|
|||||||
"Kdf": user.client_kdf_type,
|
"Kdf": user.client_kdf_type,
|
||||||
"KdfIterations": user.client_kdf_iter,
|
"KdfIterations": user.client_kdf_iter,
|
||||||
"ResetMasterPassword": false, // TODO: according to official server seems something like: user.password_hash.is_empty(), but would need testing
|
"ResetMasterPassword": false, // TODO: according to official server seems something like: user.password_hash.is_empty(), but would need testing
|
||||||
"scope": "api offline_access",
|
"scope": scope,
|
||||||
"unofficialServer": true,
|
"unofficialServer": true,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
@ -90,6 +92,7 @@ fn _password_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> JsonResult
|
|||||||
if scope != "api offline_access" {
|
if scope != "api offline_access" {
|
||||||
err!("Scope not supported")
|
err!("Scope not supported")
|
||||||
}
|
}
|
||||||
|
let scope_vec = vec!["api".into(), "offline_access".into()];
|
||||||
|
|
||||||
// Ratelimit the login
|
// Ratelimit the login
|
||||||
crate::ratelimit::check_limit_login(&ip.ip)?;
|
crate::ratelimit::check_limit_login(&ip.ip)?;
|
||||||
@ -157,8 +160,7 @@ fn _password_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> JsonResult
|
|||||||
|
|
||||||
// Common
|
// Common
|
||||||
let orgs = UserOrganization::find_confirmed_by_user(&user.uuid, &conn);
|
let orgs = UserOrganization::find_confirmed_by_user(&user.uuid, &conn);
|
||||||
|
let (access_token, expires_in) = device.refresh_tokens(&user, orgs, scope_vec);
|
||||||
let (access_token, expires_in) = device.refresh_tokens(&user, orgs);
|
|
||||||
device.save(&conn)?;
|
device.save(&conn)?;
|
||||||
|
|
||||||
let mut result = json!({
|
let mut result = json!({
|
||||||
@ -173,7 +175,7 @@ fn _password_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> JsonResult
|
|||||||
"Kdf": user.client_kdf_type,
|
"Kdf": user.client_kdf_type,
|
||||||
"KdfIterations": user.client_kdf_iter,
|
"KdfIterations": user.client_kdf_iter,
|
||||||
"ResetMasterPassword": false,// TODO: Same as above
|
"ResetMasterPassword": false,// TODO: Same as above
|
||||||
"scope": "api offline_access",
|
"scope": scope,
|
||||||
"unofficialServer": true,
|
"unofficialServer": true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -191,6 +193,7 @@ fn _api_key_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> JsonResult
|
|||||||
if scope != "api" {
|
if scope != "api" {
|
||||||
err!("Scope not supported")
|
err!("Scope not supported")
|
||||||
}
|
}
|
||||||
|
let scope_vec = vec!["api".into()];
|
||||||
|
|
||||||
// Ratelimit the login
|
// Ratelimit the login
|
||||||
crate::ratelimit::check_limit_login(&ip.ip)?;
|
crate::ratelimit::check_limit_login(&ip.ip)?;
|
||||||
@ -232,24 +235,24 @@ fn _api_key_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> JsonResult
|
|||||||
|
|
||||||
// Common
|
// Common
|
||||||
let orgs = UserOrganization::find_confirmed_by_user(&user.uuid, &conn);
|
let orgs = UserOrganization::find_confirmed_by_user(&user.uuid, &conn);
|
||||||
|
let (access_token, expires_in) = device.refresh_tokens(&user, orgs, scope_vec);
|
||||||
let (access_token, expires_in) = device.refresh_tokens(&user, orgs);
|
|
||||||
device.save(&conn)?;
|
device.save(&conn)?;
|
||||||
|
|
||||||
info!("User {} logged in successfully via API key. IP: {}", user.email, ip.ip);
|
info!("User {} logged in successfully via API key. IP: {}", user.email, ip.ip);
|
||||||
|
|
||||||
|
// Note: No refresh_token is returned. The CLI just repeats the
|
||||||
|
// client_credentials login flow when the existing token expires.
|
||||||
Ok(Json(json!({
|
Ok(Json(json!({
|
||||||
"access_token": access_token,
|
"access_token": access_token,
|
||||||
"expires_in": expires_in,
|
"expires_in": expires_in,
|
||||||
"token_type": "Bearer",
|
"token_type": "Bearer",
|
||||||
"refresh_token": device.refresh_token,
|
|
||||||
"Key": user.akey,
|
"Key": user.akey,
|
||||||
"PrivateKey": user.private_key,
|
"PrivateKey": user.private_key,
|
||||||
|
|
||||||
"Kdf": user.client_kdf_type,
|
"Kdf": user.client_kdf_type,
|
||||||
"KdfIterations": user.client_kdf_iter,
|
"KdfIterations": user.client_kdf_iter,
|
||||||
"ResetMasterPassword": false, // TODO: Same as above
|
"ResetMasterPassword": false, // TODO: Same as above
|
||||||
"scope": "api",
|
"scope": scope,
|
||||||
"unofficialServer": true,
|
"unofficialServer": true,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,12 @@ impl Device {
|
|||||||
self.twofactor_remember = None;
|
self.twofactor_remember = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refresh_tokens(&mut self, user: &super::User, orgs: Vec<super::UserOrganization>) -> (String, i64) {
|
pub fn refresh_tokens(
|
||||||
|
&mut self,
|
||||||
|
user: &super::User,
|
||||||
|
orgs: Vec<super::UserOrganization>,
|
||||||
|
scope: Vec<String>,
|
||||||
|
) -> (String, i64) {
|
||||||
// If there is no refresh token, we create one
|
// If there is no refresh token, we create one
|
||||||
if self.refresh_token.is_empty() {
|
if self.refresh_token.is_empty() {
|
||||||
use crate::crypto;
|
use crate::crypto;
|
||||||
@ -98,7 +103,7 @@ impl Device {
|
|||||||
|
|
||||||
sstamp: user.security_stamp.to_string(),
|
sstamp: user.security_stamp.to_string(),
|
||||||
device: self.uuid.to_string(),
|
device: self.uuid.to_string(),
|
||||||
scope: vec!["api".into(), "offline_access".into()],
|
scope,
|
||||||
amr: vec!["Application".into()],
|
amr: vec!["Application".into()],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user