|
|
@ -7,6 +7,7 @@ use chrono::Duration;
|
|
|
|
use jsonwebtoken::{self, Algorithm, Header};
|
|
|
|
use jsonwebtoken::{self, Algorithm, Header};
|
|
|
|
use serde::ser::Serialize;
|
|
|
|
use serde::ser::Serialize;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use crate::error::{Error, MapResult};
|
|
|
|
use crate::CONFIG;
|
|
|
|
use crate::CONFIG;
|
|
|
|
|
|
|
|
|
|
|
|
const JWT_ALGORITHM: Algorithm = Algorithm::RS256;
|
|
|
|
const JWT_ALGORITHM: Algorithm = Algorithm::RS256;
|
|
|
@ -31,11 +32,11 @@ lazy_static! {
|
|
|
|
pub fn encode_jwt<T: Serialize>(claims: &T) -> String {
|
|
|
|
pub fn encode_jwt<T: Serialize>(claims: &T) -> String {
|
|
|
|
match jsonwebtoken::encode(&JWT_HEADER, claims, &PRIVATE_RSA_KEY) {
|
|
|
|
match jsonwebtoken::encode(&JWT_HEADER, claims, &PRIVATE_RSA_KEY) {
|
|
|
|
Ok(token) => token,
|
|
|
|
Ok(token) => token,
|
|
|
|
Err(e) => panic!("Error encoding jwt {}", e)
|
|
|
|
Err(e) => panic!("Error encoding jwt {}", e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn decode_jwt(token: &str) -> Result<JWTClaims, String> {
|
|
|
|
pub fn decode_jwt(token: &str) -> Result<JWTClaims, Error> {
|
|
|
|
let validation = jsonwebtoken::Validation {
|
|
|
|
let validation = jsonwebtoken::Validation {
|
|
|
|
leeway: 30, // 30 seconds
|
|
|
|
leeway: 30, // 30 seconds
|
|
|
|
validate_exp: true,
|
|
|
|
validate_exp: true,
|
|
|
@ -47,16 +48,12 @@ pub fn decode_jwt(token: &str) -> Result<JWTClaims, String> {
|
|
|
|
algorithms: vec![JWT_ALGORITHM],
|
|
|
|
algorithms: vec![JWT_ALGORITHM],
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
match jsonwebtoken::decode(token, &PUBLIC_RSA_KEY, &validation) {
|
|
|
|
jsonwebtoken::decode(token, &PUBLIC_RSA_KEY, &validation)
|
|
|
|
Ok(decoded) => Ok(decoded.claims),
|
|
|
|
.map(|d| d.claims)
|
|
|
|
Err(msg) => {
|
|
|
|
.map_res("Error decoding login JWT")
|
|
|
|
error!("Error validating jwt - {:#?}", msg);
|
|
|
|
|
|
|
|
Err(msg.to_string())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn decode_invite_jwt(token: &str) -> Result<InviteJWTClaims, String> {
|
|
|
|
pub fn decode_invite_jwt(token: &str) -> Result<InviteJWTClaims, Error> {
|
|
|
|
let validation = jsonwebtoken::Validation {
|
|
|
|
let validation = jsonwebtoken::Validation {
|
|
|
|
leeway: 30, // 30 seconds
|
|
|
|
leeway: 30, // 30 seconds
|
|
|
|
validate_exp: true,
|
|
|
|
validate_exp: true,
|
|
|
@ -68,13 +65,9 @@ pub fn decode_invite_jwt(token: &str) -> Result<InviteJWTClaims, String> {
|
|
|
|
algorithms: vec![JWT_ALGORITHM],
|
|
|
|
algorithms: vec![JWT_ALGORITHM],
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
match jsonwebtoken::decode(token, &PUBLIC_RSA_KEY, &validation) {
|
|
|
|
jsonwebtoken::decode(token, &PUBLIC_RSA_KEY, &validation)
|
|
|
|
Ok(decoded) => Ok(decoded.claims),
|
|
|
|
.map(|d| d.claims)
|
|
|
|
Err(msg) => {
|
|
|
|
.map_res("Error decoding invite JWT")
|
|
|
|
error!("Error validating jwt - {:#?}", msg);
|
|
|
|
|
|
|
|
Err(msg.to_string())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
@ -185,7 +178,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for Headers {
|
|
|
|
// Check JWT token is valid and get device and user from it
|
|
|
|
// Check JWT token is valid and get device and user from it
|
|
|
|
let claims: JWTClaims = match decode_jwt(access_token) {
|
|
|
|
let claims: JWTClaims = match decode_jwt(access_token) {
|
|
|
|
Ok(claims) => claims,
|
|
|
|
Ok(claims) => claims,
|
|
|
|
Err(_) => err_handler!("Invalid claim")
|
|
|
|
Err(_) => err_handler!("Invalid claim"),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let device_uuid = claims.device;
|
|
|
|
let device_uuid = claims.device;
|
|
|
@ -193,17 +186,17 @@ impl<'a, 'r> FromRequest<'a, 'r> for Headers {
|
|
|
|
|
|
|
|
|
|
|
|
let conn = match request.guard::<DbConn>() {
|
|
|
|
let conn = match request.guard::<DbConn>() {
|
|
|
|
Outcome::Success(conn) => conn,
|
|
|
|
Outcome::Success(conn) => conn,
|
|
|
|
_ => err_handler!("Error getting DB")
|
|
|
|
_ => err_handler!("Error getting DB"),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let device = match Device::find_by_uuid(&device_uuid, &conn) {
|
|
|
|
let device = match Device::find_by_uuid(&device_uuid, &conn) {
|
|
|
|
Some(device) => device,
|
|
|
|
Some(device) => device,
|
|
|
|
None => err_handler!("Invalid device id")
|
|
|
|
None => err_handler!("Invalid device id"),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let user = match User::find_by_uuid(&user_uuid, &conn) {
|
|
|
|
let user = match User::find_by_uuid(&user_uuid, &conn) {
|
|
|
|
Some(user) => user,
|
|
|
|
Some(user) => user,
|
|
|
|
None => err_handler!("Device has no user associated")
|
|
|
|
None => err_handler!("Device has no user associated"),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if user.security_stamp != claims.sstamp {
|
|
|
|
if user.security_stamp != claims.sstamp {
|
|
|
@ -248,7 +241,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for OrgHeaders {
|
|
|
|
None => err_handler!("The current user isn't member of the organization")
|
|
|
|
None => err_handler!("The current user isn't member of the organization")
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Outcome::Success(Self{
|
|
|
|
Outcome::Success(Self {
|
|
|
|
host: headers.host,
|
|
|
|
host: headers.host,
|
|
|
|
device: headers.device,
|
|
|
|
device: headers.device,
|
|
|
|
user: headers.user,
|
|
|
|
user: headers.user,
|
|
|
@ -260,7 +253,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for OrgHeaders {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
|
|
|
}
|
|
|
|
_ => err_handler!("Error getting the organization id"),
|
|
|
|
_ => err_handler!("Error getting the organization id"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|