Skip to content

Commit 8735ca8

Browse files
authored
Merge pull request #192 from marcominerva/develop
Make JwtBearerService public
2 parents da08617 + 711c23f commit 8735ca8

12 files changed

Lines changed: 57 additions & 42 deletions

File tree

samples/Controllers/ApiKeySample/ApiKeySample.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.4" />
11-
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.5" />
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.5" />
11+
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.7" />
1212
</ItemGroup>
1313

1414
<ItemGroup>

samples/Controllers/BasicAuthenticationSample/BasicAuthenticationSample.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.4" />
11-
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.5" />
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.5" />
11+
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.7" />
1212
</ItemGroup>
1313

1414
<ItemGroup>

samples/Controllers/JwtBearerSample/JwtBearerSample.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.4" />
11-
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.5" />
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.5" />
11+
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.7" />
1212
</ItemGroup>
1313

1414
<ItemGroup>

samples/MinimalApis/ApiKeySample/ApiKeySample.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.4" />
11-
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.5" />
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.5" />
11+
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.7" />
1212
</ItemGroup>
1313

1414
<ItemGroup>

samples/MinimalApis/BasicAuthenticationSample/BasicAuthenticationSample.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.4" />
11-
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.5" />
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.5" />
11+
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.7" />
1212
</ItemGroup>
1313

1414
<ItemGroup>

samples/MinimalApis/JwtBearerSample/JwtBearerSample.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.4" />
11-
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.5" />
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.5" />
11+
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.7" />
1212
</ItemGroup>
1313

1414
<ItemGroup>

samples/MinimalApis/Net8JwtBearerSample/Net8JwtBearerSample.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.5" />
10+
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
1111
</ItemGroup>
1212

1313
<ItemGroup>

src/SimpleAuthentication.Abstractions/SimpleAuthentication.Abstractions.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
</ItemGroup>
3737

3838
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
39-
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.4" />
39+
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.5" />
4040
</ItemGroup>
4141

4242
<ItemGroup>

src/SimpleAuthentication.Swashbuckle/SimpleAuthentication.Swashbuckle.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
<ItemGroup>
3535
<PackageReference Include="SimpleAuthenticationTools.Abstractions" Version="3.1.10" />
36-
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="10.1.5" />
36+
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="10.1.7" />
3737
</ItemGroup>
3838

3939
<ItemGroup>

src/SimpleAuthentication/JwtBearer/JwtBearerService.cs

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,40 @@
66

77
namespace SimpleAuthentication.JwtBearer;
88

9-
internal class JwtBearerService(IOptions<JwtBearerSettings> jwtBearerSettingsOptions) : IJwtBearerService
9+
/// <summary>
10+
/// Default implementation of <see cref="IJwtBearerService"/> that provides JWT Bearer token generation and validation.
11+
/// </summary>
12+
/// <param name="jwtBearerSettingsOptions">The JWT Bearer settings.</param>
13+
public class JwtBearerService(IOptions<JwtBearerSettings> jwtBearerSettingsOptions) : IJwtBearerService
1014
{
11-
private readonly JwtBearerSettings jwtBearerSettings = jwtBearerSettingsOptions.Value;
15+
/// <summary>
16+
/// Gets the JWT Bearer settings used by this service.
17+
/// </summary>
18+
protected JwtBearerSettings JwtBearerSettings { get; } = jwtBearerSettingsOptions?.Value ?? throw new ArgumentNullException(nameof(jwtBearerSettingsOptions));
1219

13-
public Task<string> CreateTokenAsync(string userName, IList<Claim>? claims = null, string? issuer = null, string? audience = null, DateTime? absoluteExpiration = null)
20+
/// <inheritdoc />
21+
public virtual Task<string> CreateTokenAsync(string userName, IList<Claim>? claims = null, string? issuer = null, string? audience = null, DateTime? absoluteExpiration = null)
1422
{
23+
var now = DateTime.UtcNow;
24+
25+
if (absoluteExpiration.HasValue && absoluteExpiration.Value < now)
26+
{
27+
throw new ArgumentException("The expiration date must be greater than or equal to the current date and time.", nameof(absoluteExpiration));
28+
}
29+
1530
claims ??= [];
16-
claims.Update(jwtBearerSettings.NameClaimType, userName);
31+
claims.Update(JwtBearerSettings.NameClaimType, userName);
1732
claims.Update(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString());
1833

19-
var now = DateTime.UtcNow;
20-
2134
var securityTokenDescriptor = new SecurityTokenDescriptor()
2235
{
23-
Subject = new ClaimsIdentity(claims, jwtBearerSettings.SchemeName, jwtBearerSettings.NameClaimType, jwtBearerSettings.RoleClaimType),
24-
Issuer = issuer ?? jwtBearerSettings.Issuers?.FirstOrDefault(),
25-
Audience = audience ?? jwtBearerSettings.Audiences?.FirstOrDefault(),
36+
Subject = new ClaimsIdentity(claims, JwtBearerSettings.SchemeName, JwtBearerSettings.NameClaimType, JwtBearerSettings.RoleClaimType),
37+
Issuer = issuer ?? JwtBearerSettings.Issuers?.FirstOrDefault(),
38+
Audience = audience ?? JwtBearerSettings.Audiences?.FirstOrDefault(),
2639
IssuedAt = now,
27-
NotBefore = now.Add(-jwtBearerSettings.ClockSkew),
28-
Expires = absoluteExpiration ?? (jwtBearerSettings.ExpirationTime.GetValueOrDefault() > TimeSpan.Zero ? now.Add(jwtBearerSettings.ExpirationTime!.Value) : DateTime.MaxValue),
29-
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtBearerSettings.SecurityKey)), jwtBearerSettings.Algorithm)
40+
NotBefore = now.Add(-JwtBearerSettings.ClockSkew),
41+
Expires = absoluteExpiration ?? (JwtBearerSettings.ExpirationTime.GetValueOrDefault() > TimeSpan.Zero ? now.Add(JwtBearerSettings.ExpirationTime!.Value) : DateTime.MaxValue),
42+
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtBearerSettings.SecurityKey)), JwtBearerSettings.Algorithm)
3043
};
3144

3245
var tokenHandler = new JsonWebTokenHandler();
@@ -35,7 +48,8 @@ public Task<string> CreateTokenAsync(string userName, IList<Claim>? claims = nul
3548
return Task.FromResult(token);
3649
}
3750

38-
public async Task<ClaimsPrincipal> ValidateTokenAsync(string token, bool validateLifetime = true)
51+
/// <inheritdoc />
52+
public virtual async Task<ClaimsPrincipal> ValidateTokenAsync(string token, bool validateLifetime = true)
3953
{
4054
var tokenHandler = new JsonWebTokenHandler();
4155

@@ -46,23 +60,23 @@ public async Task<ClaimsPrincipal> ValidateTokenAsync(string token, bool validat
4660

4761
var tokenValidationParameters = new TokenValidationParameters
4862
{
49-
AuthenticationType = jwtBearerSettings.SchemeName,
50-
NameClaimType = jwtBearerSettings.NameClaimType,
51-
RoleClaimType = jwtBearerSettings.RoleClaimType,
52-
ValidateIssuer = jwtBearerSettings.Issuers?.Any() ?? false,
53-
ValidIssuers = jwtBearerSettings.Issuers,
54-
ValidateAudience = jwtBearerSettings.Audiences?.Any() ?? false,
55-
ValidAudiences = jwtBearerSettings.Audiences,
63+
AuthenticationType = JwtBearerSettings.SchemeName,
64+
NameClaimType = JwtBearerSettings.NameClaimType,
65+
RoleClaimType = JwtBearerSettings.RoleClaimType,
66+
ValidateIssuer = JwtBearerSettings.Issuers?.Any() ?? false,
67+
ValidIssuers = JwtBearerSettings.Issuers,
68+
ValidateAudience = JwtBearerSettings.Audiences?.Any() ?? false,
69+
ValidAudiences = JwtBearerSettings.Audiences,
5670
ValidateIssuerSigningKey = true,
57-
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtBearerSettings.SecurityKey)),
71+
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtBearerSettings.SecurityKey)),
5872
RequireExpirationTime = true,
5973
ValidateLifetime = validateLifetime,
60-
ClockSkew = jwtBearerSettings.ClockSkew
74+
ClockSkew = JwtBearerSettings.ClockSkew
6175
};
6276

6377
var validationResult = await tokenHandler.ValidateTokenAsync(token, tokenValidationParameters);
6478

65-
if (!validationResult.IsValid || validationResult.SecurityToken is not JsonWebToken jsonWebToken || jsonWebToken.Alg != jwtBearerSettings.Algorithm)
79+
if (!validationResult.IsValid || validationResult.SecurityToken is not JsonWebToken jsonWebToken || jsonWebToken.Alg != JwtBearerSettings.Algorithm)
6680
{
6781
throw new SecurityTokenException("Token is expired or invalid", validationResult.Exception);
6882
}
@@ -71,12 +85,13 @@ public async Task<ClaimsPrincipal> ValidateTokenAsync(string token, bool validat
7185
return principal;
7286
}
7387

74-
public async Task<string> RefreshTokenAsync(string token, bool validateLifetime, DateTime? absoluteExpiration = null)
88+
/// <inheritdoc />
89+
public virtual async Task<string> RefreshTokenAsync(string token, bool validateLifetime, DateTime? absoluteExpiration = null)
7590
{
7691
var principal = await ValidateTokenAsync(token, validateLifetime);
7792
var claims = (principal.Identity as ClaimsIdentity)!.Claims.ToList();
7893

79-
var userName = claims.First(c => c.Type == jwtBearerSettings.NameClaimType).Value;
94+
var userName = claims.First(c => c.Type == JwtBearerSettings.NameClaimType).Value;
8095
var issuer = claims.FirstOrDefault(c => c.Type == JwtRegisteredClaimNames.Iss)?.Value;
8196
var audience = claims.FirstOrDefault(c => c.Type == JwtRegisteredClaimNames.Aud)?.Value;
8297

0 commit comments

Comments
 (0)