mirror of https://github.com/abpframework/abp.git
7 changed files with 67 additions and 95 deletions
@ -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); |
|
||||
} |
|
||||
} |
|
||||
@ -1,78 +1,89 @@ |
|||||
using System; |
using IdentityModel; |
||||
using System.Collections.Generic; |
|
||||
using System.Net.Http.Headers; |
|
||||
using System.Threading.Tasks; |
|
||||
using IdentityModel; |
|
||||
using IdentityModel.Client; |
using IdentityModel.Client; |
||||
|
using JetBrains.Annotations; |
||||
using Microsoft.Extensions.Logging; |
using Microsoft.Extensions.Logging; |
||||
using Microsoft.Extensions.Logging.Abstractions; |
using Microsoft.Extensions.Logging.Abstractions; |
||||
using Microsoft.Extensions.Options; |
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; |
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
namespace Volo.Abp.IdentityModel |
namespace Volo.Abp.IdentityModel |
||||
{ |
{ |
||||
[Dependency(ReplaceServices = true)] |
[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; } |
protected IdentityClientOptions ClientOptions { get; } |
||||
|
|
||||
public IdentityModelHttpClientAuthenticator( |
public IdentityModelAuthenticationService( |
||||
IOptions<IdentityClientOptions> options) |
IOptions<IdentityClientOptions> options) |
||||
{ |
{ |
||||
ClientOptions = options.Value; |
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); |
var accessToken = await GetAccessTokenOrNullAsync(identityClientName); |
||||
|
if (accessToken == null) |
||||
if (accessToken != null) |
|
||||
{ |
{ |
||||
//TODO: "Bearer" should be configurable
|
return false; |
||||
context.Client.DefaultRequestHeaders.Authorization |
|
||||
= new AuthenticationHeaderValue("Bearer", accessToken); |
|
||||
} |
} |
||||
} |
|
||||
|
|
||||
protected virtual async Task<string> GetAccessTokenFromServerOrNullAsync(IdentityModelHttpClientAuthenticateContext context) |
SetAccessToken(client, accessToken); |
||||
{ |
return true; |
||||
//TODO: Better logging
|
|
||||
|
|
||||
var configuration = GetClientConfiguration(context); |
} |
||||
|
|
||||
|
protected virtual async Task<string> GetAccessTokenOrNullAsync(string identityClientName) |
||||
|
{ |
||||
|
var configuration = GetClientConfiguration(identityClientName); |
||||
if (configuration == null) |
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 null; |
||||
} |
} |
||||
|
|
||||
|
return await GetAccessTokenAsync(configuration); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<string> GetAccessTokenAsync(IdentityClientConfiguration configuration) |
||||
|
{ |
||||
var discoveryResponse = await GetDiscoveryResponse(configuration); |
var discoveryResponse = await GetDiscoveryResponse(configuration); |
||||
if (discoveryResponse.IsError) |
if (discoveryResponse.IsError) |
||||
{ |
{ |
||||
Logger.LogError($"Could not retrieve the OpenId Connect discovery document! ErrorType: {discoveryResponse.ErrorType}. Error: {discoveryResponse.Error}"); |
throw new AbpException($"Could not retrieve the OpenId Connect discovery document! ErrorType: {discoveryResponse.ErrorType}. Error: {discoveryResponse.Error}"); |
||||
return null; |
|
||||
} |
} |
||||
|
|
||||
var tokenResponse = await GetTokenResponse(discoveryResponse, configuration); |
var tokenResponse = await GetTokenResponse(discoveryResponse, configuration); |
||||
if (tokenResponse.IsError) |
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}"); |
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 null; |
|
||||
} |
} |
||||
|
|
||||
return tokenResponse.AccessToken; |
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.Default; |
||||
} |
} |
||||
|
|
||||
return ClientOptions.IdentityClients.GetOrDefault(context.IdentityClientName) ?? |
return ClientOptions.IdentityClients.GetOrDefault(identityClientName) ?? |
||||
ClientOptions.IdentityClients.Default; |
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…
Reference in new issue