From 50219fdfd553d6335b6f0b4341719b09680c4ba0 Mon Sep 17 00:00:00 2001 From: Mateusz Woda Date: Tue, 14 Mar 2023 11:34:12 +0100 Subject: [PATCH] feat: add configurable `JWTAudience` claim (#897) --- Box.V2.Test/BoxConfigTest.cs | 25 +++++++++++++++++++++++++ Box.V2/Config/BoxConfig.cs | 12 ++++++++++++ Box.V2/Config/BoxConfigBuilder.cs | 23 ++++++++++++++++++++++- Box.V2/Config/IBoxConfig.cs | 5 +++++ Box.V2/JWTAuth/BoxJWTAuth.cs | 2 +- 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/Box.V2.Test/BoxConfigTest.cs b/Box.V2.Test/BoxConfigTest.cs index 66141bf79..fd5ed8bb6 100644 --- a/Box.V2.Test/BoxConfigTest.cs +++ b/Box.V2.Test/BoxConfigTest.cs @@ -85,5 +85,30 @@ public void BoxConfig_SetBoxAccountApiHostUri() Assert.AreEqual(newConfig.BoxAccountApiHostUri.ToString(), exampleUri + "/"); Assert.AreEqual(newConfig.AuthCodeBaseUri.ToString(), exampleUri + "/" + "oauth2/authorize"); } + + [TestMethod] + public void BoxConfig_DefaultJWTAudience() + { + var exampleUri = new Uri("https://example.com/account"); + var newConfig = new BoxConfigBuilder("", "") + .SetBoxApiHostUri(exampleUri) + .Build(); + + Assert.AreEqual(newConfig.JWTAudience, "https://api.box.com/oauth2/token"); + } + + [TestMethod] + public void BoxConfig_SetJWTAudience() + { + var exampleUri = new Uri("https://example.com/account"); + var customAudience = "custom_audience/oauth2/token"; + var newConfig = new BoxConfigBuilder("", "") + .SetBoxApiHostUri(exampleUri) + .SetJWTAudience(customAudience) + .Build(); + + Assert.AreEqual(newConfig.BoxApiHostUri.ToString(), exampleUri + "/"); + Assert.AreEqual(newConfig.JWTAudience, customAudience); + } } } diff --git a/Box.V2/Config/BoxConfig.cs b/Box.V2/Config/BoxConfig.cs index 26695f174..be7333072 100644 --- a/Box.V2/Config/BoxConfig.cs +++ b/Box.V2/Config/BoxConfig.cs @@ -66,6 +66,7 @@ public BoxConfig(BoxConfigBuilder builder) WebProxy = builder.WebProxy; Timeout = builder.Timeout; RetryStrategy = builder.RetryStrategy; + JWTAudience = builder.JWTAudience; } /// @@ -155,6 +156,17 @@ public Uri BoxApiUri private set { _boxApiUri = value; } } + private string _jwtAudience; + + /// + /// Audience claim for JWT token. + /// + public string JWTAudience + { + get { return _jwtAudience ?? Constants.BoxAuthTokenApiUriString; } + private set { _jwtAudience = value; } + } + public string ClientId { get; private set; } public string ConsumerKey { get; private set; } public string ClientSecret { get; private set; } diff --git a/Box.V2/Config/BoxConfigBuilder.cs b/Box.V2/Config/BoxConfigBuilder.cs index 9d4863904..2188c135d 100644 --- a/Box.V2/Config/BoxConfigBuilder.cs +++ b/Box.V2/Config/BoxConfigBuilder.cs @@ -239,6 +239,17 @@ public BoxConfigBuilder SetRetryStrategy(IRetryStrategy retryStrategy) return this; } + /// + /// Sets audience claim used in JWT tokens. + /// + /// Audience claim value + /// this BoxConfigBuilder object for chaining + public BoxConfigBuilder SetJWTAudience(string jwtAudience) + { + _jwtAudience = jwtAudience; + return this; + } + public string ClientId { get; private set; } public string ClientSecret { get; private set; } public string EnterpriseId { get; private set; } @@ -247,7 +258,6 @@ public BoxConfigBuilder SetRetryStrategy(IRetryStrategy retryStrategy) public string JWTPublicKeyId { get; private set; } public string UserAgent { get; private set; } - public Uri BoxApiHostUri { get; private set; } = new Uri(Constants.BoxApiHostUriString); public Uri BoxAccountApiHostUri { get; private set; } = new Uri(Constants.BoxAccountApiHostUriString); public Uri BoxUploadApiUri { get; private set; } = new Uri(new Uri(Constants.BoxUploadApiUriWithoutVersionString), Constants.BoxApiCurrentVersionUriString); @@ -283,6 +293,17 @@ public Uri BoxApiUri /// public IRetryStrategy RetryStrategy { get; private set; } = new ExponentialBackoff(); + private string _jwtAudience; + + /// + /// Audience claim for JWT token. + /// + public string JWTAudience + { + get { return _jwtAudience ?? Constants.BoxAuthTokenApiUriString; } + private set { _jwtAudience = value; } + } + private Uri EnsureEndsWithSlash(Uri uri) { return uri.ToString().EndsWith("/") ? uri : new Uri($"{uri}{"/"}"); diff --git a/Box.V2/Config/IBoxConfig.cs b/Box.V2/Config/IBoxConfig.cs index 821454d3e..a5f4740c9 100644 --- a/Box.V2/Config/IBoxConfig.cs +++ b/Box.V2/Config/IBoxConfig.cs @@ -146,5 +146,10 @@ public interface IBoxConfig /// Retry strategy for failed requests /// IRetryStrategy RetryStrategy { get; } + /// + /// JWT token audience claim. + /// https://api.box.com/oauth2/token is used by default. + /// + string JWTAudience { get; } } } diff --git a/Box.V2/JWTAuth/BoxJWTAuth.cs b/Box.V2/JWTAuth/BoxJWTAuth.cs index 0c1309824..57dae1ca2 100644 --- a/Box.V2/JWTAuth/BoxJWTAuth.cs +++ b/Box.V2/JWTAuth/BoxJWTAuth.cs @@ -265,7 +265,7 @@ private string ConstructJWTAssertion(string sub, string boxSubType, DateTimeOffs expireTime = nowOverride.Value.AddSeconds(30); } - var payload = new JwtPayload(_boxConfig.ClientId, new Uri(Constants.BoxAuthTokenApiUriString).ToString(), + var payload = new JwtPayload(_boxConfig.ClientId, _boxConfig.JWTAudience, claims, null, expireTime.LocalDateTime); var header = new JwtHeader(signingCredentials: _credentials);