-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat:add stack caller * feat:delete stackcaller buildingblock * feat:delete stackcaller test * feat:pr * refactor:tokenprovider * feat:Func
- Loading branch information
Showing
20 changed files
with
324 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
25 changes: 25 additions & 0 deletions
25
src/Contrib/StackSdks/Masa.Contrib.StackSdks.Caller/AuthenticationService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Copyright (c) MASA Stack All rights reserved. | ||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information. | ||
|
||
namespace Masa.Contrib.StackSdks.Caller; | ||
|
||
public class AuthenticationService : IAuthenticationService | ||
{ | ||
private readonly TokenProvider _tokenProvider; | ||
private readonly JwtTokenValidator _jwtTokenValidator; | ||
|
||
public AuthenticationService(TokenProvider tokenProvider, | ||
JwtTokenValidator jwtTokenValidator) | ||
{ | ||
_tokenProvider = tokenProvider; | ||
_jwtTokenValidator = jwtTokenValidator; | ||
} | ||
|
||
public async Task ExecuteAsync(HttpRequestMessage requestMessage) | ||
{ | ||
await _jwtTokenValidator.ValidateTokenAsync(_tokenProvider); | ||
|
||
if (!_tokenProvider.AccessToken.IsNullOrWhiteSpace()) | ||
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _tokenProvider.AccessToken); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/Contrib/StackSdks/Masa.Contrib.StackSdks.Caller/ClientRefreshTokenOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Copyright (c) MASA Stack All rights reserved. | ||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information. | ||
|
||
namespace Masa.Contrib.StackSdks.Caller; | ||
|
||
public class ClientRefreshTokenOptions | ||
{ | ||
public string ClientId { get; set; } = string.Empty; | ||
|
||
public string ClientSecret { get; set; } = string.Empty; | ||
} |
95 changes: 95 additions & 0 deletions
95
src/Contrib/StackSdks/Masa.Contrib.StackSdks.Caller/JwtTokenValidator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// Copyright (c) MASA Stack All rights reserved. | ||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information. | ||
|
||
namespace Masa.Contrib.StackSdks.Caller; | ||
|
||
public class JwtTokenValidator | ||
{ | ||
readonly JwtTokenValidatorOptions _jwtTokenValidatorOptions; | ||
readonly ClientRefreshTokenOptions _clientRefreshTokenOptions; | ||
readonly HttpClient _httpClient; | ||
readonly ILogger<JwtTokenValidator>? _logger; | ||
|
||
public JwtTokenValidator( | ||
IOptions<JwtTokenValidatorOptions> jwtTokenValidatorOptions, | ||
HttpClient httpClient, | ||
IOptions<ClientRefreshTokenOptions> clientRefreshTokenOptions, | ||
ILogger<JwtTokenValidator>? logger) | ||
{ | ||
_jwtTokenValidatorOptions = jwtTokenValidatorOptions.Value; | ||
_httpClient = httpClient; | ||
_clientRefreshTokenOptions = clientRefreshTokenOptions.Value; | ||
_logger = logger; | ||
} | ||
|
||
public async Task ValidateTokenAsync(TokenProvider tokenProvider) | ||
{ | ||
var discoveryDocument = await _httpClient.GetDiscoveryDocumentAsync(_jwtTokenValidatorOptions.AuthorityEndpoint); | ||
var validationParameters = new TokenValidationParameters | ||
{ | ||
ValidateLifetime = _jwtTokenValidatorOptions.ValidateLifetime, | ||
ValidateAudience = _jwtTokenValidatorOptions.ValidateAudience, | ||
ValidateIssuer = _jwtTokenValidatorOptions.ValidateIssuer, | ||
ValidIssuer = discoveryDocument.Issuer, | ||
ValidAudiences = _jwtTokenValidatorOptions.ValidAudiences, | ||
ValidateIssuerSigningKey = true, | ||
IssuerSigningKeys = GetIssuerSigningKeys(discoveryDocument) | ||
}; | ||
JwtSecurityTokenHandler handler = new(); | ||
handler.InboundClaimTypeMap.Clear(); | ||
try | ||
{ | ||
handler.ValidateToken(tokenProvider.AccessToken, validationParameters, out SecurityToken _); | ||
} | ||
catch (SecurityTokenExpiredException) | ||
{ | ||
if (!string.IsNullOrEmpty(tokenProvider.RefreshToken)) | ||
{ | ||
var tokenClient = new TokenClient(_httpClient, new TokenClientOptions | ||
{ | ||
Address = discoveryDocument.TokenEndpoint, | ||
ClientId = _clientRefreshTokenOptions.ClientId, | ||
ClientSecret = _clientRefreshTokenOptions.ClientSecret | ||
}); | ||
var tokenResult = await tokenClient.RequestRefreshTokenAsync(tokenProvider.RefreshToken).ConfigureAwait(false); | ||
if (tokenResult.IsError) | ||
{ | ||
_logger?.LogError("JwtTokenValidator failed, RefreshToken failed, Error Message: {Message}", tokenResult.Error); | ||
throw new UserFriendlyException($"JwtTokenValidator failed, RefreshToken failed, Error Message: {tokenResult.Error}"); | ||
} | ||
else | ||
{ | ||
tokenProvider.AccessToken = tokenResult.AccessToken; | ||
handler.ValidateToken(tokenProvider.AccessToken, validationParameters, out SecurityToken _); | ||
} | ||
} | ||
else | ||
{ | ||
_logger?.LogWarning( | ||
"RefreshToken is null,please AllowOfflineAccess value(true) and RequestedScopes should contains offline_access"); | ||
throw new UserFriendlyException("JwtTokenValidator failed, RefreshToken is null"); | ||
} | ||
} | ||
catch (Exception e) | ||
{ | ||
_logger?.LogError(e, "JwtTokenValidator failed"); | ||
throw new UserFriendlyException("JwtTokenValidator failed"); | ||
} | ||
} | ||
|
||
private static List<SecurityKey> GetIssuerSigningKeys(DiscoveryDocumentResponse discoveryDocument) | ||
{ | ||
var keys = new List<SecurityKey>(); | ||
foreach (var webKey in discoveryDocument.KeySet.Keys) | ||
{ | ||
var e = Base64Url.Decode(webKey.E); | ||
var n = Base64Url.Decode(webKey.N); | ||
var key = new RsaSecurityKey(new RSAParameters { Exponent = e, Modulus = n }) | ||
{ | ||
KeyId = webKey.Kid | ||
}; | ||
keys.Add(key); | ||
} | ||
return keys; | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/Contrib/StackSdks/Masa.Contrib.StackSdks.Caller/JwtTokenValidatorOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright (c) MASA Stack All rights reserved. | ||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information. | ||
|
||
namespace Masa.Contrib.StackSdks.Caller; | ||
|
||
public class JwtTokenValidatorOptions | ||
{ | ||
public string AuthorityEndpoint { get; set; } = string.Empty; | ||
|
||
public bool ValidateLifetime { get; set; } = true; | ||
|
||
public bool ValidateAudience { get; set; } | ||
|
||
public bool ValidateIssuer { get; set; } = true; | ||
|
||
public IEnumerable<string> ValidAudiences { get; set; } = Enumerable.Empty<string>(); | ||
} |
21 changes: 21 additions & 0 deletions
21
src/Contrib/StackSdks/Masa.Contrib.StackSdks.Caller/Masa.Contrib.StackSdks.Caller.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="IdentityModel" Version="$(IdentityModelPackageVersion)" /> | ||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(MicrosoftPackageVersion)" /> | ||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftPackageVersion)" /> | ||
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="$(IdentityPackageVersion)" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\..\BuildingBlocks\Service\Masa.BuildingBlocks.Service.Caller\Masa.BuildingBlocks.Service.Caller.csproj" /> | ||
<ProjectReference Include="..\..\Service\Caller\Masa.Contrib.Service.Caller.HttpClient\Masa.Contrib.Service.Caller.HttpClient.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
24 changes: 24 additions & 0 deletions
24
src/Contrib/StackSdks/Masa.Contrib.StackSdks.Caller/ServiceCollectionExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright (c) MASA Stack All rights reserved. | ||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information. | ||
|
||
namespace Masa.Contrib.StackSdks.Caller; | ||
|
||
public static class ServiceCollectionExtensions | ||
{ | ||
public static IServiceCollection AddStackCaller( | ||
this IServiceCollection services, | ||
Assembly assembly, | ||
Func<IServiceProvider, TokenProvider> tokenProvider, | ||
Action<JwtTokenValidatorOptions> jwtTokenValidatorOptions, | ||
Action<ClientRefreshTokenOptions>? clientRefreshTokenOptions = null) | ||
{ | ||
MasaArgumentException.ThrowIfNull(jwtTokenValidatorOptions); | ||
|
||
services.Configure(jwtTokenValidatorOptions); | ||
services.Configure(clientRefreshTokenOptions); | ||
services.AddScoped((serviceProvider) => { return tokenProvider.Invoke(serviceProvider); }); | ||
services.AddSingleton<JwtTokenValidator>(); | ||
services.AddAutoRegistrationCaller(assembly); | ||
return services; | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
src/Contrib/StackSdks/Masa.Contrib.StackSdks.Caller/StackHttpClientCaller.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright (c) MASA Stack All rights reserved. | ||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information. | ||
|
||
namespace Masa.Contrib.StackSdks.Caller; | ||
|
||
public abstract class StackHttpClientCaller : HttpClientCallerBase | ||
{ | ||
protected override void UseHttpClientPost(MasaHttpClientBuilder masaHttpClientBuilder) | ||
{ | ||
masaHttpClientBuilder.UseAuthentication(serviceProvider => new AuthenticationService( | ||
serviceProvider.GetRequiredService<TokenProvider>(), | ||
serviceProvider.GetRequiredService<JwtTokenValidator>() | ||
)); | ||
base.UseHttpClientPost(masaHttpClientBuilder); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/Contrib/StackSdks/Masa.Contrib.StackSdks.Caller/TokenProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Copyright (c) MASA Stack All rights reserved. | ||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information. | ||
|
||
namespace Masa.Contrib.StackSdks.Caller; | ||
|
||
public class TokenProvider | ||
{ | ||
public string? AccessToken { get; set; } | ||
|
||
public string? RefreshToken { get; set; } | ||
|
||
public string? IdToken { get; set; } | ||
} |
15 changes: 15 additions & 0 deletions
15
src/Contrib/StackSdks/Masa.Contrib.StackSdks.Caller/_Imports.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright (c) MASA Stack All rights reserved. | ||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information. | ||
|
||
global using IdentityModel; | ||
global using IdentityModel.Client; | ||
global using Masa.BuildingBlocks.Service.Caller; | ||
global using Masa.Contrib.Service.Caller.HttpClient; | ||
global using Microsoft.Extensions.DependencyInjection; | ||
global using Microsoft.Extensions.Logging; | ||
global using Microsoft.Extensions.Options; | ||
global using Microsoft.IdentityModel.Tokens; | ||
global using System.IdentityModel.Tokens.Jwt; | ||
global using System.Net.Http.Headers; | ||
global using System.Reflection; | ||
global using System.Security.Cryptography; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters