mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 09:38:14 +08:00
more auth stuff...nowhere near done
This commit is contained in:
45
src/Ocelot/Authorisation/AddClaims.cs
Normal file
45
src/Ocelot/Authorisation/AddClaims.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Ocelot.Claims.Parser;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.HeaderBuilder;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.Authorisation
|
||||
{
|
||||
public class AddClaims : IAddHeadersToRequest
|
||||
{
|
||||
private readonly IClaimsParser _claimsParser;
|
||||
|
||||
public AddClaims(IClaimsParser claimsParser)
|
||||
{
|
||||
_claimsParser = claimsParser;
|
||||
}
|
||||
|
||||
public Response SetHeadersOnContext(List<ClaimToHeader> configurationHeaderExtractorProperties, HttpContext context)
|
||||
{
|
||||
foreach (var config in configurationHeaderExtractorProperties)
|
||||
{
|
||||
var value = _claimsParser.GetValue(context.User.Claims, config.ClaimKey, config.Delimiter, config.Index);
|
||||
|
||||
if (value.IsError)
|
||||
{
|
||||
return new ErrorResponse(value.Errors);
|
||||
}
|
||||
|
||||
var exists = context.Request.Headers.FirstOrDefault(x => x.Key == config.HeaderKey);
|
||||
|
||||
if (!string.IsNullOrEmpty(exists.Key))
|
||||
{
|
||||
context.Request.Headers.Remove(exists);
|
||||
}
|
||||
|
||||
context.Request.Headers.Add(config.HeaderKey, new StringValues(value.Data));
|
||||
}
|
||||
|
||||
return new OkResponse();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.ScopedData;
|
||||
|
||||
namespace Ocelot.Authorisation
|
||||
@ -34,15 +35,21 @@ namespace Ocelot.Authorisation
|
||||
return;
|
||||
}
|
||||
|
||||
var authorised = _authoriser.Authorise(context.User, new RouteClaimsRequirement());
|
||||
//todo - call authoriser
|
||||
var authorised = new OkResponse<bool>(true); //_authoriser.Authorise(context.User, new RouteClaimsRequirement(new Dictionary<string, string>()));
|
||||
|
||||
if (authorised)
|
||||
if (authorised.IsError)
|
||||
{
|
||||
SetPipelineError(authorised.Errors);
|
||||
return;
|
||||
}
|
||||
|
||||
if (authorised.Data)
|
||||
{
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
//set an error
|
||||
SetPipelineError(new List<Error>
|
||||
{
|
||||
new UnauthorisedError($"{context.User.Identity.Name} unable to access {downstreamRoute.Data.ReRoute.UpstreamTemplate}")
|
||||
|
12
src/Ocelot/Authorisation/ClaimValueNotAuthorisedError.cs
Normal file
12
src/Ocelot/Authorisation/ClaimValueNotAuthorisedError.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Ocelot.Errors;
|
||||
|
||||
namespace Ocelot.Authorisation
|
||||
{
|
||||
public class ClaimValueNotAuthorisedError : Error
|
||||
{
|
||||
public ClaimValueNotAuthorisedError(string message)
|
||||
: base(message, OcelotErrorCode.ClaimValueNotAuthorisedError)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,53 @@
|
||||
using System.Security.Claims;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using Ocelot.Claims.Parser;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.Authorisation
|
||||
{
|
||||
public class ClaimsAuthoriser : IAuthoriser
|
||||
{
|
||||
public bool Authorise(ClaimsPrincipal claimsPrincipal, RouteClaimsRequirement routeClaimsRequirement)
|
||||
private readonly IClaimsParser _claimsParser;
|
||||
|
||||
public ClaimsAuthoriser(IClaimsParser claimsParser)
|
||||
{
|
||||
return false;
|
||||
_claimsParser = claimsParser;
|
||||
}
|
||||
|
||||
public Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, RouteClaimsRequirement routeClaimsRequirement)
|
||||
{
|
||||
foreach (var required in routeClaimsRequirement.RequiredClaimsAndValues)
|
||||
{
|
||||
var value = _claimsParser.GetValue(claimsPrincipal.Claims, required.Key, string.Empty, 0);
|
||||
|
||||
if (value.IsError)
|
||||
{
|
||||
return new ErrorResponse<bool>(value.Errors);
|
||||
}
|
||||
|
||||
if (value.Data != null)
|
||||
{
|
||||
var authorised = value.Data == required.Value;
|
||||
if (!authorised)
|
||||
{
|
||||
return new ErrorResponse<bool>(new List<Error>
|
||||
{
|
||||
new ClaimValueNotAuthorisedError(
|
||||
$"claim value: {value.Data} is not the same as required value: {required.Value} for type: {required.Key}")
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ErrorResponse<bool>(new List<Error>
|
||||
{
|
||||
new UserDoesNotHaveClaimError($"user does not have claim {required.Key}")
|
||||
});
|
||||
}
|
||||
}
|
||||
return new OkResponse<bool>(true);
|
||||
}
|
||||
}
|
||||
}
|
13
src/Ocelot/Authorisation/IAddClaims.cs
Normal file
13
src/Ocelot/Authorisation/IAddClaims.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.Authorisation
|
||||
{
|
||||
public interface IAddClaims
|
||||
{
|
||||
Response SetHeadersOnContext(List<ClaimToHeader> configurationHeaderExtractorProperties,
|
||||
HttpContext context);
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
using System.Security.Claims;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.Authorisation
|
||||
{
|
||||
public interface IAuthoriser
|
||||
{
|
||||
bool Authorise(ClaimsPrincipal claimsPrincipal,
|
||||
Response<bool> Authorise(ClaimsPrincipal claimsPrincipal,
|
||||
RouteClaimsRequirement routeClaimsRequirement);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Authorisation
|
||||
{
|
||||
public class RouteClaimsRequirement
|
||||
{
|
||||
public RouteClaimsRequirement(Dictionary<string, string> requiredClaimsAndValues)
|
||||
{
|
||||
RequiredClaimsAndValues = requiredClaimsAndValues;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> RequiredClaimsAndValues { get; private set; }
|
||||
}
|
||||
}
|
||||
|
12
src/Ocelot/Authorisation/UserDoesNotHaveClaimError.cs
Normal file
12
src/Ocelot/Authorisation/UserDoesNotHaveClaimError.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Ocelot.Errors;
|
||||
|
||||
namespace Ocelot.Authorisation
|
||||
{
|
||||
public class UserDoesNotHaveClaimError : Error
|
||||
{
|
||||
public UserDoesNotHaveClaimError(string message)
|
||||
: base(message, OcelotErrorCode.UserDoesNotHaveClaimError)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using Ocelot.Errors;
|
||||
|
||||
namespace Ocelot.HeaderBuilder.Parser
|
||||
namespace Ocelot.Claims.Parser
|
||||
{
|
||||
public class CannotFindClaimError : Error
|
||||
{
|
@ -4,7 +4,7 @@ using System.Security.Claims;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.HeaderBuilder.Parser
|
||||
namespace Ocelot.Claims.Parser
|
||||
{
|
||||
public class ClaimsParser : IClaimsParser
|
||||
{
|
@ -2,7 +2,7 @@
|
||||
using System.Security.Claims;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.HeaderBuilder.Parser
|
||||
namespace Ocelot.Claims.Parser
|
||||
{
|
||||
public interface IClaimsParser
|
||||
{
|
@ -7,6 +7,7 @@ namespace Ocelot.Configuration.Yaml
|
||||
public YamlReRoute()
|
||||
{
|
||||
AddHeadersToRequest = new Dictionary<string, string>();
|
||||
AddClaims = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public string DownstreamTemplate { get; set; }
|
||||
@ -14,5 +15,6 @@ namespace Ocelot.Configuration.Yaml
|
||||
public string UpstreamHttpMethod { get; set; }
|
||||
public YamlAuthenticationOptions AuthenticationOptions { get; set; }
|
||||
public Dictionary<string, string> AddHeadersToRequest { get; set; }
|
||||
public Dictionary<string, string> AddClaims { get; set; }
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Authentication.Handler.Creator;
|
||||
using Ocelot.Authentication.Handler.Factory;
|
||||
using Ocelot.Authorisation;
|
||||
using Ocelot.Claims.Parser;
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.Configuration.Parser;
|
||||
using Ocelot.Configuration.Provider;
|
||||
@ -15,7 +16,6 @@ using Ocelot.DownstreamRouteFinder.Finder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
|
||||
using Ocelot.HeaderBuilder;
|
||||
using Ocelot.HeaderBuilder.Parser;
|
||||
using Ocelot.RequestBuilder.Builder;
|
||||
using Ocelot.Requester;
|
||||
using Ocelot.Responder;
|
||||
|
@ -15,6 +15,8 @@
|
||||
ParsingConfigurationHeaderError,
|
||||
NoInstructionsError,
|
||||
InstructionNotForClaimsError,
|
||||
UnauthorizedError
|
||||
UnauthorizedError,
|
||||
ClaimValueNotAuthorisedError,
|
||||
UserDoesNotHaveClaimError
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Ocelot.Claims.Parser;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.HeaderBuilder.Parser;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.HeaderBuilder
|
||||
|
@ -20,7 +20,7 @@ namespace Ocelot.Middleware
|
||||
|
||||
builder.UseAuthenticationMiddleware();
|
||||
|
||||
//builder.UseAuthorisationMiddleware();
|
||||
builder.UseAuthorisationMiddleware();
|
||||
|
||||
builder.UseHttpRequestHeadersBuilderMiddleware();
|
||||
|
||||
|
Reference in New Issue
Block a user