parent
9726a26056
commit
f5200a1d55
17
Security.sln
17
Security.sln
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 2013
|
# Visual Studio 2013
|
||||||
VisualStudioVersion = 12.0.30401.0
|
VisualStudioVersion = 12.0.30411.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4D2B6A51-2F9F-44F5-8131-EA5CAC053652}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4D2B6A51-2F9F-44F5-8131-EA5CAC053652}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -13,6 +13,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Security.C
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "CookieSample", "samples\CookieSample\CookieSample.kproj", "{558C2C2A-AED8-49DE-BB60-D5F8AE06C714}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "CookieSample", "samples\CookieSample\CookieSample.kproj", "{558C2C2A-AED8-49DE-BB60-D5F8AE06C714}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{7BF11F3A-60B6-4796-B504-579C67FFBA34}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Security", "test\Microsoft.AspNet.Security.Test\Microsoft.AspNet.Security.kproj", "{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -53,6 +57,16 @@ Global
|
||||||
{558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|Mixed Platforms.Build.0 = Release|x86
|
{558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||||
{558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|x86.ActiveCfg = Release|x86
|
{558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|x86.ActiveCfg = Release|x86
|
||||||
{558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|x86.Build.0 = Release|x86
|
{558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|x86.Build.0 = Release|x86
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|Mixed Platforms.Build.0 = Debug|x86
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|Any CPU.ActiveCfg = Release|x86
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|x86.Build.0 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -61,5 +75,6 @@ Global
|
||||||
{0F174C63-1898-4024-9A3C-3FDF5CAE5C68} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
|
{0F174C63-1898-4024-9A3C-3FDF5CAE5C68} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
|
||||||
{15F1211B-B695-4A1C-B730-1AC58FC91090} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
|
{15F1211B-B695-4A1C-B730-1AC58FC91090} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
|
||||||
{558C2C2A-AED8-49DE-BB60-D5F8AE06C714} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
|
{558C2C2A-AED8-49DE-BB60-D5F8AE06C714} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
|
||||||
|
{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B} = {7BF11F3A-60B6-4796-B504-579C67FFBA34}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security.Authorization
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains authorization information used by <see cref="IAuthorizationPolicy"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class AuthorizationPolicyContext
|
||||||
|
{
|
||||||
|
public AuthorizationPolicyContext(IEnumerable<Claim> claims, ClaimsPrincipal user, object resource )
|
||||||
|
{
|
||||||
|
Claims = (claims ?? Enumerable.Empty<Claim>()).ToList();
|
||||||
|
User = user;
|
||||||
|
Resource = resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of claims the <see cref="IAuthorizationService"/> is checking.
|
||||||
|
/// </summary>
|
||||||
|
public IList<Claim> Claims { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The user to check the claims against.
|
||||||
|
/// </summary>
|
||||||
|
public ClaimsPrincipal User { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An optional resource associated to the check.
|
||||||
|
/// </summary>
|
||||||
|
public object Resource { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or set whether the permission will be granted to the user.
|
||||||
|
/// </summary>
|
||||||
|
public bool Authorized { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When set to <value>true</value>, the authorization check will be processed again.
|
||||||
|
/// </summary>
|
||||||
|
public bool Retry { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security.Authorization
|
||||||
|
{
|
||||||
|
public class DefaultAuthorizationService : IAuthorizationService
|
||||||
|
{
|
||||||
|
private readonly IList<IAuthorizationPolicy> _policies;
|
||||||
|
public int MaxRetries = 99;
|
||||||
|
|
||||||
|
public DefaultAuthorizationService(IEnumerable<IAuthorizationPolicy> policies)
|
||||||
|
{
|
||||||
|
_policies = policies.OrderBy(x => x.Order).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AuthorizeAsync(IEnumerable<Claim> claims, ClaimsPrincipal user)
|
||||||
|
{
|
||||||
|
return await AuthorizeAsync(claims, user, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Authorize(IEnumerable<Claim> claims, ClaimsPrincipal user)
|
||||||
|
{
|
||||||
|
return AuthorizeAsync(claims, user, null).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AuthorizeAsync(IEnumerable<Claim> claims, ClaimsPrincipal user, object resource)
|
||||||
|
{
|
||||||
|
var context = new AuthorizationPolicyContext(claims, user, resource);
|
||||||
|
|
||||||
|
foreach (var policy in _policies)
|
||||||
|
{
|
||||||
|
await policy.ApplyingAsync(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we only apply the policies for a limited number of times to prevent
|
||||||
|
// infinite loops
|
||||||
|
|
||||||
|
int retries;
|
||||||
|
for (retries = 0; retries < MaxRetries; retries++)
|
||||||
|
{
|
||||||
|
// we don't need to check for owned claims if the permission is already granted
|
||||||
|
if (!context.Authorized)
|
||||||
|
{
|
||||||
|
if (context.User != null)
|
||||||
|
{
|
||||||
|
if (context.Claims.Any(claim => user.HasClaim(claim.Type, claim.Value)))
|
||||||
|
{
|
||||||
|
context.Authorized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the retry flag
|
||||||
|
context.Retry = false;
|
||||||
|
|
||||||
|
// give a chance for policies to change claims or the grant
|
||||||
|
foreach (var policy in _policies)
|
||||||
|
{
|
||||||
|
await policy.ApplyAsync(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no policies have changed the context, stop checking
|
||||||
|
if (!context.Retry)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retries == MaxRetries)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Too many authorization retries.");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var policy in _policies)
|
||||||
|
{
|
||||||
|
await policy.AppliedAsync(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.Authorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Authorize(IEnumerable<Claim> claims, ClaimsPrincipal user, object resource)
|
||||||
|
{
|
||||||
|
return AuthorizeAsync(claims, user, resource).Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
namespace Microsoft.AspNet.Security.Authorization
|
||||||
|
{
|
||||||
|
public interface IAuthorizationPolicy
|
||||||
|
{
|
||||||
|
int Order { get; set; }
|
||||||
|
Task ApplyingAsync(AuthorizationPolicyContext context);
|
||||||
|
Task ApplyAsync(AuthorizationPolicyContext context);
|
||||||
|
Task AppliedAsync(AuthorizationPolicyContext context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security.Authorization
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Checks claims based permissions for a user.
|
||||||
|
/// </summary>
|
||||||
|
public interface IAuthorizationService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a user has specific claims.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="claims">The claims to check against a specific user.</param>
|
||||||
|
/// <param name="user">The user to check claims against.</param>
|
||||||
|
/// <returns><value>true</value> when the user fulfills one of the claims, <value>false</value> otherwise.</returns>
|
||||||
|
Task<bool> AuthorizeAsync(IEnumerable<Claim> claims, ClaimsPrincipal user);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a user has specific claims.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="claims">The claims to check against a specific user.</param>
|
||||||
|
/// <param name="user">The user to check claims against.</param>
|
||||||
|
/// <returns><value>true</value> when the user fulfills one of the claims, <value>false</value> otherwise.</returns>
|
||||||
|
bool Authorize(IEnumerable<Claim> claims, ClaimsPrincipal user);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a user has specific claims for a specific context obj.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="claims">The claims to check against a specific user.</param>
|
||||||
|
/// <param name="user">The user to check claims against.</param>
|
||||||
|
/// <param name="resource">The resource the claims should be check with.</param>
|
||||||
|
/// <returns><value>true</value> when the user fulfills one of the claims, <value>false</value> otherwise.</returns>
|
||||||
|
Task<bool> AuthorizeAsync(IEnumerable<Claim> claims, ClaimsPrincipal user, object resource);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a user has specific claims for a specific context obj.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="claims">The claims to check against a specific user.</param>
|
||||||
|
/// <param name="user">The user to check claims against.</param>
|
||||||
|
/// <param name="resource">The resource the claims should be check with.</param>
|
||||||
|
/// <returns><value>true</value> when the user fulfills one of the claims, <value>false</value> otherwise.</returns>
|
||||||
|
bool Authorize(IEnumerable<Claim> claims, ClaimsPrincipal user, object resource);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,10 @@
|
||||||
<Compile Include="AuthenticationMode.cs" />
|
<Compile Include="AuthenticationMode.cs" />
|
||||||
<Compile Include="AuthenticationOptions.cs" />
|
<Compile Include="AuthenticationOptions.cs" />
|
||||||
<Compile Include="AuthenticationTicket.cs" />
|
<Compile Include="AuthenticationTicket.cs" />
|
||||||
|
<Compile Include="Authorization\AuthorizationPolicyContext.cs" />
|
||||||
|
<Compile Include="Authorization\DefaultAuthorizationService.cs" />
|
||||||
|
<Compile Include="Authorization\IAuthorizationPolicy.cs" />
|
||||||
|
<Compile Include="Authorization\IAuthorizationService.cs" />
|
||||||
<Compile Include="CertificateSubjectKeyIdentifierValidator.cs" />
|
<Compile Include="CertificateSubjectKeyIdentifierValidator.cs" />
|
||||||
<Compile Include="CertificateSubjectPublicKeyInfoValidator.cs" />
|
<Compile Include="CertificateSubjectPublicKeyInfoValidator.cs" />
|
||||||
<Compile Include="CertificateThumbprintValidator.cs" />
|
<Compile Include="CertificateThumbprintValidator.cs" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,276 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Security.Authorization;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security.Test
|
||||||
|
{
|
||||||
|
public class DefaultAuthorizationServiceTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldAllowIfClaimIsPresent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
||||||
|
var user = new ClaimsPrincipal(
|
||||||
|
new ClaimsIdentity( new Claim[] { new Claim("Permission", "CanViewPage") }, "Basic")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldAllowIfClaimIsAmongValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
||||||
|
var user = new ClaimsPrincipal(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim("Permission", "CanViewPage"),
|
||||||
|
new Claim("Permission", "CanViewAnything")
|
||||||
|
},
|
||||||
|
"Basic")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldNotAllowIfClaimTypeIsNotPresent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
||||||
|
var user = new ClaimsPrincipal(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim("SomethingElse", "CanViewPage"),
|
||||||
|
},
|
||||||
|
"Basic")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldNotAllowIfClaimValueIsNotPresent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
||||||
|
var user = new ClaimsPrincipal(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim("Permission", "CanViewComment"),
|
||||||
|
},
|
||||||
|
"Basic")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldNotAllowIfNoClaims()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
||||||
|
var user = new ClaimsPrincipal(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[0],
|
||||||
|
"Basic")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldNotAllowIfUserIsNull()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
||||||
|
ClaimsPrincipal user = null;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldNotAllowIfUserIsNotAuthenticated()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
||||||
|
var user = new ClaimsPrincipal(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim("Permission", "CanViewComment"),
|
||||||
|
},
|
||||||
|
null)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldApplyPoliciesInOrder()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string result = "";
|
||||||
|
var policies = new IAuthorizationPolicy[] {
|
||||||
|
new FakePolicy() {
|
||||||
|
Order = 20,
|
||||||
|
ApplyingAsyncAction = (context) => { result += "20"; }
|
||||||
|
},
|
||||||
|
new FakePolicy() {
|
||||||
|
Order = -1,
|
||||||
|
ApplyingAsyncAction = (context) => { result += "-1"; }
|
||||||
|
},
|
||||||
|
new FakePolicy() {
|
||||||
|
Order = 30,
|
||||||
|
ApplyingAsyncAction = (context) => { result += "30"; }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var authorizationService = new DefaultAuthorizationService(policies);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(null, null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("-12030", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldInvokeApplyingApplyAppliedInOrder()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string result = "";
|
||||||
|
var policies = new IAuthorizationPolicy[] {
|
||||||
|
new FakePolicy() {
|
||||||
|
Order = 20,
|
||||||
|
ApplyingAsyncAction = (context) => { result += "Applying20"; },
|
||||||
|
ApplyAsyncAction = (context) => { result += "Apply20"; },
|
||||||
|
AppliedAsyncAction = (context) => { result += "Applied20"; }
|
||||||
|
},
|
||||||
|
new FakePolicy() {
|
||||||
|
Order = -1,
|
||||||
|
ApplyingAsyncAction = (context) => { result += "Applying-1"; },
|
||||||
|
ApplyAsyncAction = (context) => { result += "Apply-1"; },
|
||||||
|
AppliedAsyncAction = (context) => { result += "Applied-1"; }
|
||||||
|
},
|
||||||
|
new FakePolicy() {
|
||||||
|
Order = 30,
|
||||||
|
ApplyingAsyncAction = (context) => { result += "Applying30"; },
|
||||||
|
ApplyAsyncAction = (context) => { result += "Apply30"; },
|
||||||
|
AppliedAsyncAction = (context) => { result += "Applied30"; }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var authorizationService = new DefaultAuthorizationService(policies);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(null, null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("Applying-1Applying20Applying30Apply-1Apply20Apply30Applied-1Applied20Applied30", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldConvertNullClaimsToEmptyList()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
IList<Claim> claims = null;
|
||||||
|
var policies = new IAuthorizationPolicy[] {
|
||||||
|
new FakePolicy() {
|
||||||
|
Order = 20,
|
||||||
|
ApplyingAsyncAction = (context) => { claims = context.Claims; }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var authorizationService = new DefaultAuthorizationService(policies);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(null, null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(claims);
|
||||||
|
Assert.Equal(0, claims.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ShouldThrowWhenPoliciesDontStop()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var policies = new IAuthorizationPolicy[] {
|
||||||
|
new FakePolicy() {
|
||||||
|
ApplyAsyncAction = (context) => { context.Retry = true; }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var authorizationService = new DefaultAuthorizationService(policies);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
Exception ex = Assert.Throws<AggregateException>(() => authorizationService.Authorize(null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Check_ApplyCanMutateClaims()
|
||||||
|
{
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
var user = new ClaimsPrincipal(
|
||||||
|
new ClaimsIdentity( new Claim[] { new Claim("Permission", "CanDeleteComments") }, "Basic")
|
||||||
|
);
|
||||||
|
|
||||||
|
var policies = new IAuthorizationPolicy[] {
|
||||||
|
new FakePolicy() {
|
||||||
|
ApplyAsyncAction = (context) => {
|
||||||
|
// for instance, if user owns the comment
|
||||||
|
if(!context.Claims.Any(claim => claim.Type == "Permission" && claim.Value == "CanDeleteComments"))
|
||||||
|
{
|
||||||
|
context.Claims.Add(new Claim("Permission", "CanDeleteComments"));
|
||||||
|
context.Retry = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var authorizationService = new DefaultAuthorizationService(policies);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = authorizationService.Authorize(Enumerable.Empty<Claim>(), user);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(allowed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Security.Authorization;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security.Test
|
||||||
|
{
|
||||||
|
public class FakePolicy : IAuthorizationPolicy
|
||||||
|
{
|
||||||
|
|
||||||
|
public int Order { get; set; }
|
||||||
|
|
||||||
|
public Task ApplyingAsync(AuthorizationPolicyContext context)
|
||||||
|
{
|
||||||
|
if (ApplyingAsyncAction != null)
|
||||||
|
{
|
||||||
|
ApplyingAsyncAction(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task ApplyAsync(AuthorizationPolicyContext context)
|
||||||
|
{
|
||||||
|
if (ApplyAsyncAction != null)
|
||||||
|
{
|
||||||
|
ApplyAsyncAction(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task AppliedAsync(AuthorizationPolicyContext context)
|
||||||
|
{
|
||||||
|
if (AppliedAsyncAction != null)
|
||||||
|
{
|
||||||
|
AppliedAsyncAction(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action<AuthorizationPolicyContext> ApplyingAsyncAction { get; set;}
|
||||||
|
|
||||||
|
public Action<AuthorizationPolicyContext> ApplyAsyncAction { get; set;}
|
||||||
|
|
||||||
|
public Action<AuthorizationPolicyContext> AppliedAsyncAction { get; set;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="__ToolsVersion__" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">12.0</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\ProjectK\Microsoft.Web.ProjectK.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>8da26cd1-1302-4cfd-9270-9fa1b7c6138b</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Project.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="DefaultAuthorizationServiceTests.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Properties\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\ProjectK\Microsoft.Web.ProjectK.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"version" : "0.1-alpha-*",
|
||||||
|
"compilationOptions": {
|
||||||
|
"warningsAsErrors": true
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.AspNet.Security" : "0.1-alpha-*",
|
||||||
|
"Moq": "4.2.1312.1622",
|
||||||
|
"Xunit.KRunner": "0.1-alpha-*",
|
||||||
|
"xunit.abstractions": "2.0.0-aspnet-*",
|
||||||
|
"xunit.assert": "2.0.0-aspnet-*",
|
||||||
|
"xunit.core": "2.0.0-aspnet-*",
|
||||||
|
"xunit.execution": "2.0.0-aspnet-*"
|
||||||
|
},
|
||||||
|
"commands": {
|
||||||
|
"test": "Xunit.KRunner"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"net45": {
|
||||||
|
"dependencies": {
|
||||||
|
"System.Runtime": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue