|
|
|
@ -8,6 +8,13 @@ use ruma::{ |
|
|
|
}, |
|
|
|
}, |
|
|
|
UserId, |
|
|
|
UserId, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
use serde::Deserialize; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)] |
|
|
|
|
|
|
|
struct Claims { |
|
|
|
|
|
|
|
sub: String, |
|
|
|
|
|
|
|
exp: usize, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "conduit_bin")] |
|
|
|
#[cfg(feature = "conduit_bin")] |
|
|
|
use rocket::{get, post}; |
|
|
|
use rocket::{get, post}; |
|
|
|
@ -40,39 +47,61 @@ pub async fn login_route( |
|
|
|
body: Ruma<login::Request<'_>>, |
|
|
|
body: Ruma<login::Request<'_>>, |
|
|
|
) -> ConduitResult<login::Response> { |
|
|
|
) -> ConduitResult<login::Response> { |
|
|
|
// Validate login method
|
|
|
|
// Validate login method
|
|
|
|
let user_id = |
|
|
|
|
|
|
|
// TODO: Other login methods
|
|
|
|
// TODO: Other login methods
|
|
|
|
if let (login::IncomingUserInfo::MatrixId(username), login::IncomingLoginInfo::Password { password }) = |
|
|
|
let user_id = match &body.login_info { |
|
|
|
(&body.user, &body.login_info) |
|
|
|
login::IncomingLoginInfo::Password { password } => { |
|
|
|
{ |
|
|
|
let username = if let login::IncomingUserInfo::MatrixId(matrix_id) = &body.user { |
|
|
|
let user_id = UserId::parse_with_server_name(username.to_string(), db.globals.server_name()) |
|
|
|
matrix_id |
|
|
|
.map_err(|_| Error::BadRequest( |
|
|
|
} else { |
|
|
|
ErrorKind::InvalidUsername, |
|
|
|
return Err(Error::BadRequest(ErrorKind::Forbidden, "Bad login type.")); |
|
|
|
"Username is invalid." |
|
|
|
}; |
|
|
|
))?; |
|
|
|
let user_id = |
|
|
|
let hash = db.users.password_hash(&user_id)? |
|
|
|
UserId::parse_with_server_name(username.to_owned(), db.globals.server_name()) |
|
|
|
.ok_or(Error::BadRequest( |
|
|
|
.map_err(|_| { |
|
|
|
|
|
|
|
Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid.") |
|
|
|
|
|
|
|
})?; |
|
|
|
|
|
|
|
let hash = db.users.password_hash(&user_id)?.ok_or(Error::BadRequest( |
|
|
|
ErrorKind::Forbidden, |
|
|
|
ErrorKind::Forbidden, |
|
|
|
"Wrong username or password." |
|
|
|
"Wrong username or password.", |
|
|
|
))?; |
|
|
|
))?; |
|
|
|
|
|
|
|
|
|
|
|
if hash.is_empty() { |
|
|
|
if hash.is_empty() { |
|
|
|
return Err(Error::BadRequest( |
|
|
|
return Err(Error::BadRequest( |
|
|
|
ErrorKind::UserDeactivated, |
|
|
|
ErrorKind::UserDeactivated, |
|
|
|
"The user has been deactivated" |
|
|
|
"The user has been deactivated", |
|
|
|
)); |
|
|
|
)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let hash_matches = |
|
|
|
let hash_matches = argon2::verify_encoded(&hash, password.as_bytes()).unwrap_or(false); |
|
|
|
argon2::verify_encoded(&hash, password.as_bytes()).unwrap_or(false); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !hash_matches { |
|
|
|
if !hash_matches { |
|
|
|
return Err(Error::BadRequest(ErrorKind::Forbidden, "Wrong username or password.")); |
|
|
|
return Err(Error::BadRequest( |
|
|
|
|
|
|
|
ErrorKind::Forbidden, |
|
|
|
|
|
|
|
"Wrong username or password.", |
|
|
|
|
|
|
|
)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
user_id |
|
|
|
user_id |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
login::IncomingLoginInfo::Token { token } => { |
|
|
|
|
|
|
|
if let Some(jwt_decoding_key) = db.globals.jwt_decoding_key() { |
|
|
|
|
|
|
|
let token = jsonwebtoken::decode::<Claims>( |
|
|
|
|
|
|
|
&token, |
|
|
|
|
|
|
|
&jwt_decoding_key, |
|
|
|
|
|
|
|
&jsonwebtoken::Validation::default(), |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
.map_err(|_| Error::BadRequest(ErrorKind::InvalidUsername, "Token is invalid."))?; |
|
|
|
|
|
|
|
let username = token.claims.sub; |
|
|
|
|
|
|
|
UserId::parse_with_server_name(username, db.globals.server_name()).map_err( |
|
|
|
|
|
|
|
|_| Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid."), |
|
|
|
|
|
|
|
)? |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return Err(Error::BadRequest(ErrorKind::Forbidden, "Bad login type.")); |
|
|
|
return Err(Error::BadRequest( |
|
|
|
|
|
|
|
ErrorKind::Unknown, |
|
|
|
|
|
|
|
"Token login is not supported (server has no jwt decoding key).", |
|
|
|
|
|
|
|
)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Generate new device id if the user didn't specify one
|
|
|
|
// Generate new device id if the user didn't specify one
|
|
|
|
|