Skip to content

Commit 3d1aff9

Browse files
committed
remove unsure parts
1 parent c42f1e1 commit 3d1aff9

File tree

5 files changed

+8
-220
lines changed

5 files changed

+8
-220
lines changed

core/Azure.Mcp.Core/src/Areas/Server/Authentication/HttpHost/HttpHostAuthSetupFactory.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,7 @@ public static IHttpHostAuthSetup Create(ServerConfiguration serverConfiguration)
4040
}
4141

4242
var outboundType = serverConfiguration.OutboundAuthentication?.Type;
43-
if (outboundType == OutboundAuthenticationType.JwtObo)
44-
{
45-
return new JwtOboHttpHostAuthSetup(serverConfiguration);
46-
}
47-
else if (outboundType == OutboundAuthenticationType.ManagedIdentity)
43+
if (outboundType == OutboundAuthenticationType.ManagedIdentity)
4844
{
4945
return new JwtHttpHostAuthSetup(serverConfiguration);
5046
}

core/Azure.Mcp.Core/src/Areas/Server/Authentication/HttpHost/JwtOboHttpHostAuthSetup.cs

Lines changed: 1 addition & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ internal sealed class JwtOboHttpHostAuthSetup : IHttpHostAuthSetup
3232
public JwtOboHttpHostAuthSetup(ServerConfiguration serverConfiguration)
3333
{
3434
_serverConfiguration = serverConfiguration ?? throw new ArgumentNullException(nameof(serverConfiguration));
35-
ValidateClientCredential(_serverConfiguration.OutboundAuthentication.ClientCredential!);
3635
}
3736

3837
/// <summary>
@@ -42,22 +41,7 @@ public JwtOboHttpHostAuthSetup(ServerConfiguration serverConfiguration)
4241
/// <param name="services">The service collection to configure authentication services in.</param>
4342
public void SetupServices(IServiceCollection services)
4443
{
45-
var inboundAzureAd = _serverConfiguration.InboundAuthentication.AzureAd!;
46-
var clientCredential = _serverConfiguration.OutboundAuthentication.ClientCredential!;
47-
48-
services.Configure<ForwardedHeadersOptions>(options =>
49-
{
50-
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
51-
options.KnownNetworks.Clear();
52-
options.KnownProxies.Clear();
53-
});
54-
55-
services.AddHttpContextAccessor();
56-
57-
var microsoftIdentityConfig = CreateMicrosoftIdentityConfiguration(inboundAzureAd, clientCredential);
58-
services.AddMicrosoftIdentityWebApiAuthentication(microsoftIdentityConfig, "AzureAd")
59-
.EnableTokenAcquisitionToCallDownstreamApi()
60-
.AddInMemoryTokenCaches();
44+
throw new NotImplementedException("anuchan to discuss with svukel (Steven).");
6145
}
6246

6347
/// <summary>
@@ -81,59 +65,4 @@ public void SetupEndpoints(IEndpointConventionBuilder mcpEndpoints)
8165
{
8266
mcpEndpoints.RequireAuthorization();
8367
}
84-
85-
/// <summary>
86-
/// Creates an IConfiguration instance for Microsoft Identity Web from Azure AD configuration.
87-
/// </summary>
88-
/// <param name="inboundAzureAd">The inbound Azure AD configuration for token validation.</param>
89-
/// <param name="outboundAzureAd">The outbound Azure AD configuration for OBO token acquisition.</param>
90-
/// <returns>An IConfiguration instance that Microsoft Identity Web can use.</returns>
91-
private static IConfiguration CreateMicrosoftIdentityConfiguration(AzureAdConfig inboundAzureAd, ClientCredentialConfig clientCredentialConfig)
92-
{
93-
var configurationData = new Dictionary<string, string?>
94-
{
95-
["AzureAd:Instance"] = inboundAzureAd.Instance,
96-
["AzureAd:TenantId"] = inboundAzureAd.TenantId,
97-
["AzureAd:ClientId"] = inboundAzureAd.ClientId,
98-
["AzureAd:Audience"] = inboundAzureAd.Audience,
99-
["AzureAd:ClientSecret"] = clientCredentialConfig.Secret
100-
};
101-
102-
return new ConfigurationBuilder()
103-
.AddInMemoryCollection(configurationData)
104-
.Build();
105-
}
106-
107-
/// <summary>
108-
/// Validates client credential configuration and throws for unsupported types.
109-
/// Currently only ClientSecret is supported.
110-
/// </summary>
111-
/// <param name="clientCredential">The client credential to validate.</param>
112-
/// <exception cref="ArgumentException">Thrown when ClientSecret is missing.</exception>
113-
/// <exception cref="NotImplementedException">Thrown when certificate types are used (not yet implemented).</exception>
114-
private static void ValidateClientCredential(ClientCredentialConfig clientCredential)
115-
{
116-
switch (clientCredential.Kind)
117-
{
118-
case JwtOboClientCredentialKind.ClientSecret:
119-
if (string.IsNullOrWhiteSpace(clientCredential.Secret))
120-
{
121-
throw new ArgumentException("ClientSecret is required when ClientCredential.Kind is ClientSecret", nameof(clientCredential));
122-
}
123-
break;
124-
125-
case JwtOboClientCredentialKind.CertificateLocal:
126-
throw new NotImplementedException(
127-
"ClientCredential.Kind 'CertificateLocal' is not yet implemented. " +
128-
"Currently only 'ClientSecret' is supported for JWT exchange authentication.");
129-
130-
case JwtOboClientCredentialKind.CertificateKeyVault:
131-
throw new NotImplementedException(
132-
"ClientCredential.Kind 'CertificateKeyVault' is not yet implemented. " +
133-
"Currently only 'ClientSecret' is supported for JWT exchange authentication.");
134-
135-
default:
136-
throw new ArgumentException($"Unsupported ClientCredential.Kind '{clientCredential.Kind}'", nameof(clientCredential));
137-
}
138-
}
13968
}

core/Azure.Mcp.Core/src/Areas/Server/Commands/ServiceStartCommand.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,9 @@ private IHost CreateHttpHost(ServiceStartOptions serverOptions)
344344
authConfig.SetupServices(services);
345345
ConfigureServices(services);
346346
var outboundType = serverOptions.ServerConfiguration!.OutboundAuthentication.Type;
347-
if (outboundType == OutboundAuthenticationType.JwtPassthrough ||
348-
outboundType == OutboundAuthenticationType.JwtObo)
347+
if (outboundType == OutboundAuthenticationType.JwtPassthrough)
349348
{
349+
// Note: similar no-cache for OutboundAuthenticationType.JwtObo when implemented
350350
services.AddSingleton<ICacheService, NoCacheService>();
351351
}
352352
ConfigureMcpServer(services, serverOptions);

core/Azure.Mcp.Core/src/Services/Azure/Authentication/JwtOboCredentialProvider.cs

Lines changed: 4 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public JwtOboCredentialProvider(IHttpContextAccessor httpContextAccessor, IToken
4040
/// <returns>A TokenCredential that performs JWT exchange.</returns>
4141
public Task<TokenCredential> CreateAsync(string? tenant = null)
4242
{
43-
return Task.FromResult<TokenCredential>(new JwtOboTokenCredential(_tokenAcquisition, _httpContextAccessor));
43+
throw new NotImplementedException("anuchan to discuss with svukel (Steven).");
4444
}
4545

4646
/// <summary>
@@ -49,60 +49,7 @@ public Task<TokenCredential> CreateAsync(string? tenant = null)
4949
/// <returns>User identity string extracted from the incoming token, or null if not available.</returns>
5050
public string? GetCurrentUserId()
5151
{
52-
try
53-
{
54-
var httpContext = _httpContextAccessor.HttpContext;
55-
var principal = httpContext?.User;
56-
57-
if (principal?.Identity?.IsAuthenticated != true)
58-
{
59-
throw new InvalidOperationException("User is not authenticated. JWT exchange authentication requires an authenticated user context.");
60-
}
61-
62-
// Extract user object ID using the same pattern as the reference code
63-
var userObjectId = ExtractUserObjectId(principal);
64-
var tenantId = ExtractTenantId(principal);
65-
66-
// Combine tenant and user for unique identifier (similar to cache key pattern)
67-
if (!string.IsNullOrEmpty(userObjectId))
68-
{
69-
return !string.IsNullOrEmpty(tenantId)
70-
? $"{tenantId}_{userObjectId}"
71-
: userObjectId;
72-
}
73-
74-
throw new InvalidOperationException("Unable to extract user object ID from authentication context. Required claims (oid, sub, etc.) are missing from the token.");
75-
}
76-
catch (Exception ex)
77-
{
78-
// Throw exception to prevent cache contamination between users
79-
// Better to fail the request than risk cross-user data leakage
80-
throw new InvalidOperationException("Failed to extract user identity from authentication context. This is required for secure multi-user operations.", ex);
81-
}
82-
}
83-
84-
/// <summary>
85-
/// Extracts the tenant ID from the ClaimsPrincipal.
86-
/// </summary>
87-
/// <param name="principal">The ClaimsPrincipal containing user claims.</param>
88-
/// <returns>The tenant ID, or null if not found.</returns>
89-
private static string? ExtractTenantId(ClaimsPrincipal principal)
90-
{
91-
return principal.FindFirst("tid")?.Value
92-
?? principal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid")?.Value;
93-
}
94-
95-
/// <summary>
96-
/// Extracts the user object ID from the ClaimsPrincipal.
97-
/// </summary>
98-
/// <param name="principal">The ClaimsPrincipal containing user claims.</param>
99-
/// <returns>The user object ID, or null if not found.</returns>
100-
private static string? ExtractUserObjectId(ClaimsPrincipal principal)
101-
{
102-
return principal.FindFirst("oid")?.Value
103-
?? principal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value
104-
?? principal.FindFirst(ClaimTypes.NameIdentifier)?.Value
105-
?? principal.FindFirst("sub")?.Value;
52+
throw new NotImplementedException("anuchan to discuss with svukel (Steven).");
10653
}
10754

10855
/// <summary>
@@ -124,87 +71,9 @@ public override AccessToken GetToken(TokenRequestContext requestContext, Cancell
12471
throw new NotImplementedException("Synchronous token acquisition is not supported. Use GetTokenAsync instead.");
12572
}
12673

127-
public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
74+
public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
12875
{
129-
var httpContext = _httpContextAccessor.HttpContext;
130-
if (httpContext == null)
131-
{
132-
throw new InvalidOperationException("No HTTP context available. This credential can only be used within an HTTP request.");
133-
}
134-
135-
if (requestContext.Scopes == null || requestContext.Scopes.Length == 0)
136-
{
137-
throw new ArgumentException("Token request context must have at least one scope.", nameof(requestContext));
138-
}
139-
140-
try
141-
{
142-
var scopes = requestContext.Scopes.ToArray();
143-
// This automatically uses the current user's ClaimsPrincipal from HTTP context to perform JWT exchange
144-
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes);
145-
146-
if (string.IsNullOrEmpty(accessToken))
147-
{
148-
throw new InvalidOperationException("Token acquisition returned null or empty token.");
149-
}
150-
151-
var expiresOn = ExtractJwtExpiration(accessToken);
152-
153-
return new AccessToken(accessToken, expiresOn);
154-
}
155-
catch (Exception ex) when (!(ex is InvalidOperationException))
156-
{
157-
throw new AuthenticationFailedException($"Failed to acquire JWT exchange token: {ex.Message}", ex);
158-
}
159-
}
160-
161-
/// <summary>
162-
/// Attempts to extract the expiration time from a JWT token.
163-
/// </summary>
164-
/// <param name="jwt">The JWT token to parse.</param>
165-
/// <returns>The expiration time as a DateTimeOffset, or 15 seconds from now if parsing fails.</returns>
166-
private static DateTimeOffset ExtractJwtExpiration(string jwt)
167-
{
168-
try
169-
{
170-
var parts = jwt.Split('.');
171-
if (parts.Length < 2)
172-
{
173-
// Invalid JWT format
174-
return DateTimeOffset.UtcNow.AddSeconds(15);
175-
}
176-
177-
string payload = parts[1];
178-
179-
// Add padding if needed
180-
switch (payload.Length % 4)
181-
{
182-
case 2:
183-
payload += "==";
184-
break;
185-
case 3:
186-
payload += "=";
187-
break;
188-
}
189-
190-
var payloadBytes = Convert.FromBase64String(payload);
191-
var payloadJson = System.Text.Encoding.UTF8.GetString(payloadBytes);
192-
193-
using var document = JsonDocument.Parse(payloadJson);
194-
195-
if (document.RootElement.TryGetProperty("exp", out var expElement))
196-
{
197-
var expUnix = expElement.GetInt64();
198-
return DateTimeOffset.FromUnixTimeSeconds(expUnix);
199-
}
200-
// No exp claim found
201-
return DateTimeOffset.UtcNow.AddSeconds(15);
202-
}
203-
catch
204-
{
205-
// If parsing fails, return short expiration to use fallback
206-
return DateTimeOffset.UtcNow.AddSeconds(15);
207-
}
76+
throw new NotImplementedException("anuchan to discuss with svukel (Steven).");
20877
}
20978
}
21079
}

core/Azure.Mcp.Core/src/Services/Azure/Authentication/TokenCredentialProviderFactory.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,6 @@ public static ITokenCredentialProvider Create(ServerConfiguration serverConfigur
5353
var httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
5454
return new JwtPassthroughCredentialProvider(httpContextAccessor);
5555
}
56-
else if (outboundType == OutboundAuthenticationType.JwtObo)
57-
{
58-
var httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
59-
var tokenAcquisition = serviceProvider.GetRequiredService<ITokenAcquisition>();
60-
return new JwtOboCredentialProvider(httpContextAccessor, tokenAcquisition);
61-
}
6256
else
6357
{
6458
throw new NotSupportedException($"Outbound authentication type '{outboundType}' is not supported.");

0 commit comments

Comments
 (0)