Redesign IdentityModelAuthenticationService

pull/1100/head
Halil ibrahim Kalkan 7 years ago
parent b74d703c03
commit 09298d4d9a

@ -13,11 +13,12 @@ namespace Volo.Abp.Http.Client.IdentityModel
{
public IHttpContextAccessor HttpContextAccessor { get; set; }
protected IIdentityModelHttpClientAuthenticator IdentityModelHttpClientAuthenticator { get; }
protected IIdentityModelAuthenticationService IdentityModelAuthenticationService { get; }
public IdentityModelRemoteServiceHttpClientAuthenticator(IIdentityModelHttpClientAuthenticator identityModelHttpClientAuthenticator)
public IdentityModelRemoteServiceHttpClientAuthenticator(
IIdentityModelAuthenticationService identityModelAuthenticationService)
{
IdentityModelHttpClientAuthenticator = identityModelHttpClientAuthenticator;
IdentityModelAuthenticationService = identityModelAuthenticationService;
}
public async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context)
@ -32,7 +33,7 @@ namespace Volo.Abp.Http.Client.IdentityModel
}
}
await IdentityModelHttpClientAuthenticator.AuthenticateAsync(
await IdentityModelAuthenticationService.TryAuthenticateAsync(
context.Client,
context.RemoteService.GetIdentityClient()
);

@ -0,0 +1,17 @@
using System.Net.Http;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityModel
{
//TODO: Re-consider this interface!
public interface IIdentityModelAuthenticationService
{
Task<bool> TryAuthenticateAsync(
[NotNull] HttpClient client,
string identityClientName = null);
Task<string> GetAccessTokenAsync(
IdentityClientConfiguration configuration);
}
}

@ -1,9 +0,0 @@
using System.Threading.Tasks;
namespace Volo.Abp.IdentityModel
{
public interface IIdentityModelHttpClientAuthenticator
{
Task AuthenticateAsync(IdentityModelHttpClientAuthenticateContext context);
}
}

@ -77,12 +77,16 @@ namespace Volo.Abp.IdentityModel
}
public IdentityClientConfiguration(
string authority,
string scope,
string clientId,
string clientSecret,
string grantType = OidcConstants.GrantTypes.ClientCredentials,
string userName = null,
string userPassword = null)
{
this[nameof(Authority)] = authority;
this[nameof(Scope)] = scope;
this[nameof(ClientId)] = clientId;
this[nameof(ClientSecret)] = clientSecret;
this[nameof(GrantType)] = grantType;

@ -1,78 +1,89 @@
using System;
using System.Collections.Generic;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using IdentityModel;
using IdentityModel;
using IdentityModel.Client;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.IdentityModel
{
[Dependency(ReplaceServices = true)]
public class IdentityModelHttpClientAuthenticator : IIdentityModelHttpClientAuthenticator, ITransientDependency
public class IdentityModelAuthenticationService : IIdentityModelAuthenticationService, ITransientDependency
{
public ILogger<IdentityModelHttpClientAuthenticator> Logger { get; set; }
public ILogger<IdentityModelAuthenticationService> Logger { get; set; }
protected IdentityClientOptions ClientOptions { get; }
public IdentityModelHttpClientAuthenticator(
public IdentityModelAuthenticationService(
IOptions<IdentityClientOptions> options)
{
ClientOptions = options.Value;
Logger = NullLogger<IdentityModelHttpClientAuthenticator>.Instance;
Logger = NullLogger<IdentityModelAuthenticationService>.Instance;
}
public async Task AuthenticateAsync(IdentityModelHttpClientAuthenticateContext context)
public async Task<bool> TryAuthenticateAsync(
[NotNull] HttpClient client,
string identityClientName = null)
{
var accessToken = await GetAccessTokenFromServerOrNullAsync(context);
if (accessToken != null)
var accessToken = await GetAccessTokenOrNullAsync(identityClientName);
if (accessToken == null)
{
//TODO: "Bearer" should be configurable
context.Client.DefaultRequestHeaders.Authorization
= new AuthenticationHeaderValue("Bearer", accessToken);
return false;
}
}
protected virtual async Task<string> GetAccessTokenFromServerOrNullAsync(IdentityModelHttpClientAuthenticateContext context)
{
//TODO: Better logging
SetAccessToken(client, accessToken);
return true;
var configuration = GetClientConfiguration(context);
}
protected virtual async Task<string> GetAccessTokenOrNullAsync(string identityClientName)
{
var configuration = GetClientConfiguration(identityClientName);
if (configuration == null)
{
Logger.LogWarning($"Could not find {nameof(IdentityClientConfiguration)} for {context.IdentityClientName}. Either define a configuration for {context.IdentityClientName} or set a default configuration.");
Logger.LogWarning($"Could not find {nameof(IdentityClientConfiguration)} for {identityClientName}. Either define a configuration for {identityClientName} or set a default configuration.");
return null;
}
return await GetAccessTokenAsync(configuration);
}
public virtual async Task<string> GetAccessTokenAsync(IdentityClientConfiguration configuration)
{
var discoveryResponse = await GetDiscoveryResponse(configuration);
if (discoveryResponse.IsError)
{
Logger.LogError($"Could not retrieve the OpenId Connect discovery document! ErrorType: {discoveryResponse.ErrorType}. Error: {discoveryResponse.Error}");
return null;
throw new AbpException($"Could not retrieve the OpenId Connect discovery document! ErrorType: {discoveryResponse.ErrorType}. Error: {discoveryResponse.Error}");
}
var tokenResponse = await GetTokenResponse(discoveryResponse, configuration);
if (tokenResponse.IsError)
{
Logger.LogError($"Could not get token from the OpenId Connect server! ErrorType: {tokenResponse.ErrorType}. Error: {tokenResponse.Error}. ErrorDescription: {tokenResponse.ErrorDescription}. HttpStatusCode: {tokenResponse.HttpStatusCode}");
return null;
throw new AbpException($"Could not get token from the OpenId Connect server! ErrorType: {tokenResponse.ErrorType}. Error: {tokenResponse.Error}. ErrorDescription: {tokenResponse.ErrorDescription}. HttpStatusCode: {tokenResponse.HttpStatusCode}");
}
return tokenResponse.AccessToken;
}
private IdentityClientConfiguration GetClientConfiguration(IdentityModelHttpClientAuthenticateContext context)
protected virtual void SetAccessToken(HttpClient client, string accessToken)
{
//TODO: "Bearer" should be configurable
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}
private IdentityClientConfiguration GetClientConfiguration(string identityClientName = null)
{
if (context.IdentityClientName.IsNullOrEmpty())
if (identityClientName.IsNullOrEmpty())
{
return ClientOptions.IdentityClients.Default;
}
return ClientOptions.IdentityClients.GetOrDefault(context.IdentityClientName) ??
return ClientOptions.IdentityClients.GetOrDefault(identityClientName) ??
ClientOptions.IdentityClients.Default;
}

@ -1,25 +0,0 @@
using System.Net.Http;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityModel
{
public class IdentityModelHttpClientAuthenticateContext
{
public HttpClient Client { get; }
/// <summary>
/// The identity client name configured with the <see cref="IdentityClientOptions"/>.
/// </summary>
public string IdentityClientName { get; }
/// <param name="client"><see cref="HttpClient"/> object to be authenticated</param>
/// <param name="identityClientName">The identity client name configured with the <see cref="IdentityClientOptions"/>.</param>
public IdentityModelHttpClientAuthenticateContext(
[NotNull] HttpClient client,
string identityClientName = null)
{
Client = Check.NotNull(client, nameof(client));
IdentityClientName = identityClientName;
}
}
}

@ -1,27 +0,0 @@
using System.Net.Http;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityModel
{
public static class IdentityModelHttpClientAuthenticatorExtensions
{
/// <param name="authenticator">Authenticator object</param>
/// <param name="client"><see cref="HttpClient"/> object to be authenticated</param>
/// <param name="identityClientName">The identity client name configured with the <see cref="IdentityClientOptions"/>.</param>
public static Task AuthenticateAsync(
[NotNull] this IIdentityModelHttpClientAuthenticator authenticator,
[NotNull] HttpClient client,
string identityClientName = null)
{
Check.NotNull(authenticator, nameof(authenticator));
return authenticator.AuthenticateAsync(
new IdentityModelHttpClientAuthenticateContext(
client,
identityClientName
)
);
}
}
}
Loading…
Cancel
Save