From 7f29b737db8e3199dcd11415f46be02a83567dc2 Mon Sep 17 00:00:00 2001 From: Gautam Korlam Date: Mon, 22 Jul 2024 22:21:37 -0700 Subject: [PATCH] [Claims] Add all possible backend clains to ClerkJWT --- src/validators/authorizer.rs | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/validators/authorizer.rs b/src/validators/authorizer.rs index 7af92e2..bc0c790 100644 --- a/src/validators/authorizer.rs +++ b/src/validators/authorizer.rs @@ -5,6 +5,33 @@ use crate::{ use jsonwebtoken::{decode, decode_header, errors::Error as jwtError, Algorithm, DecodingKey, Header, Validation}; use std::{error::Error, fmt}; +#[derive(Debug, Serialize, Deserialize, PartialEq)] +pub struct ActiveOrganization { + #[serde(rename = "org_id")] + id: String, + #[serde(rename = "org_slug")] + slug: String, + #[serde(rename = "org_role")] + role: String, + #[serde(rename = "org_permissions")] + permissions: Vec, +} + +impl ActiveOrganization { + /// Checks if the user has the specific permission in their session claims. + pub fn has_permission(&self, permission: &str) -> bool { + self.permissions.contains(&permission.to_string()) + } + + /// Checks if the user has the specific role in their session claims. + /// Performing role checks is not considered a best-practice and developers + /// should avoid it as much as possible. Usually, complex role checks can be + /// refactored with a single permission check. + pub fn has_role(&self, role: &str) -> bool { + self.role == role + } +} + #[derive(Debug, Serialize, Deserialize, PartialEq)] pub struct ClerkJwt { pub azp: Option, @@ -14,6 +41,9 @@ pub struct ClerkJwt { pub nbf: i32, pub sid: Option, pub sub: String, + pub act: Option, + #[serde(flatten)] + pub org: Option, } pub trait ClerkRequest { @@ -147,6 +177,11 @@ mod tests { azp: String, iss: String, sid: String, + act: String, + org_id: String, + org_slug: String, + org_role: String, + org_permissions: Vec, } struct Helper { @@ -181,6 +216,11 @@ mod tests { iss: "issuer".to_string(), nbf: current_time, sid: "session_id".to_string(), + act: "actor".to_string(), + org_id: "org_id".to_string(), + org_slug: "org_slug".to_string(), + org_role: "org_role".to_string(), + org_permissions: vec!["org_permission".to_string()], }; let mut header = Header::new(Algorithm::RS256); @@ -229,6 +269,13 @@ mod tests { iss: "issuer".to_string(), nbf: current_time as i32, sid: Some("session_id".to_string()), + act: Some("actor".to_string()), + org: Some(ActiveOrganization { + id: "org_id".to_string(), + slug: "org_slug".to_string(), + role: "org_role".to_string(), + permissions: vec!["org_permission".to_string()], + }), }; match validate_jwt(token.as_str(), jwks) {