Skip to content

Commit

Permalink
support custom JWT tokens on the backend (#28431)
Browse files Browse the repository at this point in the history
GitOrigin-RevId: 5ea4cb3631505ce098a6e3925325077fc285a7a2
  • Loading branch information
rrwang7 authored and Convex, Inc. committed Jul 30, 2024
1 parent dabfba3 commit 99e7e80
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ minitrace = { version = "0.6", features = [ "enable" ] }
must-let = { git = "https://github.com/sujayakar/must-let", rev = "5b487d78db235e396e61dd03ce261ced0eafff9d" }
num_cpus = "1.16.0"
oauth2 = "4.4.2"
openidconnect = { git = "https://github.com/get-convex/openidconnect-rs", rev = "45a84cf974d45db998af10546a4c35abd5f0a487", features = [ "accept-rfc3339-timestamps" ] }
openidconnect = { git = "https://github.com/get-convex/openidconnect-rs", rev = "eb55e703f0c0585e3ed796f48e3ed9e96b56d31d", features = [ "accept-rfc3339-timestamps" ] }
parking_lot = { version = "0.12", features = [ "hardware-lock-elision" ] }
paste = { version = "1.0.12" }
phf = { version = "0.11.2", features = [ "macros" ] }
Expand Down
7 changes: 5 additions & 2 deletions crates/application/src/tests/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use common::{
},
RequestId,
};
use futures::FutureExt;
use itertools::Itertools;
use keybroker::Identity;
use must_let::must_let;
Expand Down Expand Up @@ -126,10 +127,12 @@ async fn test_env_vars_not_accessible_in_components(rt: TestRuntime) -> anyhow::
value: "emma".parse()?,
},
)
.boxed()
.await?;
application.commit_test(tx).await?;
let result =
run_function(&application, "componentEntry:envVarQuery".parse()?, vec![]).await??;
let result = run_function(&application, "componentEntry:envVarQuery".parse()?, vec![])
.boxed()
.await??;
assert_eq!(ConvexValue::Null, result.value);
let result =
run_function(&application, "componentEntry:envVarAction".parse()?, vec![]).await??;
Expand Down
14 changes: 13 additions & 1 deletion crates/convex/sync_types/src/json.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use anyhow::bail;
use std::collections::BTreeMap;

use anyhow::{
bail,
Context,
};
use serde::{
Deserialize,
Deserializer,
Expand Down Expand Up @@ -784,6 +789,8 @@ struct UserIdentityAttributesJson {
pub address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
#[serde(flatten)]
pub custom_claims: Option<BTreeMap<String, String>>,
}

impl TryFrom<JsonValue> for UserIdentityAttributes {
Expand All @@ -798,6 +805,9 @@ impl TryFrom<JsonValue> for UserIdentityAttributes {
} else {
bail!("Either \"tokenIdentifier\" or \"issuer\" and \"subject\" must be set")
};
let custom_claims = raw
.custom_claims
.context("expected custom claims to be set")?;

Ok(UserIdentityAttributes {
token_identifier,
Expand All @@ -821,6 +831,7 @@ impl TryFrom<JsonValue> for UserIdentityAttributes {
phone_number_verified: raw.phone_number_verified,
address: raw.address,
updated_at: raw.updated_at,
custom_claims,
})
}
}
Expand Down Expand Up @@ -851,6 +862,7 @@ impl TryFrom<UserIdentityAttributes> for JsonValue {
phone_number_verified: value.phone_number_verified,
address: value.address,
updated_at: value.updated_at,
custom_claims: Some(value.custom_claims),
};
Ok(serde_json::to_value(raw)?)
}
Expand Down
3 changes: 3 additions & 0 deletions crates/convex/sync_types/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{
collections::BTreeMap,
fmt::Display,
ops::Deref,
};
Expand Down Expand Up @@ -193,6 +194,7 @@ pub struct UserIdentityAttributes {
pub address: Option<String>,
/// Stored as RFC3339 string
pub updated_at: Option<String>,
pub custom_claims: BTreeMap<String, String>,
}

impl Default for UserIdentityAttributes {
Expand All @@ -219,6 +221,7 @@ impl Default for UserIdentityAttributes {
phone_number_verified: None,
address: None,
updated_at: None,
custom_claims: BTreeMap::new(),
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions crates/keybroker/src/broker.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use core::panic;
use std::{
collections::BTreeMap,
fmt,
time::{
Duration,
Expand Down Expand Up @@ -418,6 +419,42 @@ impl UserIdentity {
let claims = binding.claims(&verifier, nonce_verifier)?;
let subject = claims.subject().to_string();
let issuer = claims.issuer().to_string();
let mut custom_claims = BTreeMap::new();
for claim in claims.custom_claims() {
// Filter out standard claims and claims set by auth providers
match claim.0.as_str() {
// Standard claims that we support: see https://docs.convex.dev/api/interfaces/server.UserIdentity
"sub"
| "iss"
| "exp"
| "name"
| "given_name"
| "family_name"
| "nickname"
| "preferred_username"
| "profile"
| "picture"
| "website"
| "email"
| "email_verified"
| "gender"
| "birthdate"
| "zoneinfo"
| "locale"
| "phone_number"
| "phone_number_verified"
| "address"
| "updated_at"
// Clerk claims: see https://clerk.com/docs/backend-requests/resources/session-tokens
| "jti" | "nbf" => {
continue;
},
_ => {
let value = claim.1.as_str().context("Only string values for custom claims are supported")?.to_string();
custom_claims.insert(claim.0.to_string(), value);
},
}
}
Ok(UserIdentity {
subject: subject.clone(),
issuer: issuer.clone(),
Expand Down Expand Up @@ -448,6 +485,7 @@ impl UserIdentity {
.and_then(|a| a.formatted.as_ref())
.map(|f| f.to_string()),
updated_at: claims.updated_at().map(|dt| dt.to_rfc3339()),
custom_claims,
},
})
}
Expand Down
1 change: 1 addition & 0 deletions crates/pb/protos/convex_identity.proto
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ message UserIdentityAttributes {
optional bool phone_number_verified = 19;
optional string address = 20;
optional string updated_at = 21;
map<string, string> custom_claims = 22;
}
4 changes: 4 additions & 0 deletions crates/pb/src/user_identity_attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl TryFrom<UserIdentityAttributesProto> for UserIdentityAttributes {
phone_number_verified,
address,
updated_at,
custom_claims,
}: UserIdentityAttributesProto,
) -> anyhow::Result<UserIdentityAttributes> {
let token_identifier =
Expand Down Expand Up @@ -58,6 +59,7 @@ impl TryFrom<UserIdentityAttributesProto> for UserIdentityAttributes {
phone_number_verified,
address,
updated_at,
custom_claims: custom_claims.into_iter().collect(),
})
}
}
Expand Down Expand Up @@ -86,6 +88,7 @@ impl From<UserIdentityAttributes> for UserIdentityAttributesProto {
phone_number_verified,
address,
updated_at,
custom_claims,
}: UserIdentityAttributes,
) -> UserIdentityAttributesProto {
UserIdentityAttributesProto {
Expand All @@ -110,6 +113,7 @@ impl From<UserIdentityAttributes> for UserIdentityAttributesProto {
phone_number_verified,
address,
updated_at,
custom_claims: custom_claims.into_iter().collect(),
}
}
}
Expand Down

0 comments on commit 99e7e80

Please sign in to comment.