last ...
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
using System.Linq;
|
||||
using xIds.Helpers;
|
||||
using IdentityModel;
|
||||
using xIds.Interfaces;
|
||||
using xCommons.Constants;
|
||||
@@ -5,10 +7,12 @@ using xCommons.Extensions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using xIdentityService.Constants;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace xIds.Providers
|
||||
@@ -41,18 +45,49 @@ namespace xIds.Providers
|
||||
/// <returns></returns>
|
||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
{
|
||||
//
|
||||
// Obtain the endpoint currently being executed
|
||||
var endpoint = Context.GetEndpoint();
|
||||
|
||||
//
|
||||
// Retrieve all AuthorizeAttribute metadata from the endpoint
|
||||
var hasApiKeyScheme = false;
|
||||
var apiKeyScopes = XApiKeyHelper.GetXApiKeyScopes();
|
||||
var apiKeyPolicies = XApiKeyHelper.GetXApiKeyPolicies();
|
||||
var authorizeAttributes = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>();
|
||||
if (
|
||||
apiKeyPolicies.HasChild() &&
|
||||
authorizeAttributes.HasChild()
|
||||
)
|
||||
{
|
||||
//
|
||||
// Retrieve a List of ApiKey Policies ...
|
||||
hasApiKeyScheme = authorizeAttributes.Any(attr =>
|
||||
apiKeyPolicies.Any(asc => asc.ToNormalString() == attr.Policy.ToNormalString()) ||
|
||||
attr.AuthenticationSchemes.ToNormalString() == XAuthenticationScheme.XApiKey.GetStringValue().ToNormalString()
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// if there is not any Policies for ApiKey Authentication
|
||||
// or Authorization, pass no Result ...
|
||||
if (!hasApiKeyScheme)
|
||||
{
|
||||
return AuthenticateResult.NoResult();
|
||||
}
|
||||
|
||||
//
|
||||
var apiKeyHeader = HeaderName;
|
||||
if (!Request.Headers.ContainsKey(apiKeyHeader))
|
||||
{
|
||||
return AuthenticateResult.NoResult();
|
||||
return AuthenticateResult.Fail("ApiKey not Exists ...");
|
||||
}
|
||||
|
||||
//
|
||||
var apiKey = Request.Headers[apiKeyHeader].ToString();
|
||||
if (apiKey.IsNullOrEmpty())
|
||||
{
|
||||
return AuthenticateResult.NoResult();
|
||||
return AuthenticateResult.Fail("ApiKey not Provided ...");
|
||||
}
|
||||
|
||||
// Extract Client IP ...
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using xIds.Helpers;
|
||||
using IdentityModel;
|
||||
using xIds.Interfaces;
|
||||
using xIdentityHelper;
|
||||
using xCommons.Constants;
|
||||
using xCommons.Extensions;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using xIdentityModels.Constants;
|
||||
using xIdentityService.Constants;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace xIds.Providers
|
||||
{
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Class | AttributeTargets.Method,
|
||||
AllowMultiple = false,
|
||||
Inherited = true
|
||||
)]
|
||||
public class XApiKeyAuthorizationFilter : AuthorizeAttribute, IAuthorizationFilter
|
||||
{
|
||||
// /// <summary>
|
||||
// /// Optional required scope for this endpoint.
|
||||
// /// Example: [XApiKeyAuthorizationFilter(RequiredScope = "read")]
|
||||
// /// </summary>
|
||||
// public string RequiredScope { get; set; }
|
||||
|
||||
// /// <summary>
|
||||
// /// If false, a missing header will only result in NoResult (anonymous)
|
||||
// /// instead of a 401. Default is true (must provide a key).
|
||||
// /// </summary>
|
||||
// public bool ApiKeyRequired { get; set; } = true;
|
||||
|
||||
// /// <summary>
|
||||
// /// Optional allowed scopes. If empty, no scope enforcement.
|
||||
// /// </summary>
|
||||
// public string[] AllowedScopes { get; set; }
|
||||
|
||||
public XApiKeyAuthorizationFilter() { }
|
||||
|
||||
/// <summary>
|
||||
/// Authorization Filtering ...
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public void OnAuthorization(AuthorizationFilterContext context)
|
||||
{
|
||||
Task.FromResult(OnAuthorizationAsync(context));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle Authorization Filtering Using Tasks ...
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
private async Task OnAuthorizationAsync(AuthorizationFilterContext context)
|
||||
{
|
||||
//
|
||||
// Access HttpContext ...
|
||||
var http = context.HttpContext;
|
||||
|
||||
//
|
||||
try
|
||||
{
|
||||
//
|
||||
// Obtain the endpoint currently being executed
|
||||
var endpoint = http.GetEndpoint();
|
||||
|
||||
//
|
||||
// Retrieve all AuthorizeAttribute metadata from the endpoint
|
||||
var hasApiKeyScheme = false;
|
||||
var apiKeyScopes = XApiKeyHelper.GetXApiKeyScopes();
|
||||
var apiKeyPolicies = XApiKeyHelper.GetXApiKeyPolicies();
|
||||
var authorizeAttributes = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>();
|
||||
if (
|
||||
apiKeyPolicies.HasChild() &&
|
||||
authorizeAttributes.HasChild()
|
||||
)
|
||||
{
|
||||
//
|
||||
// Retrieve a List of ApiKey Policies ...
|
||||
hasApiKeyScheme = authorizeAttributes.Any(attr =>
|
||||
apiKeyPolicies.Any(asc => asc.ToNormalString() == attr.Policy.ToNormalString())
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// if there is not any Policies for ApiKey Authentication
|
||||
// or Authorization, pass no Result ...
|
||||
if (!hasApiKeyScheme)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the application provider from DI ...
|
||||
var applicationProvider = http.RequestServices
|
||||
.GetService(typeof(IXApplicationProvider))
|
||||
as IXApplicationProvider;
|
||||
if (applicationProvider.IsNull())
|
||||
{
|
||||
//
|
||||
context.Result = new UnauthorizedObjectResult("Provider Service Not Registered ...");
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Checking Header ...
|
||||
var apiKeyHeader = XHeader.ApiKey.GetStringValue();
|
||||
var apiKeyAuthentication = XAuthenticationScheme.XApiKey.GetStringValue();
|
||||
if (!http.Request.Headers.ContainsKey(apiKeyHeader))
|
||||
{
|
||||
//
|
||||
context.Result = new UnauthorizedObjectResult("ApiKey not Exists ...");
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Extract ApiKey from Header ...
|
||||
var apiKey = http.Request.Headers[apiKeyHeader].ToString();
|
||||
if (apiKey.IsNullOrEmpty())
|
||||
{
|
||||
//
|
||||
context.Result = new UnauthorizedObjectResult("ApiKey not Provided ...");
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Extract Client IP ...
|
||||
var clientIP = http.Request.HttpContext.Connection.RemoteIpAddress?.ToString();
|
||||
|
||||
//
|
||||
// Validating ApiKey ...
|
||||
var validationResult = await applicationProvider
|
||||
.ValidateApiKey(
|
||||
apiKey: apiKey,
|
||||
clientIP: clientIP
|
||||
);
|
||||
if (validationResult.Errors.HasChild())
|
||||
{
|
||||
//
|
||||
var message = validationResult.Errors.ToListString('\n');
|
||||
context.Result = new UnauthorizedObjectResult(message);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Creating Claims ...
|
||||
var claims = new List<Claim> {
|
||||
//
|
||||
// Owner Identifier of API Key ...
|
||||
new(ClaimTypes.Name, validationResult.OwnerId),
|
||||
new(JwtClaimTypes.Subject, validationResult.OwnerId),
|
||||
//
|
||||
// Application Id ...
|
||||
new(XCustomClaims.ApplicationId, validationResult.ApplicationId.ToString()),
|
||||
//
|
||||
// Authentication Type ...
|
||||
new(XCustomClaims.AuthType, apiKeyAuthentication),
|
||||
};
|
||||
|
||||
//
|
||||
// Add Scopes ...
|
||||
if (validationResult.Scopes != null)
|
||||
{
|
||||
//
|
||||
foreach (var scope in validationResult.Scopes)
|
||||
{
|
||||
claims.Add(new Claim(JwtClaimTypes.Scope, scope));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create Principal and Ticket ...
|
||||
var identity = new ClaimsIdentity(claims, apiKeyAuthentication);
|
||||
var principal = new ClaimsPrincipal(identity);
|
||||
|
||||
//
|
||||
http.User = principal;
|
||||
}
|
||||
catch
|
||||
{
|
||||
context.Result = new UnauthorizedObjectResult("ApiKey authorization failed ...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user