Skip to content

Commit 6fcbac8

Browse files
committed
Enhance authentication setup and endpoint clarity
- Ensure roles in `ApiKey` and `Credential` classes are non-optional and add equality/hash code methods. - Initialize roles and claims with empty lists in settings and validation result classes to prevent null references. - Simplify role claim addition in authentication handlers by removing null checks. - Maintain consistency in `SimpleAuthenticationExtensions` by initializing roles with empty lists if null.
1 parent 278bb18 commit 6fcbac8

13 files changed

Lines changed: 79 additions & 29 deletions

File tree

samples/Controllers/ApiKeySample/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
// .Build())
2525
// .AddPolicy("ApiKey", builder => builder.AddAuthenticationSchemes(ApiKeyDefaults.AuthenticationScheme).RequireAuthenticatedUser());
2626

27+
// This service is used when there isn't a fixed API Key value in the configuration.
2728
builder.Services.AddTransient<IApiKeyValidator, CustomApiKeyValidator>();
2829

2930
// Uncomment the following line if you have multiple authentication schemes and

samples/Controllers/BasicAuthenticationSample/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
// .Build())
2626
// .AddPolicy("Basic", builder => builder.AddAuthenticationSchemes(BasicAuthenticationDefaults.AuthenticationScheme).RequireAuthenticatedUser());
2727

28+
// This service is used when there isn't a fixed user/password value in the configuration.
2829
builder.Services.AddTransient<IBasicAuthenticationValidator, CustomBasicAuthenticationValidator>();
2930

3031
// Uncomment the following line if you have multiple authentication schemes and

samples/MinimalApis/ApiKeySample/Program.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
// .Build())
2626
// .AddPolicy("ApiKey", builder => builder.AddAuthenticationSchemes(ApiKeyDefaults.AuthenticationScheme).RequireAuthenticatedUser());
2727

28+
// This service is used when there isn't a fixed API Key value in the configuration.
2829
builder.Services.AddTransient<IApiKeyValidator, CustomApiKeyValidator>();
2930

3031
// Uncomment the following line if you have multiple authentication schemes and
@@ -63,10 +64,12 @@
6364
})
6465
.RequireAuthorization();
6566

66-
app.MapGet("api/admin", () => "Administrator access granted")
67+
app.MapGet("api/administrator", () => TypedResults.NoContent())
68+
.WithDescription("This endpoint requires the user to have the 'Administrator' role.")
6769
.RequireAuthorization(policy => policy.RequireRole("Administrator"));
6870

69-
app.MapGet("api/user", () => "User access granted")
71+
app.MapGet("api/user", () => TypedResults.NoContent())
72+
.WithDescription("This endpoint requires the user to have the 'User' role.")
7073
.RequireAuthorization(policy => policy.RequireRole("User"));
7174

7275
app.Run();

samples/MinimalApis/BasicAuthenticationSample/Program.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
// .Build())
2626
// .AddPolicy("Basic", builder => builder.AddAuthenticationSchemes(BasicAuthenticationDefaults.AuthenticationScheme).RequireAuthenticatedUser());
2727

28+
// This service is used when there isn't a fixed user/password value in the configuration.
2829
builder.Services.AddTransient<IBasicAuthenticationValidator, CustomBasicAuthenticationValidator>();
2930

3031
// Uncomment the following line if you have multiple authentication schemes and
@@ -63,10 +64,12 @@
6364
})
6465
.RequireAuthorization();
6566

66-
app.MapGet("api/admin", () => "Administrator access granted")
67+
app.MapGet("api/administrator", () => TypedResults.NoContent())
68+
.WithDescription("This endpoint requires the user to have the 'Administrator' role.")
6769
.RequireAuthorization(policy => policy.RequireRole("Administrator"));
6870

69-
app.MapGet("api/user", () => "User access granted")
71+
app.MapGet("api/user", () => TypedResults.NoContent())
72+
.WithDescription("This endpoint requires the user to have the 'User' role.")
7073
.RequireAuthorization(policy => policy.RequireRole("User"));
7174

7275
app.Run();

src/SimpleAuthentication.Abstractions/ApiKey/ApiKey.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,28 @@ namespace SimpleAuthentication.ApiKey;
55
/// </summary>
66
/// <param name="Value">The API key value</param>
77
/// <param name="UserName">The user name associated with the current key</param>
8-
/// <param name="Roles">The optional list of roles to assign to the user</param>
9-
public record class ApiKey(string Value, string UserName, IEnumerable<string>? Roles = null);
8+
/// <param name="Roles">The list of roles to assign to the user</param>
9+
public record class ApiKey(string Value, string UserName, IEnumerable<string> Roles)
10+
{
11+
/// <inheritdoc />
12+
public virtual bool Equals(ApiKey? other)
13+
{
14+
if (other is null)
15+
{
16+
return false;
17+
}
18+
19+
if (ReferenceEquals(this, other))
20+
{
21+
return true;
22+
}
23+
24+
return Value == other.Value && UserName == other.UserName;
25+
}
26+
27+
/// <inheritdoc />
28+
public override int GetHashCode()
29+
{
30+
return HashCode.Combine(Value, UserName);
31+
}
32+
}

src/SimpleAuthentication.Abstractions/ApiKey/ApiKeySettings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public class ApiKeySettings : AuthenticationSchemeOptions
4646
/// </summary>
4747
/// <seealso cref="ApiKeyValue"/>
4848
/// <seealso cref="UserName"/>
49-
public IEnumerable<string>? Roles { get; set; }
49+
public IEnumerable<string> Roles { get; set; } = [];
5050

5151
/// <summary>
5252
/// The collection of valid API keys.
@@ -79,7 +79,7 @@ internal IEnumerable<ApiKey> GetAllApiKeys()
7979
if (!string.IsNullOrWhiteSpace(ApiKeyValue) && !string.IsNullOrWhiteSpace(UserName))
8080
{
8181
// If necessary, add the API Key from the base properties.
82-
apiKeys.Add(new(ApiKeyValue, UserName, Roles));
82+
apiKeys.Add(new(ApiKeyValue, UserName, Roles ?? []));
8383
}
8484

8585
return apiKeys;

src/SimpleAuthentication.Abstractions/ApiKey/ApiKeyValidationResult.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@ public class ApiKeyValidationResult
2323
/// <summary>
2424
/// Gets the claim list, if authentication was successful.
2525
/// </summary>
26-
public IList<Claim>? Claims { get; }
26+
public IList<Claim> Claims { get; } = [];
2727

2828
/// <summary>
2929
/// Gets the failure message, if authentication was unsuccessful.
3030
/// </summary>
3131
public string? FailureMessage { get; }
3232

33-
private ApiKeyValidationResult(string userName, IList<Claim>? claims)
33+
private ApiKeyValidationResult(string userName, IList<Claim>? claims = null)
3434
{
3535
Succeeded = true;
3636
UserName = userName;
37-
Claims = claims;
37+
Claims = claims ?? [];
3838
}
3939

4040
private ApiKeyValidationResult(string failureMessage)

src/SimpleAuthentication.Abstractions/BasicAuthentication/BasicAuthenticationSettings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class BasicAuthenticationSettings : AuthenticationSchemeOptions
3535
/// </summary>
3636
/// <seealso cref="UserName"/>
3737
/// <seealso cref="Password"/>
38-
public IEnumerable<string>? Roles { get; set; }
38+
public IEnumerable<string> Roles { get; set; } = [];
3939

4040
/// <summary>
4141
/// The collection of authorization credentials.
@@ -68,7 +68,7 @@ internal IEnumerable<Credential> GetAllCredentials()
6868
if (!string.IsNullOrWhiteSpace(UserName) && !string.IsNullOrWhiteSpace(Password))
6969
{
7070
// If necessary, add the Credentials from the base properties.
71-
credentials.Add(new(UserName, Password, Roles));
71+
credentials.Add(new(UserName, Password, Roles ?? []));
7272
}
7373

7474
return credentials;

src/SimpleAuthentication.Abstractions/BasicAuthentication/BasicAuthenticationValidationResult.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class BasicAuthenticationValidationResult
2323
/// <summary>
2424
/// Gets the claim list, if authentication was successful.
2525
/// </summary>
26-
public IList<Claim>? Claims { get; }
26+
public IList<Claim> Claims { get; } = [];
2727

2828
/// <summary>
2929
/// Gets the failure message, if authentication was unsuccessful.
@@ -34,7 +34,7 @@ private BasicAuthenticationValidationResult(string userName, IList<Claim>? claim
3434
{
3535
Succeeded = true;
3636
UserName = userName;
37-
Claims = claims;
37+
Claims = claims ?? [];
3838
}
3939

4040
private BasicAuthenticationValidationResult(string failureMessage)

src/SimpleAuthentication.Abstractions/BasicAuthentication/Credential.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,28 @@ namespace SimpleAuthentication.BasicAuthentication;
55
/// </summary>
66
/// <param name="UserName">The user name</param>
77
/// <param name="Password">The password</param>
8-
/// <param name="Roles">The optional list of roles to assign to the user</param>
9-
public record class Credential(string UserName, string Password, IEnumerable<string>? Roles = null);
8+
/// <param name="Roles">The list of roles to assign to the user</param>
9+
public record class Credential(string UserName, string Password, IEnumerable<string> Roles)
10+
{
11+
/// <inheritdoc />
12+
public virtual bool Equals(Credential? other)
13+
{
14+
if (other is null)
15+
{
16+
return false;
17+
}
18+
19+
if (ReferenceEquals(this, other))
20+
{
21+
return true;
22+
}
23+
24+
return UserName == other.UserName && Password == other.Password;
25+
}
26+
27+
/// <inheritdoc />
28+
public override int GetHashCode()
29+
{
30+
return HashCode.Combine(UserName, Password);
31+
}
32+
}

0 commit comments

Comments
 (0)