From a192f1380b24075a76eb3827669298d215f676d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szak=C3=A1ts=20Alp=C3=A1r=20Zsolt?= Date: Sat, 16 Aug 2025 23:31:35 +0200 Subject: [PATCH] Configures OIDC with explicit endpoints Configures the OpenID Connect (OIDC) authentication flow by explicitly setting the authorization, token, JWKS, end session, and user info endpoints. This change removes the custom OIDC configuration manager and directly sets the configuration within the OIDC options. This approach simplifies the configuration and ensures that the application uses the correct endpoints for authentication and authorization with the third-party provider. --- Source/ProofOfConcept/Program.cs | 18 ++++--- .../TeslaOIDCConfigurationManager.cs | 54 +++---------------- 2 files changed, 18 insertions(+), 54 deletions(-) diff --git a/Source/ProofOfConcept/Program.cs b/Source/ProofOfConcept/Program.cs index 0279aeb..1f902c3 100644 --- a/Source/ProofOfConcept/Program.cs +++ b/Source/ProofOfConcept/Program.cs @@ -40,13 +40,19 @@ builder.Services .AddCookie() .AddOpenIdConnect(o => { - // === Use Fleet-Auth third-party OIDC config === - // Issuer in that doc: https://fleet-auth.tesla.com/oauth2/v3/nts - o.Authority = "https://fleet-auth.tesla.com/oauth2/v3/nts"; - - // Point directly at the third-party metadata you found: + // Point directly at the third-party metadata o.MetadataAddress = "https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/thirdparty/.well-known/openid-configuration"; - + + // === Use Fleet-Auth third-party OIDC config === + o.Authority = "https://fleet-auth.tesla.com/oauth2/v3/nts"; + + o.Configuration ??= new OpenIdConnectConfiguration(); + o.Configuration.AuthorizationEndpoint = "https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/authorize"; + o.Configuration.TokenEndpoint = "https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/token"; + o.Configuration.JwksUri = "https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/discovery/thirdparty/keys"; + o.Configuration.EndSessionEndpoint = "https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/logout"; + o.Configuration.UserInfoEndpoint = "https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/userinfo"; + // Standard OIDC web app settings o.ResponseType = OpenIdConnectResponseType.Code; o.UsePkce = true; diff --git a/Source/ProofOfConcept/Utilities/TeslaOIDCConfigurationManager.cs b/Source/ProofOfConcept/Utilities/TeslaOIDCConfigurationManager.cs index b02ef6f..cbbc3fa 100644 --- a/Source/ProofOfConcept/Utilities/TeslaOIDCConfigurationManager.cs +++ b/Source/ProofOfConcept/Utilities/TeslaOIDCConfigurationManager.cs @@ -11,13 +11,12 @@ using Microsoft.IdentityModel.Protocols.OpenIdConnect; public sealed class TeslaOIDCConfigurationManager : IConfigurationManager { + private readonly Func urlOverride; private readonly IConfigurationManager _inner; - private readonly string _tokenEndpointOverride; - // No HttpClient/ServiceProvider needed — uses default retriever internally - public TeslaOIDCConfigurationManager(string metadataAddress, string tokenEndpointOverride) + public TeslaOIDCConfigurationManager(string metadataAddress, Func urlOverride) { - _tokenEndpointOverride = tokenEndpointOverride; + this.urlOverride = urlOverride; _inner = new ConfigurationManager( metadataAddress, new OpenIdConnectConfigurationRetriever()); @@ -25,51 +24,10 @@ public sealed class TeslaOIDCConfigurationManager : IConfigurationManager GetConfigurationAsync(CancellationToken cancel) { - var cfg = await _inner.GetConfigurationAsync(cancel).ConfigureAwait(false); - cfg.TokenEndpoint = _tokenEndpointOverride; // <-- required by Tesla - return cfg; + OpenIdConnectConfiguration? configuration = await _inner.GetConfigurationAsync(cancel); + configuration.TokenEndpoint = urlOverride(configuration.TokenEndpoint); + return configuration; } public void RequestRefresh() => _inner.RequestRefresh(); - - public sealed class SigningKeyResolver - { - private readonly HttpClient backChannel; - private readonly TimeSpan cacheDuration; - private readonly ConcurrentDictionary cache; - - public SigningKeyResolver(HttpClient backChannel, TimeSpan cacheDuration) - { - this.backChannel = backChannel; - this.cacheDuration = cacheDuration; - this.cache = new ConcurrentDictionary(); - } - - public IEnumerable Resolve(string token, SecurityToken securityToken, string kid, TokenValidationParameters validationParameters) - { - JwtSecurityToken jwt = new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(token); - string? issuer = jwt.Issuer?.TrimEnd('/'); - - // Issuer is empty - if (string.IsNullOrEmpty(issuer)) - return Array.Empty(); - - // Serve from cache if fresh - if (cache.TryGetValue(issuer, out var entry) && entry.exp > DateTimeOffset.UtcNow) - return entry.keys; - - // Fetch JWKS from the same issuer (sync-over-async kept local to this callback) - string jwksUrl = $"{issuer}/certs"; - string json = backChannel.GetStringAsync(jwksUrl).GetAwaiter().GetResult(); - - // Get result - JsonWebKeySet jwks = new JsonWebKeySet(json); - SecurityKey[] keys = jwks.Keys.Select(k => (SecurityKey)k).ToArray(); - - // Cache - cache[issuer] = (DateTimeOffset.UtcNow.Add(this.cacheDuration), keys); - - return keys; - } - } } \ No newline at end of file