make invitation expiration time configurable

configure the number of hours after which organization invites,
emergency access invites, email verification emails and account deletion
requests expire (defaults to 5 days or 120 hours and must be atleast 1)
This commit is contained in:
Stefan Melmuk 2022-10-08 18:31:34 +02:00
parent 6fa6eb18e8
commit b70316e6d3
No known key found for this signature in database
GPG key ID: 817020C608FE9C09
3 changed files with 19 additions and 4 deletions

View file

@ -245,6 +245,10 @@
## Name shown in the invitation emails that don't come from a specific organization ## Name shown in the invitation emails that don't come from a specific organization
# INVITATION_ORG_NAME=Vaultwarden # INVITATION_ORG_NAME=Vaultwarden
## The number of hours after which an organization invite token, emergency access invite token,
## email verification token and deletion request token will expire (must be at least 1)
# INVITATION_EXPIRATION_HOURS=120
## Per-organization attachment storage limit (KB) ## Per-organization attachment storage limit (KB)
## Max kilobytes of attachment storage allowed per organization. ## Max kilobytes of attachment storage allowed per organization.
## When this limit is reached, organization members will not be allowed to upload further attachments for ciphers owned by that organization. ## When this limit is reached, organization members will not be allowed to upload further attachments for ciphers owned by that organization.

View file

@ -148,9 +148,10 @@ pub fn generate_invite_claims(
invited_by_email: Option<String>, invited_by_email: Option<String>,
) -> InviteJwtClaims { ) -> InviteJwtClaims {
let time_now = Utc::now().naive_utc(); let time_now = Utc::now().naive_utc();
let expire_hours = i64::from(CONFIG.invitation_expiration_hours());
InviteJwtClaims { InviteJwtClaims {
nbf: time_now.timestamp(), nbf: time_now.timestamp(),
exp: (time_now + Duration::days(5)).timestamp(), exp: (time_now + Duration::hours(expire_hours)).timestamp(),
iss: JWT_INVITE_ISSUER.to_string(), iss: JWT_INVITE_ISSUER.to_string(),
sub: uuid, sub: uuid,
email, email,
@ -185,9 +186,10 @@ pub fn generate_emergency_access_invite_claims(
grantor_email: Option<String>, grantor_email: Option<String>,
) -> EmergencyAccessInviteJwtClaims { ) -> EmergencyAccessInviteJwtClaims {
let time_now = Utc::now().naive_utc(); let time_now = Utc::now().naive_utc();
let expire_hours = i64::from(CONFIG.invitation_expiration_hours());
EmergencyAccessInviteJwtClaims { EmergencyAccessInviteJwtClaims {
nbf: time_now.timestamp(), nbf: time_now.timestamp(),
exp: (time_now + Duration::days(5)).timestamp(), exp: (time_now + Duration::hours(expire_hours)).timestamp(),
iss: JWT_EMERGENCY_ACCESS_INVITE_ISSUER.to_string(), iss: JWT_EMERGENCY_ACCESS_INVITE_ISSUER.to_string(),
sub: uuid, sub: uuid,
email, email,
@ -211,9 +213,10 @@ pub struct BasicJwtClaims {
pub fn generate_delete_claims(uuid: String) -> BasicJwtClaims { pub fn generate_delete_claims(uuid: String) -> BasicJwtClaims {
let time_now = Utc::now().naive_utc(); let time_now = Utc::now().naive_utc();
let expire_hours = i64::from(CONFIG.invitation_expiration_hours());
BasicJwtClaims { BasicJwtClaims {
nbf: time_now.timestamp(), nbf: time_now.timestamp(),
exp: (time_now + Duration::days(5)).timestamp(), exp: (time_now + Duration::hours(expire_hours)).timestamp(),
iss: JWT_DELETE_ISSUER.to_string(), iss: JWT_DELETE_ISSUER.to_string(),
sub: uuid, sub: uuid,
} }
@ -221,9 +224,10 @@ pub fn generate_delete_claims(uuid: String) -> BasicJwtClaims {
pub fn generate_verify_email_claims(uuid: String) -> BasicJwtClaims { pub fn generate_verify_email_claims(uuid: String) -> BasicJwtClaims {
let time_now = Utc::now().naive_utc(); let time_now = Utc::now().naive_utc();
let expire_hours = i64::from(CONFIG.invitation_expiration_hours());
BasicJwtClaims { BasicJwtClaims {
nbf: time_now.timestamp(), nbf: time_now.timestamp(),
exp: (time_now + Duration::days(5)).timestamp(), exp: (time_now + Duration::hours(expire_hours)).timestamp(),
iss: JWT_VERIFYEMAIL_ISSUER.to_string(), iss: JWT_VERIFYEMAIL_ISSUER.to_string(),
sub: uuid, sub: uuid,
} }

View file

@ -430,6 +430,9 @@ make_config! {
org_creation_users: String, true, def, "".to_string(); org_creation_users: String, true, def, "".to_string();
/// Allow invitations |> Controls whether users can be invited by organization admins, even when signups are otherwise disabled /// Allow invitations |> Controls whether users can be invited by organization admins, even when signups are otherwise disabled
invitations_allowed: bool, true, def, true; invitations_allowed: bool, true, def, true;
/// Invitation token expiration time (in hours) |> The number of hours after which an organization invite token, emergency access invite token,
/// email verification token and deletion request token will expire (must be at least 1)
invitation_expiration_hours: u32, false, def, 120;
/// Allow emergency access |> Controls whether users can enable emergency access to their accounts. This setting applies globally to all users. /// Allow emergency access |> Controls whether users can enable emergency access to their accounts. This setting applies globally to all users.
emergency_access_allowed: bool, true, def, true; emergency_access_allowed: bool, true, def, true;
/// Password iterations |> Number of server-side passwords hashing iterations. /// Password iterations |> Number of server-side passwords hashing iterations.
@ -726,6 +729,10 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
_ => err!("Only HTTP 301/302 and 307/308 redirects are supported"), _ => err!("Only HTTP 301/302 and 307/308 redirects are supported"),
} }
if cfg.invitation_expiration_hours < 1 {
err!("`INVITATION_EXPIRATION_HOURS` has a minimum size of 1")
}
Ok(()) Ok(())
} }