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