8000 +dynamic claim variables by embix · Pull Request #855 · ThreeMammals/Ocelot · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

+dynamic claim variables #855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
8000
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 56 additions & 8 deletions src/Ocelot/Authorisation/ClaimsAuthoriser.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text.RegularExpressions;

using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Middleware;
using Ocelot.Responses;
using Ocelot.Values;

namespace Ocelot.Authorisation
{
Expand All @@ -15,8 +22,11 @@ public ClaimsAuthoriser(IClaimsParser claimsParser)
8000 _claimsParser = claimsParser;
}

public Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, Dictionary<string, string> routeClaimsRequirement)
{
public Response<bool> Authorise(
ClaimsPrincipal claimsPrincipal,
Dictionary<string, string> routeClaimsRequirement,
List<PlaceholderNameAndValue> urlPathPlaceholderNameAndValues
){
foreach (var required in routeClaimsRequirement)
{
var values = _claimsParser.GetValuesByClaimType(claimsPrincipal.Claims, required.Key);
Expand All @@ -27,12 +37,50 @@ public Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, Dictionary<stri
}

if (values.Data != null)
{
var authorised = values.Data.Contains(required.Value);
if (!authorised)
{
// dynamic claim
var match = Regex.Match(required.Value, @"^{(?<variable>.+)}$");
if (match.Success)
{
return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
$"claim value: {string.Join(", ", values.Data)} is not the same as required value: {required.Value} for type: {required.Key}"));
var variableName = match.Captures[0].Value;

var matchingPlaceholders = urlPathPlaceholderNameAndValues.Where(p => p.Name.Equals(variableName)).Take(2).ToArray();
if (matchingPlaceholders.Length == 1)
{
// match
var actualValue = matchingPlaceholders[0].Value;
var authorised = values.Data.Contains(actualValue);
if (!authorised)
{
return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
$"dynamic claim value for {variableName} of {string.Join(", ", values.Data)} is not the same as required value: {actualValue}"));
}
}
else
{
// config error
if (matchingPlaceholders.Length == 0)
{
return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
$"config error: requires variable claim value: {variableName} placeholders does not contain that variable: {string.Join(", ", urlPathPlaceholderNameAndValues.Select(p=>p.Name))}"));
}
else
{
return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
$"config error: requires variable claim value: {required.Value} but placeholders are ambiguou 10000 s: {string.Join(", ", urlPathPlaceholderNameAndValues.Where(p=>p.Name.Equals(variableName)).Select(p => p.Value))}"));
}
}

}
else
{
// static claim
var authorised = values.Data.Contains(required.Value);
if (!authorised)
{
return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
$"claim value: {string.Join(", ", values.Data)} is not the same as required value: {required.Value} for type: {required.Key}"));
}
}
}
else
Expand Down
10 changes: 9 additions & 1 deletion src/Ocelot/Authorisation/IClaimsAuthoriser.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
using System.Security.Claims;

using Ocelot.Configuration;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Responses;
using Ocelot.Values;

namespace Ocelot.Authorisation
{
using System.Collections.Generic;

public interface IClaimsAuthoriser
{
Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, Dictionary<string, string> routeClaimsRequirement);
Response<bool> Authorise(
ClaimsPrincipal claimsPrincipal,
Dictionary<string, string> routeClaimsRequirement,
List<PlaceholderNameAndValue> urlPathPlaceholderNameAndValues
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ public async Task Invoke(DownstreamContext context)
if (IsAuthorisedRoute(context.DownstreamReRoute))
{
Logger.LogInformation("route is authorised");
var authorised = _claimsAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.RouteClaimsRequirement);

var authorised = _claimsAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.RouteClaimsRequirement, context.TemplatePlaceholderNameAndValues);

if (authorised.IsError)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,21 @@ private void GivenTheDownStreamRouteIs(List<PlaceholderNameAndValue> templatePla
private void GivenTheAuthServiceReturns(Response<bool> expected)
{
_authService
.Setup(x => x.Authorise(It.IsAny<ClaimsPrincipal>(), It.IsAny<Dictionary<string, string>>()))
.Setup(x => x.Authorise(
It.IsAny<ClaimsPrincipal>(),
It.IsAny<Dictionary<string, string>>(),
It.IsAny<List<PlaceholderNameAndValue>>()))
.Returns(expected);
}

private void ThenTheAuthServiceIsCalledCorrectly()
{
_authService
.Verify(x => x.Authorise(It.IsAny<ClaimsPrincipal>(),
It.IsAny<Dictionary<string, string>>()), Times.Once);
.Verify(x => x.Authorise(
It.IsAny<ClaimsPrincipal>(),
It.IsAny<Dictionary<string, string>>(),
It.IsAny<List<PlaceholderNameAndValue>>())
, Times.Once);
}
}
}
52 changes: 51 additions & 1 deletion test/Ocelot.UnitTests/Authorization/ClaimsAuthoriserTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
using System.Collections.Generic;
using System.Security.Claims;
using Ocelot.Authorisation;
using Ocelot.Configuration;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Responses;
using Ocelot.Values;

using Shouldly;
using TestStack.BDDfy;
using Xunit;
Expand All @@ -15,6 +19,7 @@ public class ClaimsAuthoriserTests
private readonly ClaimsAuthoriser _claimsAuthoriser;
private ClaimsPrincipal _claimsPrincipal;
private Dictionary<string, string> _requirement;
private List<PlaceholderNameAndValue> _urlPathPlaceholderNameAndValues;
private Response<bool> _result;

public ClaimsAuthoriserTests()
Expand All @@ -38,6 +43,46 @@ public void should_authorise_user()
.BDDfy();
}

[Fact]
public void should_authorize_dynamic_user()
{
this.Given(x => x.GivenAClaimsPrincipal(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
{
new Claim("userid", "14"),
}))))
.And(x => x.GivenARouteClaimsRequirement(new Dictionary<string, string>
{
{"userid", "{userId}"}
}))
.And(x => x.GivenAPlaceHolderNameAndValueList(new List<PlaceholderNameAndValue>
{
new PlaceholderNameAndValue("{userId}", "14")
}))
.When(x => x.WhenICallTheAuthoriser())
.Then(x => x.ThenTheUserIsAuthorised())
.BDDfy();
}

[Fact]
public void should_not_authorize_dynamic_user()
{
this.Given(x => x.GivenAClaimsPrincipal(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
{
new Claim("userid", "15"),
}))))
.And(x => x.GivenARouteClaimsRequirement(new Dictionary<string, string>
{
{"userid", "{userId}"}
}))
.And(x => x.GivenAPlaceHolderNameAndValueList(new List<PlaceholderNameAndValue>
{
new PlaceholderNameAndValue("{userId}", "14")
}))
.When(x => x.WhenICallTheAuthoriser())
.Then(x => x.ThenTheUserIsntAuthorised())
.BDDfy();
}

[Fact]
public void should_authorise_user_multiple_claims_of_same_type()
{
Expand Down Expand Up @@ -78,9 +123,14 @@ private void GivenARouteClaimsRequirement(Dictionary<string, string> requirement
_requirement = requirement;
}

private void GivenAPlaceHolderNameAndValueList(List<PlaceholderNameAndValue> urlPathPlaceholderNameAndValues)
{
_urlPathPlaceholderNameAndValues = urlPathPlaceholderNameAndValues;
}

private void WhenICallTheAuthoriser()
{
_result = _claimsAuthoriser.Authorise(_claimsPrincipal, _requirement);
_result = _claimsAuthoriser.Authorise(_claimsPrincipal, _requirement, _urlPathPlaceholderNameAndValues);
}

private void ThenTheUserIsAuthorised()
Expand Down
0