Skip to content

Commit

Permalink
Use C# 12 features (#806)
Browse files Browse the repository at this point in the history
- Use primary constructors where relevant.
- Use collection literals where relevant.
- Add helper method to reduce duplicative tests.
- Apply some IDE suggestions.
- Remove redundant using statements.
- Fix some typos.
- Hide shared files from the Visual Studio project explorer.
  • Loading branch information
martincostello authored Oct 2, 2023
1 parent 54962db commit 3246aad
Show file tree
Hide file tree
Showing 161 changed files with 418 additions and 1,973 deletions.
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
</PropertyGroup>

<ItemGroup>
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json" Link="stylecop.json" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json" Link="stylecop.json" Visible="false" />
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
</ItemGroup>

Expand All @@ -98,7 +98,7 @@
</ItemGroup>

<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)$(PackageReadmeFile)" Pack="True" PackagePath="" />
<None Include="$(MSBuildThisFileDirectory)$(PackageReadmeFile)" Pack="True" PackagePath="" Visible="false" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion samples/Mvc.Client/Controllers/AuthenticationController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class AuthenticationController : Controller
public async Task<IActionResult> SignIn([FromForm] string provider)
{
// Note: the "provider" parameter corresponds to the external
// authentication provider choosen by the user agent.
// authentication provider chosen by the user agent.
if (string.IsNullOrWhiteSpace(provider))
{
return BadRequest();
Expand Down
32 changes: 11 additions & 21 deletions samples/Mvc.Client/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,8 @@

namespace Mvc.Client;

public class Startup
public class Startup(IConfiguration configuration, IHostEnvironment hostingEnvironment)
{
public Startup(IConfiguration configuration, IHostEnvironment hostingEnvironment)
{
Configuration = configuration;
HostingEnvironment = hostingEnvironment;
}

public IConfiguration Configuration { get; }

private IHostEnvironment HostingEnvironment { get; }

public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
Expand All @@ -38,21 +28,21 @@ public void ConfigureServices(IServiceCollection services)

.AddGoogle(options =>
{
options.ClientId = Configuration["Google:ClientId"] ?? string.Empty;
options.ClientSecret = Configuration["Google:ClientSecret"] ?? string.Empty;
options.ClientId = configuration["Google:ClientId"] ?? string.Empty;
options.ClientSecret = configuration["Google:ClientSecret"] ?? string.Empty;
})

.AddTwitter(options =>
{
options.ClientId = Configuration["Twitter:ClientId"] ?? string.Empty;
options.ClientSecret = Configuration["Twitter:ClientSecret"] ?? string.Empty;
options.ClientId = configuration["Twitter:ClientId"] ?? string.Empty;
options.ClientSecret = configuration["Twitter:ClientSecret"] ?? string.Empty;
})

.AddGitHub(options =>
{
options.ClientId = Configuration["GitHub:ClientId"] ?? string.Empty;
options.ClientSecret = Configuration["GitHub:ClientSecret"] ?? string.Empty;
options.EnterpriseDomain = Configuration["GitHub:EnterpriseDomain"] ?? string.Empty;
options.ClientId = configuration["GitHub:ClientId"] ?? string.Empty;
options.ClientSecret = configuration["GitHub:ClientSecret"] ?? string.Empty;
options.EnterpriseDomain = configuration["GitHub:EnterpriseDomain"] ?? string.Empty;
options.Scope.Add("user:email");
})

Expand All @@ -69,16 +59,16 @@ public void ConfigureServices(IServiceCollection services)

.AddDropbox(options =>
{
options.ClientId = Configuration["Dropbox:ClientId"] ?? string.Empty;
options.ClientSecret = Configuration["Dropbox:ClientSecret"] ?? string.Empty;
options.ClientId = configuration["Dropbox:ClientId"] ?? string.Empty;
options.ClientSecret = configuration["Dropbox:ClientSecret"] ?? string.Empty;
});

services.AddMvc();
}

public void Configure(IApplicationBuilder app)
{
if (HostingEnvironment.IsDevelopment())
if (hostingEnvironment.IsDevelopment())
{
IdentityModelEventSource.ShowPII = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected override async Task<AuthenticationTicket> CreateTicketAsync(
[NotNull] AuthenticationProperties properties,
[NotNull] OAuthTokenResponse tokens)
{
string address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "client_id", Options.ClientId);
var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "client_id", Options.ClientId);

using var request = new HttpRequestMessage(HttpMethod.Get, address);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ protected override async Task<AuthenticationTicket> CreateTicketAsync(
[NotNull] AuthenticationProperties properties,
[NotNull] OAuthTokenResponse tokens)
{
string endpoint = Options.UserInformationEndpoint;
var endpoint = Options.UserInformationEndpoint;

if (Options.Fields.Count > 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected override async Task<AuthenticationTicket> CreateTicketAsync(
[NotNull] AuthenticationProperties properties,
[NotNull] OAuthTokenResponse tokens)
{
string endpoint = Options.UserInformationEndpoint;
var endpoint = Options.UserInformationEndpoint;

using var request = new HttpRequestMessage(HttpMethod.Get, endpoint);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Expand Down
4 changes: 2 additions & 2 deletions src/AspNet.Security.OAuth.Apple/AppleAuthenticationEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ public class AppleAuthenticationEvents : OAuthEvents
/// <summary>
/// Gets or sets the delegate that is invoked when the <see cref="GenerateClientSecret"/> method is invoked.
/// </summary>
public Func<AppleGenerateClientSecretContext, Task> OnGenerateClientSecret { get; set; } = async context =>
public Func<AppleGenerateClientSecretContext, Task> OnGenerateClientSecret { get; set; } = static async context =>
{
context.Options.ClientSecret = await context.Options.ClientSecretGenerator.GenerateAsync(context);
};

/// <summary>
/// Gets or sets the delegate that is invoked when the <see cref="ValidateIdToken"/> method is invoked.
/// </summary>
public Func<AppleValidateIdTokenContext, Task> OnValidateIdToken { get; set; } = async context =>
public Func<AppleValidateIdTokenContext, Task> OnValidateIdToken { get; set; } = static async context =>
{
await context.Options.TokenValidator.ValidateAsync(context);
};
Expand Down
40 changes: 16 additions & 24 deletions src/AspNet.Security.OAuth.Apple/AppleAuthenticationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,14 @@ namespace AspNet.Security.OAuth.Apple;
/// <summary>
/// Defines a handler for authentication using Apple.
/// </summary>
public partial class AppleAuthenticationHandler : OAuthHandler<AppleAuthenticationOptions>
/// <param name="options">The authentication options.</param>
/// <param name="logger">The logger to use.</param>
/// <param name="encoder">The URL encoder to use.</param>
public partial class AppleAuthenticationHandler(
[NotNull] IOptionsMonitor<AppleAuthenticationOptions> options,
[NotNull] ILoggerFactory logger,
[NotNull] UrlEncoder encoder) : OAuthHandler<AppleAuthenticationOptions>(options, logger, encoder)
{
/// <summary>
/// Initializes a new instance of the <see cref="AppleAuthenticationHandler"/> class.
/// </summary>
/// <param name="options">The authentication options.</param>
/// <param name="logger">The logger to use.</param>
/// <param name="encoder">The URL encoder to use.</param>
public AppleAuthenticationHandler(
[NotNull] IOptionsMonitor<AppleAuthenticationOptions> options,
[NotNull] ILoggerFactory logger,
[NotNull] UrlEncoder encoder)
: base(options, logger, encoder)
{
}

/// <summary>
/// The handler calls methods on the events which give the application control at certain points where processing is occurring.
/// If it is not provided a default instance is supplied which does nothing when the methods are called.
Expand Down Expand Up @@ -133,7 +125,7 @@ protected virtual IEnumerable<Claim> ExtractClaimsFromToken([NotNull] string tok

var claims = new List<Claim>(securityToken.Claims)
{
new Claim(ClaimTypes.NameIdentifier, securityToken.Subject, ClaimValueTypes.String, ClaimsIssuer),
new(ClaimTypes.NameIdentifier, securityToken.Subject, ClaimValueTypes.String, ClaimsIssuer),
};

var emailClaim = claims.Find((p) => string.Equals(p.Type, "email", StringComparison.Ordinal));
Expand Down Expand Up @@ -283,19 +275,19 @@ private async Task<HandleRequestResult> HandleRemoteAuthenticateAsync(

if (Options.SaveTokens)
{
var authTokens = new List<AuthenticationToken>()
{
new AuthenticationToken() { Name = "access_token", Value = tokens.AccessToken },
};
List<AuthenticationToken> authTokens =
[
new() { Name = "access_token", Value = tokens.AccessToken },
];

if (!string.IsNullOrEmpty(tokens.RefreshToken))
{
authTokens.Add(new AuthenticationToken() { Name = "refresh_token", Value = tokens.RefreshToken });
authTokens.Add(new() { Name = "refresh_token", Value = tokens.RefreshToken });
}

if (!string.IsNullOrEmpty(tokens.TokenType))
{
authTokens.Add(new AuthenticationToken() { Name = "token_type", Value = tokens.TokenType });
authTokens.Add(new() { Name = "token_type", Value = tokens.TokenType });
}

if (!string.IsNullOrEmpty(tokens.ExpiresIn))
Expand All @@ -306,7 +298,7 @@ private async Task<HandleRequestResult> HandleRemoteAuthenticateAsync(
// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
var expiresAt = TimeProvider.GetUtcNow().AddSeconds(value);

authTokens.Add(new AuthenticationToken()
authTokens.Add(new()
{
Name = "expires_at",
Value = expiresAt.ToString("o", CultureInfo.InvariantCulture),
Expand All @@ -318,7 +310,7 @@ private async Task<HandleRequestResult> HandleRemoteAuthenticateAsync(

if (!string.IsNullOrEmpty(idToken))
{
authTokens.Add(new AuthenticationToken() { Name = "id_token", Value = idToken });
authTokens.Add(new() { Name = "id_token", Value = idToken });
}

properties.StoreTokens(authTokens);
Expand Down
12 changes: 2 additions & 10 deletions src/AspNet.Security.OAuth.Apple/AppleEmailClaimAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,8 @@

namespace AspNet.Security.OAuth.Apple;

internal sealed class AppleEmailClaimAction : ClaimAction
internal sealed class AppleEmailClaimAction(AppleAuthenticationOptions options) : ClaimAction(ClaimTypes.Email, ClaimValueTypes.String)
{
private readonly AppleAuthenticationOptions _options;

internal AppleEmailClaimAction(AppleAuthenticationOptions options)
: base(ClaimTypes.Email, ClaimValueTypes.String)
{
_options = options;
}

public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
{
if (!identity.HasClaim((p) => string.Equals(p.Type, ClaimType, StringComparison.OrdinalIgnoreCase)))
Expand All @@ -28,7 +20,7 @@ public override void Run(JsonElement userData, ClaimsIdentity identity, string i

if (!string.IsNullOrEmpty(emailClaim?.Value))
{
identity.AddClaim(new Claim(ClaimType, emailClaim.Value, ValueType, _options.ClaimsIssuer));
identity.AddClaim(new Claim(ClaimType, emailClaim.Value, ValueType, options.ClaimsIssuer));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,12 @@ namespace AspNet.Security.OAuth.Apple;
/// <summary>
/// Contains information about the current request.
/// </summary>
public class AppleGenerateClientSecretContext : BaseContext<AppleAuthenticationOptions>
/// <param name="context">The HTTP context.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param>
public class AppleGenerateClientSecretContext(
HttpContext context,
AuthenticationScheme scheme,
AppleAuthenticationOptions options) : BaseContext<AppleAuthenticationOptions>(context, scheme, options)
{
/// <summary>
/// Creates a new instance of the <see cref="AppleGenerateClientSecretContext"/> class.
/// </summary>
/// <param name="context">The HTTP context.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param>
public AppleGenerateClientSecretContext(HttpContext context, AuthenticationScheme scheme, AppleAuthenticationOptions options)
: base(context, scheme, options)
{
}
}
32 changes: 10 additions & 22 deletions src/AspNet.Security.OAuth.Apple/ApplePostConfigureOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,15 @@ namespace AspNet.Security.OAuth.Apple;
/// <summary>
/// A class used to setup defaults for all <see cref="AppleAuthenticationOptions"/>.
/// </summary>
public class ApplePostConfigureOptions : IPostConfigureOptions<AppleAuthenticationOptions>
/// <param name="cache">The <see cref="IMemoryCache"/> to use.</param>
/// <param name="timeProvider">The <see cref="TimeProvider"/> to use.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> to use.</param>
public class ApplePostConfigureOptions(
IMemoryCache cache,
TimeProvider timeProvider,
ILoggerFactory loggerFactory) : IPostConfigureOptions<AppleAuthenticationOptions>
{
private readonly IMemoryCache _cache;
private readonly TimeProvider _timeProvider;
private readonly ILoggerFactory _loggerFactory;

/// <summary>
/// Initializes a new instance of the <see cref="ApplePostConfigureOptions"/> class.
/// </summary>
/// <param name="cache">The <see cref="IMemoryCache"/> to use.</param>
/// <param name="timeProvider">The <see cref="TimeProvider"/> to use.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> to use.</param>
public ApplePostConfigureOptions(
IMemoryCache cache,
TimeProvider timeProvider,
ILoggerFactory loggerFactory)
{
_cache = cache;
_timeProvider = timeProvider;
_loggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
}
private readonly ILoggerFactory _loggerFactory = loggerFactory ?? NullLoggerFactory.Instance;

/// <inheritdoc/>
public void PostConfigure(
Expand All @@ -51,8 +39,8 @@ public void PostConfigure(
var cryptoProviderFactory = new CryptoProviderFactory() { CacheSignatureProviders = false };

options.ClientSecretGenerator ??= new DefaultAppleClientSecretGenerator(
_cache,
_timeProvider,
cache,
timeProvider,
cryptoProviderFactory,
_loggerFactory.CreateLogger<DefaultAppleClientSecretGenerator>());

Expand Down
25 changes: 10 additions & 15 deletions src/AspNet.Security.OAuth.Apple/AppleValidateIdTokenContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,18 @@ namespace AspNet.Security.OAuth.Apple;
/// <summary>
/// Contains information about the ID token to validate.
/// </summary>
public class AppleValidateIdTokenContext : BaseContext<AppleAuthenticationOptions>
/// <param name="context">The HTTP context.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param>
/// <param name="idToken">The Apple ID token for the user to validate.</param>
public class AppleValidateIdTokenContext(
HttpContext context,
AuthenticationScheme scheme,
AppleAuthenticationOptions options,
string idToken) : BaseContext<AppleAuthenticationOptions>(context, scheme, options)
{
/// <summary>
/// Creates a new instance of the <see cref="AppleValidateIdTokenContext"/> class.
/// </summary>
/// <param name="context">The HTTP context.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param>
/// <param name="idToken">The Apple ID token for the user to validate.</param>
public AppleValidateIdTokenContext(HttpContext context, AuthenticationScheme scheme, AppleAuthenticationOptions options, string idToken)
: base(context, scheme, options)
{
IdToken = idToken;
}

/// <summary>
/// Gets the Apple ID token.
/// </summary>
public string IdToken { get; }
public string IdToken { get; } = idToken;
}
Loading

0 comments on commit 3246aad

Please sign in to comment.