From 8ec666df5f45542c9ea58e8e6e69fe8b92fb867e Mon Sep 17 00:00:00 2001 From: augustuswm Date: Fri, 17 Apr 2026 14:17:08 -0500 Subject: [PATCH] Add function for retrieving token representing service --- v-api/src/authn/jwt.rs | 2 +- v-api/src/context/mod.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/v-api/src/authn/jwt.rs b/v-api/src/authn/jwt.rs index cc57bda..3ff7f98 100644 --- a/v-api/src/authn/jwt.rs +++ b/v-api/src/authn/jwt.rs @@ -72,7 +72,7 @@ impl Claims { T: VAppPermission, { Claims { - iss: ctx.public_url().to_string(), + iss: ctx.issuer(), aud: ctx.public_url().to_string(), sub: *user, prv: *provider, diff --git a/v-api/src/context/mod.rs b/v-api/src/context/mod.rs index ddf248d..b0ba3a7 100644 --- a/v-api/src/context/mod.rs +++ b/v-api/src/context/mod.rs @@ -14,6 +14,7 @@ use std::{fmt::Debug, future::Future, path::PathBuf, sync::Arc}; use thiserror::Error; use tracing::instrument; use user::{RegisteredAccessToken, UserContextError}; +use uuid::Uuid; use v_model::{ permissions::{Caller, Permission}, storage::{ @@ -299,6 +300,31 @@ where self.auth.jwks().await } + pub fn issuer(&self) -> String { + self.public_url().to_string() + } + + pub async fn service_token(&self, audience: &str) -> Result { + #[derive(Debug, Serialize)] + struct ServiceClaims { + iss: String, + aud: String, + sub: String, + exp: i64, + nbf: i64, + jti: Uuid, + } + self.sign_jwt(&ServiceClaims { + iss: self.issuer(), + aud: audience.to_string(), + sub: self.issuer(), + exp: Utc::now().timestamp() + 3600, + nbf: Utc::now().timestamp(), + jti: Uuid::new_v4(), + }) + .await + } + pub async fn sign_jwt(&self, claims: &C) -> Result where C: Serialize + Debug, @@ -360,6 +386,7 @@ where .builtin_registration_user_mut() .permissions .remove(permission); + self } @@ -706,6 +733,7 @@ pub enum VContextBuilderError { pub struct VContextBuilder { param_path: Option, + service_name: Option, jwt_expiration: Option, public_url: Option, storage: Option>>, @@ -729,6 +757,7 @@ where pub fn new() -> Self { Self { param_path: None, + service_name: None, jwt_expiration: None, public_url: None, storage: None, @@ -742,6 +771,11 @@ where self } + pub fn with_service_name(mut self, name: String) -> Self { + self.service_name = Some(name); + self + } + pub fn with_jwt_expiration(mut self, expiration: i64) -> Self { self.jwt_expiration = Some(expiration); self