diff --git a/src/SocialiteNET/Abstractions/ISocialite.cs b/src/SocialiteNET/Abstractions/ISocialite.cs index 205fae9..0fb7583 100644 --- a/src/SocialiteNET/Abstractions/ISocialite.cs +++ b/src/SocialiteNET/Abstractions/ISocialite.cs @@ -23,7 +23,18 @@ public interface ISocialite /// Provider instance /// Thrown when config is null /// Thrown when required config properties are missing - IProvider BuildProvider(string provider, ProviderConfig config); + [Obsolete("Please use the GetProvider(ProviderEnum provider, ProviderConfig config) method")] IProvider BuildProvider(string provider, ProviderConfig config); + + /// + /// Builds an OAuth provider with custom configuration + /// + /// Provider type + /// Provider configuration + /// Provider instance + /// Thrown when config is null + /// Thrown when required config properties are missing + /// Thrown when provider is not supported + IProvider BuildProvider(ProviderEnum provider, ProviderConfig config); /// /// Adds a custom driver diff --git a/src/SocialiteNET/Abstractions/ProviderEnum.cs b/src/SocialiteNET/Abstractions/ProviderEnum.cs new file mode 100644 index 0000000..5620379 --- /dev/null +++ b/src/SocialiteNET/Abstractions/ProviderEnum.cs @@ -0,0 +1,17 @@ +namespace SocialiteNET.Abstractions; + +/// +/// Enumeration of supported providers +/// +public enum ProviderEnum +{ + /// + /// Google authentication provider. Default provider. + /// + Google, + + /// + /// GitHub authentication provider. + /// + Github, +} diff --git a/src/SocialiteNET/Core/SocialiteManager.cs b/src/SocialiteNET/Core/SocialiteManager.cs index 25de66d..db5c929 100644 --- a/src/SocialiteNET/Core/SocialiteManager.cs +++ b/src/SocialiteNET/Core/SocialiteManager.cs @@ -4,6 +4,8 @@ using System.Net.Http; using Microsoft.Extensions.DependencyInjection; using SocialiteNET.Abstractions; +using SocialiteNET.Providers.Github; +using SocialiteNET.Providers.Google; namespace SocialiteNET.Core; @@ -107,6 +109,71 @@ public IProvider BuildProvider(string provider, ProviderConfig config) return providerInstance; } + /// + public IProvider BuildProvider(ProviderEnum provider, ProviderConfig config) + { + ArgumentNullException.ThrowIfNull(config); + + config.Validate(); + + using HttpClient httpClient = this.services.GetRequiredService().CreateClient(); + + switch (provider) + { + case ProviderEnum.Google: + GoogleProvider googleProvider = new GoogleProvider( + httpClient, + config.ClientId, + config.ClientSecret, + config.RedirectUrl + ); + + if (config.Stateless) + { + googleProvider.Stateless(); + } + + if (config.UsesPkce) + { + googleProvider.WithPkce(); + } + + if (config.Parameters.Count > 0) + { + googleProvider.With(config.Parameters); + } + + return googleProvider; + + case ProviderEnum.Github: + GitHubProvider githubProvider = new GitHubProvider( + httpClient, + config.ClientId, + config.ClientSecret, + config.RedirectUrl + ); + + if (config.Stateless) + { + githubProvider.Stateless(); + } + + if (config.UsesPkce) + { + githubProvider.WithPkce(); + } + + if (config.Parameters.Count > 0) + { + githubProvider.With(config.Parameters); + } + + return githubProvider; + default: + throw new ArgumentOutOfRangeException(nameof(provider), provider, "Unsupported provider, please register a custom driver."); + } + } + /// public ISocialite Extend(string driver, Func factory) { diff --git a/tests/SocialiteNET.UnitTests/Core/SocialiteManagerGoogleTests.cs b/tests/SocialiteNET.UnitTests/Core/SocialiteManagerGoogleTests.cs index 79518d9..2f5cee0 100644 --- a/tests/SocialiteNET.UnitTests/Core/SocialiteManagerGoogleTests.cs +++ b/tests/SocialiteNET.UnitTests/Core/SocialiteManagerGoogleTests.cs @@ -87,6 +87,39 @@ public void BuildProvider_WithGoogleProviderConfig_ReturnsConfiguredGoogleProvid exception.Message.ShouldBe("Provider [Google] could not be resolved."); } + [Fact] + public void BuildProvider_WithTypedGoogleProviderConfig_ReturnsConfiguredGoogleProvider() + { + // Arrange + ServiceCollection services = []; + + IHttpClientFactory? httpClientFactory = Substitute.For(); + httpClientFactory.CreateClient().Returns(new HttpClient()); + services.AddSingleton(httpClientFactory); + + ServiceProvider serviceProvider = services.BuildServiceProvider(); + SocialiteManager manager = new(serviceProvider); + + ProviderConfig config = new() + { + ClientId = "test-client-id", + ClientSecret = "test-client-secret", + RedirectUrl = "https://example.com/callback", + Stateless = true, + UsesPkce = true + }; + config.Scopes.Add("drive"); + config.Parameters.Add("access_type", "offline"); + + // Act - This would typically fail in a real test as we can't create the type dynamically + // In a real test environment, we would need to mock or use real provider registration + var exception = Should.Throw(() => + manager.BuildProvider(ProviderEnum.Google, config)); + + // Assert + exception.Message.ShouldBe("Provider [Google] could not be resolved."); + } + [Fact] public void Extend_WithGoogleProviderFactory_RegistersCustomDriver() {