mirror of https://github.com/abpframework/abp.git
13 changed files with 316 additions and 79 deletions
@ -1,12 +0,0 @@ |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.Http.Client.IdentityModel |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpHttpClientModule) |
|||
)] |
|||
public class AbpHttpClientIdentityModelModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -1,44 +0,0 @@ |
|||
using System.Net.Http.Headers; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authentication; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Http.Client.Authentication; |
|||
|
|||
namespace NewFolder.Abp.Http.Client.IdentityModel |
|||
{ |
|||
[Dependency(ReplaceServices = true)] |
|||
public class IdentityModelHttpClientAuthenticator : IHttpClientAuthenticator, ITransientDependency |
|||
{ |
|||
public IHttpContextAccessor HttpContextAccessor { get; set; } |
|||
|
|||
public async Task Authenticate(HttpClientAuthenticateContext context) |
|||
{ |
|||
var accessToken = await GetAccessTokenFromHttpContextOrNullAsync() ?? |
|||
await GetAccessTokenFromServerOrNullAsync(context); |
|||
|
|||
if (accessToken != null) |
|||
{ |
|||
//TODO: "Bearer" should be configurable
|
|||
context.Client.DefaultRequestHeaders.Authorization |
|||
= new AuthenticationHeaderValue("Bearer", accessToken); |
|||
} |
|||
} |
|||
|
|||
protected virtual Task<string> GetAccessTokenFromServerOrNullAsync(HttpClientAuthenticateContext context) |
|||
{ |
|||
return Task.FromResult((string) null); |
|||
} |
|||
|
|||
protected virtual async Task<string> GetAccessTokenFromHttpContextOrNullAsync() |
|||
{ |
|||
var httpContext = HttpContextAccessor?.HttpContext; |
|||
if (httpContext == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return await httpContext.GetTokenAsync("access_token"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.Http.Client.IdentityModel |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpHttpClientModule) |
|||
)] |
|||
public class AbpHttpClientIdentityModelModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
Configure<IdentityClientOptions>(configuration); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
using System.Collections.Generic; |
|||
using IdentityModel; |
|||
|
|||
namespace Volo.Abp.Http.Client.IdentityModel |
|||
{ |
|||
public class IdentityClientConfiguration : Dictionary<string, string> |
|||
{ |
|||
/// <summary>
|
|||
/// Possible values: "client_credentials" or "password".
|
|||
/// Default value: "client_credentials".
|
|||
/// </summary>
|
|||
public string GrantType |
|||
{ |
|||
get => this.GetOrDefault(nameof(GrantType)); |
|||
set => this[GrantType] = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Client Id.
|
|||
/// </summary>
|
|||
public string ClientId |
|||
{ |
|||
get => this.GetOrDefault(nameof(ClientId)); |
|||
set => this[ClientId] = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Client secret (as plain text - without hashed).
|
|||
/// </summary>
|
|||
public string ClientSecret |
|||
{ |
|||
get => this.GetOrDefault(nameof(ClientSecret)); |
|||
set => this[ClientSecret] = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// User name.
|
|||
/// Valid only if <see cref="GrantType"/> is "password".
|
|||
/// </summary>
|
|||
public string UserName |
|||
{ |
|||
get => this.GetOrDefault(nameof(UserName)); |
|||
set => this[UserName] = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Password of the <see cref="UserName"/>.
|
|||
/// Valid only if <see cref="GrantType"/> is "password".
|
|||
/// </summary>
|
|||
public string UserPassword |
|||
{ |
|||
get => this.GetOrDefault(nameof(UserPassword)); |
|||
set => this[UserPassword] = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Authority.
|
|||
/// </summary>
|
|||
public string Authority |
|||
{ |
|||
get => this.GetOrDefault(nameof(Authority)); |
|||
set => this[Authority] = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Scope.
|
|||
/// </summary>
|
|||
public string Scope |
|||
{ |
|||
get => this.GetOrDefault(nameof(Scope)); |
|||
set => this[Scope] = value; |
|||
} |
|||
|
|||
public IdentityClientConfiguration() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public IdentityClientConfiguration( |
|||
string clientId, |
|||
string clientSecret, |
|||
string grantType = OidcConstants.GrantTypes.ClientCredentials, |
|||
string userName = null, |
|||
string userPassword = null) |
|||
{ |
|||
this[nameof(ClientId)] = clientId; |
|||
this[nameof(ClientSecret)] = clientSecret; |
|||
this[nameof(GrantType)] = grantType; |
|||
this[nameof(UserName)] = userName; |
|||
this[nameof(UserPassword)] = userPassword; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.Http.Client.IdentityModel |
|||
{ |
|||
public class IdentityClientConfigurationDictionary : Dictionary<string, IdentityClientConfiguration> |
|||
{ |
|||
public const string DefaultName = "Default"; |
|||
|
|||
public IdentityClientConfiguration Default |
|||
{ |
|||
get => this.GetOrDefault(DefaultName); |
|||
set => this[DefaultName] = value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
namespace Volo.Abp.Http.Client.IdentityModel |
|||
{ |
|||
public class IdentityClientOptions |
|||
{ |
|||
public IdentityClientConfigurationDictionary IdentityClients { get; set; } |
|||
|
|||
public IdentityClientOptions() |
|||
{ |
|||
IdentityClients = new IdentityClientConfigurationDictionary(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,116 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Net.Http.Headers; |
|||
using System.Threading.Tasks; |
|||
using IdentityModel; |
|||
using IdentityModel.Client; |
|||
using Microsoft.AspNetCore.Authentication; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Http.Client.Authentication; |
|||
|
|||
namespace Volo.Abp.Http.Client.IdentityModel |
|||
{ |
|||
//TODO: This class should be optimized and improved:
|
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
public class IdentityModelHttpClientAuthenticator : IHttpClientAuthenticator, ITransientDependency |
|||
{ |
|||
public IHttpContextAccessor HttpContextAccessor { get; set; } |
|||
|
|||
protected IdentityClientOptions ClientOptions { get; } |
|||
|
|||
public IdentityModelHttpClientAuthenticator( |
|||
IOptions<IdentityClientOptions> options) |
|||
{ |
|||
ClientOptions = options.Value; |
|||
} |
|||
|
|||
public async Task Authenticate(HttpClientAuthenticateContext context) |
|||
{ |
|||
var accessToken = await GetAccessTokenFromHttpContextOrNullAsync() ?? |
|||
await GetAccessTokenFromServerOrNullAsync(context); |
|||
|
|||
if (accessToken != null) |
|||
{ |
|||
//TODO: "Bearer" should be configurable
|
|||
context.Client.DefaultRequestHeaders.Authorization |
|||
= new AuthenticationHeaderValue("Bearer", accessToken); |
|||
} |
|||
} |
|||
|
|||
protected virtual async Task<string> GetAccessTokenFromHttpContextOrNullAsync() |
|||
{ |
|||
var httpContext = HttpContextAccessor?.HttpContext; |
|||
if (httpContext == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return await httpContext.GetTokenAsync("access_token"); |
|||
} |
|||
|
|||
protected virtual async Task<string> GetAccessTokenFromServerOrNullAsync(HttpClientAuthenticateContext context) |
|||
{ |
|||
var configuration = GetClientConfiguration(context); |
|||
|
|||
if (configuration == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var discoveryResponse = await GetDiscoveryResponse(configuration); |
|||
if (discoveryResponse.IsError) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var tokenResponse = await GetTokenResponse(discoveryResponse, configuration); |
|||
if (tokenResponse.IsError) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return tokenResponse.AccessToken; |
|||
} |
|||
|
|||
private IdentityClientConfiguration GetClientConfiguration(HttpClientAuthenticateContext context) |
|||
{ |
|||
var identityClientName = context.RemoteService.GetIdentityClient(); |
|||
if (identityClientName.IsNullOrEmpty()) |
|||
{ |
|||
return ClientOptions.IdentityClients.Default; |
|||
} |
|||
|
|||
return ClientOptions.IdentityClients.GetOrDefault(identityClientName) ?? |
|||
ClientOptions.IdentityClients.Default; |
|||
} |
|||
|
|||
protected virtual async Task<DiscoveryResponse> GetDiscoveryResponse(IdentityClientConfiguration configuration) |
|||
{ |
|||
return await DiscoveryClient.GetAsync(configuration.Authority); |
|||
} |
|||
|
|||
protected virtual async Task<TokenResponse> GetTokenResponse(DiscoveryResponse discoveryResponse, IdentityClientConfiguration configuration) |
|||
{ |
|||
var tokenClient = new TokenClient(discoveryResponse.TokenEndpoint, configuration.ClientId, configuration.ClientSecret); |
|||
|
|||
switch (configuration.GrantType) |
|||
{ |
|||
case OidcConstants.GrantTypes.ClientCredentials: |
|||
return await tokenClient.RequestClientCredentialsAsync( |
|||
configuration.Scope |
|||
); |
|||
case OidcConstants.GrantTypes.Password: |
|||
return await tokenClient.RequestResourceOwnerPasswordAsync( |
|||
configuration.UserName, |
|||
configuration.UserPassword, |
|||
configuration.Scope |
|||
); |
|||
default: |
|||
throw new AbpException("Grant type was not implemented: " + configuration.GrantType); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.Http.Client |
|||
{ |
|||
public static class RemoteServiceConfigurationExtensions |
|||
{ |
|||
[CanBeNull] |
|||
public static string GetIdentityClient([NotNull] this RemoteServiceConfiguration configuration) |
|||
{ |
|||
Check.NotNullOrEmpty(configuration, nameof(configuration)); |
|||
|
|||
return configuration.GetOrDefault("IdentityClient"); |
|||
} |
|||
|
|||
public static RemoteServiceConfiguration SetIdentityClient([NotNull] this RemoteServiceConfiguration configuration, [CanBeNull] string value) |
|||
{ |
|||
configuration["IdentityClient"] = value; |
|||
return configuration; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue