Initial iteration of new Authorization Service
This commit is contained in:
parent
f7c502a9e6
commit
4a635835af
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains authorization information used by <see cref="IAuthorizationPolicyHandler"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class AuthorizationContext
|
||||||
|
{
|
||||||
|
private HashSet<IAuthorizationRequirement> _pendingRequirements = new HashSet<IAuthorizationRequirement>();
|
||||||
|
private bool _failCalled;
|
||||||
|
private bool _succeedCalled;
|
||||||
|
|
||||||
|
public AuthorizationContext(
|
||||||
|
[NotNull] AuthorizationPolicy policy,
|
||||||
|
HttpContext context,
|
||||||
|
object resource)
|
||||||
|
{
|
||||||
|
Policy = policy;
|
||||||
|
Context = context;
|
||||||
|
Resource = resource;
|
||||||
|
foreach (var req in Policy.Requirements)
|
||||||
|
{
|
||||||
|
_pendingRequirements.Add(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorizationPolicy Policy { get; private set; }
|
||||||
|
public ClaimsPrincipal User { get { return Context.User; } }
|
||||||
|
public HttpContext Context { get; private set; }
|
||||||
|
public object Resource { get; private set; }
|
||||||
|
|
||||||
|
public IEnumerable<IAuthorizationRequirement> PendingRequirements { get { return _pendingRequirements; } }
|
||||||
|
|
||||||
|
public bool HasFailed { get { return _failCalled; } }
|
||||||
|
|
||||||
|
public bool HasSucceeded {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return !_failCalled && _succeedCalled && !PendingRequirements.Any();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fail()
|
||||||
|
{
|
||||||
|
_failCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Succeed(IAuthorizationRequirement requirement)
|
||||||
|
{
|
||||||
|
_succeedCalled = true;
|
||||||
|
_pendingRequirements.Remove(requirement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security
|
||||||
|
{
|
||||||
|
// Music store use case
|
||||||
|
|
||||||
|
// await AuthorizeAsync<Album>(user, "Edit", albumInstance);
|
||||||
|
|
||||||
|
// No policy name needed because this is auto based on resource (operation is the policy name)
|
||||||
|
//RegisterOperation which auto generates the policy for Authorize<T>
|
||||||
|
//bool AuthorizeAsync<TResource>(ClaimsPrincipal, string operation, TResource instance)
|
||||||
|
//bool AuthorizeAsync<TResource>(IAuthorization, ClaimsPrincipal, string operation, TResource instance)
|
||||||
|
public abstract class AuthorizationHandler<TRequirement> : IAuthorizationHandler
|
||||||
|
where TRequirement : IAuthorizationRequirement
|
||||||
|
{
|
||||||
|
public async Task HandleAsync(AuthorizationContext context)
|
||||||
|
{
|
||||||
|
foreach (var req in context.Policy.Requirements.OfType<TRequirement>())
|
||||||
|
{
|
||||||
|
if (await CheckAsync(context, req))
|
||||||
|
{
|
||||||
|
context.Succeed(req);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Task<bool> CheckAsync(AuthorizationContext context, TRequirement requirement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
//public abstract class AuthorizationHandler<TRequirement, TResource> : AuthorizationHandler<TRequirement>
|
||||||
|
// where TResource : class
|
||||||
|
// where TRequirement : IAuthorizationRequirement
|
||||||
|
//{
|
||||||
|
// public override Task HandleAsync(AuthorizationContext context)
|
||||||
|
// {
|
||||||
|
// var resource = context.Resource as TResource;
|
||||||
|
// if (resource != null)
|
||||||
|
// {
|
||||||
|
// return HandleAsync(context, resource);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return Task.FromResult(0);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public abstract Task HandleAsync(AuthorizationContext context, TResource resource);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security
|
||||||
|
{
|
||||||
|
public class AuthorizationOptions
|
||||||
|
{
|
||||||
|
// TODO: make this case insensitive
|
||||||
|
private IDictionary<string, AuthorizationPolicy> PolicyMap { get; } = new Dictionary<string, AuthorizationPolicy>();
|
||||||
|
|
||||||
|
public void AddPolicy([NotNull] string name, [NotNull] AuthorizationPolicy policy)
|
||||||
|
{
|
||||||
|
PolicyMap[name] = policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorizationPolicy GetPolicy([NotNull] string name)
|
||||||
|
{
|
||||||
|
return PolicyMap.ContainsKey(name) ? PolicyMap[name] : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,31 +2,18 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Security
|
namespace Microsoft.AspNet.Security
|
||||||
{
|
{
|
||||||
/// <summary>
|
public class AuthorizationPolicy
|
||||||
/// This class provides a base implementation for <see cref="IAuthorizationPolicy" />
|
|
||||||
/// </summary>
|
|
||||||
public abstract class AuthorizationPolicy : IAuthorizationPolicy
|
|
||||||
{
|
{
|
||||||
public int Order { get; set; }
|
public AuthorizationPolicy(IEnumerable<IAuthorizationRequirement> requirements, IEnumerable<string> activeAuthenticationTypes)
|
||||||
|
|
||||||
public virtual Task ApplyingAsync(AuthorizationPolicyContext context)
|
|
||||||
{
|
{
|
||||||
return Task.FromResult(0);
|
Requirements = requirements;
|
||||||
|
ActiveAuthenticationTypes = activeAuthenticationTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task ApplyAsync(AuthorizationPolicyContext context)
|
public IEnumerable<IAuthorizationRequirement> Requirements { get; private set; }
|
||||||
{
|
public IEnumerable<string> ActiveAuthenticationTypes { get; private set; }
|
||||||
return Task.FromResult(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual Task AppliedAsync(AuthorizationPolicyContext context)
|
|
||||||
{
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Security.Claims;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security
|
||||||
|
{
|
||||||
|
public class AuthorizationPolicyBuilder
|
||||||
|
{
|
||||||
|
public AuthorizationPolicyBuilder(params string[] activeAuthenticationTypes)
|
||||||
|
{
|
||||||
|
foreach (var authType in activeAuthenticationTypes) {
|
||||||
|
ActiveAuthenticationTypes.Add(authType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IList<IAuthorizationRequirement> Requirements { get; set; } = new List<IAuthorizationRequirement>();
|
||||||
|
public IList<string> ActiveAuthenticationTypes { get; set; } = new List<string>();
|
||||||
|
|
||||||
|
public AuthorizationPolicyBuilder RequiresClaim([NotNull] string claimType, params string[] requiredValues)
|
||||||
|
{
|
||||||
|
Requirements.Add(new ClaimsAuthorizationRequirement
|
||||||
|
{
|
||||||
|
ClaimType = claimType,
|
||||||
|
AllowedValues = requiredValues
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorizationPolicyBuilder RequiresClaim([NotNull] string claimType)
|
||||||
|
{
|
||||||
|
Requirements.Add(new ClaimsAuthorizationRequirement
|
||||||
|
{
|
||||||
|
ClaimType = claimType,
|
||||||
|
AllowedValues = null
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorizationPolicyBuilder RequiresRole([NotNull] params string[] roles)
|
||||||
|
{
|
||||||
|
RequiresClaim(ClaimTypes.Role, roles);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorizationPolicyBuilder RequireAuthenticatedUser()
|
||||||
|
{
|
||||||
|
Requirements.Add(new DenyAnonymousAuthorizationRequirement());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorizationPolicy Build()
|
||||||
|
{
|
||||||
|
return new AuthorizationPolicy(Requirements, ActiveAuthenticationTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. 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
|
|
||||||
{
|
|
||||||
/// <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;
|
|
||||||
|
|
||||||
// user claims are copied to a new and mutable list
|
|
||||||
UserClaims = user != null
|
|
||||||
? user.Claims.ToList()
|
|
||||||
: new List<Claim>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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>
|
|
||||||
/// The claims of the user.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This list can be modified by policies for retries.
|
|
||||||
/// </remarks>
|
|
||||||
public IList<Claim> UserClaims { 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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. 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
|
|
||||||
{
|
|
||||||
public static class AuthorizationServiceExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a user has specific claims.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="claim">The claim 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>
|
|
||||||
public static Task<bool> AuthorizeAsync([NotNull] this IAuthorizationService service, Claim claim, ClaimsPrincipal user)
|
|
||||||
{
|
|
||||||
return service.AuthorizeAsync(new Claim[] { claim }, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a user has specific claims.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="claim">The claim 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>
|
|
||||||
public static bool Authorize([NotNull] this IAuthorizationService service, Claim claim, ClaimsPrincipal user)
|
|
||||||
{
|
|
||||||
return service.Authorize(new Claim[] { claim }, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a user has specific claims for a specific context obj.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="claim">The claim 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>
|
|
||||||
public static Task<bool> AuthorizeAsync([NotNull] this IAuthorizationService service, Claim claim, ClaimsPrincipal user, object resource)
|
|
||||||
{
|
|
||||||
return service.AuthorizeAsync(new Claim[] { claim }, user, resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a user has specific claims for a specific context obj.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="claim">The claimsto 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>
|
|
||||||
public static bool Authorize([NotNull] this IAuthorizationService service, Claim claim, ClaimsPrincipal user, object resource)
|
|
||||||
{
|
|
||||||
return service.Authorize(new Claim[] { claim }, user, resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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>
|
|
||||||
public static Task<bool> AuthorizeAsync([NotNull] this IAuthorizationService service, IEnumerable<Claim> claims, ClaimsPrincipal user)
|
|
||||||
{
|
|
||||||
return service.AuthorizeAsync(claims, user, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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>
|
|
||||||
public static bool Authorize([NotNull] this IAuthorizationService service, IEnumerable<Claim> claims, ClaimsPrincipal user)
|
|
||||||
{
|
|
||||||
return service.Authorize(claims, user, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security
|
||||||
|
{
|
||||||
|
public class ClaimsAuthorizationHandler : AuthorizationHandler<ClaimsAuthorizationRequirement>
|
||||||
|
{
|
||||||
|
public override Task<bool> CheckAsync(AuthorizationContext context, ClaimsAuthorizationRequirement requirement)
|
||||||
|
{
|
||||||
|
if (context.Context.User == null)
|
||||||
|
{
|
||||||
|
return Task.FromResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
if (requirement.AllowedValues == null || !requirement.AllowedValues.Any())
|
||||||
|
{
|
||||||
|
found = context.Context.User.Claims.Any(c => string.Equals(c.Type, requirement.ClaimType, StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found = context.Context.User.Claims.Any(c => string.Equals(c.Type, requirement.ClaimType, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& requirement.AllowedValues.Contains(c.Value, StringComparer.Ordinal));
|
||||||
|
}
|
||||||
|
return Task.FromResult(found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security
|
||||||
|
{
|
||||||
|
// Must contain a claim with the specified name, and at least one of the required values
|
||||||
|
// If AllowedValues is null or empty, that means any claim is valid
|
||||||
|
public class ClaimsAuthorizationRequirement : IAuthorizationRequirement
|
||||||
|
{
|
||||||
|
public string ClaimType { get; set; }
|
||||||
|
public IEnumerable<string> AllowedValues { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,101 +1,67 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Security
|
namespace Microsoft.AspNet.Security
|
||||||
{
|
{
|
||||||
public class DefaultAuthorizationService : IAuthorizationService
|
public class DefaultAuthorizationService : IAuthorizationService
|
||||||
{
|
{
|
||||||
private readonly IList<IAuthorizationPolicy> _policies;
|
private readonly IList<IAuthorizationHandler> _handlers;
|
||||||
public int MaxRetries = 99;
|
private readonly AuthorizationOptions _options;
|
||||||
|
|
||||||
public DefaultAuthorizationService(IEnumerable<IAuthorizationPolicy> policies)
|
public DefaultAuthorizationService(IOptions<AuthorizationOptions> options, IEnumerable<IAuthorizationHandler> handlers)
|
||||||
{
|
{
|
||||||
if (policies == null)
|
_handlers = handlers.ToArray();
|
||||||
{
|
_options = options.Options;
|
||||||
_policies = Enumerable.Empty<IAuthorizationPolicy>().ToArray();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_policies = policies.OrderBy(x => x.Order).ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> AuthorizeAsync(IEnumerable<Claim> claims, ClaimsPrincipal user, object resource)
|
public Task<bool> AuthorizeAsync([NotNull] string policyName, HttpContext context, object resource = null)
|
||||||
{
|
{
|
||||||
var context = new AuthorizationPolicyContext(claims, user, resource);
|
var policy = _options.GetPolicy(policyName);
|
||||||
|
if (policy == null)
|
||||||
foreach (var policy in _policies)
|
|
||||||
{
|
{
|
||||||
await policy.ApplyingAsync(context);
|
return Task.FromResult(false);
|
||||||
}
|
}
|
||||||
|
return AuthorizeAsync(policy, context, resource);
|
||||||
|
}
|
||||||
|
|
||||||
// we only apply the policies for a limited number of times to prevent
|
public async Task<bool> AuthorizeAsync([NotNull] AuthorizationPolicy policy, [NotNull] HttpContext context, object resource = null)
|
||||||
// infinite loops
|
{
|
||||||
|
var user = context.User;
|
||||||
int retries;
|
try
|
||||||
for (retries = 0; retries < MaxRetries; retries++)
|
|
||||||
{
|
{
|
||||||
// we don't need to check for owned claims if the permission is already granted
|
// Generate the user identities if policy specified the AuthTypes
|
||||||
if (!context.Authorized)
|
if (policy.ActiveAuthenticationTypes != null && policy.ActiveAuthenticationTypes.Any() )
|
||||||
{
|
{
|
||||||
if (context.User != null)
|
var principal = new ClaimsPrincipal();
|
||||||
|
|
||||||
|
var results = await context.AuthenticateAsync(policy.ActiveAuthenticationTypes);
|
||||||
|
// REVIEW: re requesting the identities fails for MVC currently, so we only request if not found
|
||||||
|
foreach (var result in results)
|
||||||
{
|
{
|
||||||
if (ClaimsMatch(context.Claims, context.UserClaims))
|
principal.AddIdentity(result.Identity);
|
||||||
{
|
|
||||||
context.Authorized = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
context.User = principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the retry flag
|
var authContext = new AuthorizationContext(policy, context, resource);
|
||||||
context.Retry = false;
|
|
||||||
|
|
||||||
// give a chance for policies to change claims or the grant
|
foreach (var handler in _handlers)
|
||||||
foreach (var policy in _policies)
|
|
||||||
{
|
{
|
||||||
await policy.ApplyAsync(context);
|
await handler.HandleAsync(authContext);
|
||||||
}
|
|
||||||
|
|
||||||
// if no policies have changed the context, stop checking
|
|
||||||
if (!context.Retry)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return authContext.HasSucceeded;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
if (retries == MaxRetries)
|
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Too many authorization retries.");
|
context.User = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
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).GetAwaiter().GetResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ClaimsMatch([NotNull] IEnumerable<Claim> x, [NotNull] IEnumerable<Claim> y)
|
|
||||||
{
|
|
||||||
return x.Any(claim =>
|
|
||||||
y.Any(userClaim =>
|
|
||||||
string.Equals(claim.Type, userClaim.Type, StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
string.Equals(claim.Value, userClaim.Value, StringComparison.Ordinal)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security
|
||||||
|
{
|
||||||
|
public class DenyAnonymousAuthorizationHandler : AuthorizationHandler<DenyAnonymousAuthorizationRequirement>
|
||||||
|
{
|
||||||
|
public override Task<bool> CheckAsync(AuthorizationContext context, DenyAnonymousAuthorizationRequirement requirement)
|
||||||
|
{
|
||||||
|
var user = context.User;
|
||||||
|
var userIsAnonymous =
|
||||||
|
user == null ||
|
||||||
|
user.Identity == null ||
|
||||||
|
!user.Identity.IsAuthenticated;
|
||||||
|
return Task.FromResult(!userIsAnonymous);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNet.Security;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security
|
||||||
|
{
|
||||||
|
public class DenyAnonymousAuthorizationRequirement : IAuthorizationRequirement { }
|
||||||
|
}
|
||||||
|
|
@ -5,11 +5,9 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Security
|
namespace Microsoft.AspNet.Security
|
||||||
{
|
{
|
||||||
public interface IAuthorizationPolicy
|
public interface IAuthorizationHandler
|
||||||
{
|
{
|
||||||
int Order { get; set; }
|
Task HandleAsync(AuthorizationContext context);
|
||||||
Task ApplyingAsync(AuthorizationPolicyContext context);
|
//void Handle(AuthorizationContext context);
|
||||||
Task ApplyAsync(AuthorizationPolicyContext context);
|
|
||||||
Task AppliedAsync(AuthorizationPolicyContext context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security
|
||||||
|
{
|
||||||
|
public interface IAuthorizationRequirement
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,34 +1,32 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Security
|
namespace Microsoft.AspNet.Security
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks claims based permissions for a user.
|
/// Checks policy based permissions for a user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IAuthorizationService
|
public interface IAuthorizationService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if a user has specific claims for a specific context obj.
|
/// Checks if a user meets a specific authorization policy
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="claims">The claims to check against a specific user.</param>
|
/// <param name="policy">The policy to check against a specific context.</param>
|
||||||
/// <param name="user">The user to check claims against.</param>
|
/// <param name="context">The HttpContext to check the policy against.</param>
|
||||||
/// <param name="resource">The resource the claims should be check with.</param>
|
/// <param name="resource">The resource the policy should be checked with.</param>
|
||||||
/// <returns><value>true</value> when the user fulfills one of the claims, <value>false</value> otherwise.</returns>
|
/// <returns><value>true</value> when the user fulfills the policy, <value>false</value> otherwise.</returns>
|
||||||
Task<bool> AuthorizeAsync(IEnumerable<Claim> claims, ClaimsPrincipal user, object resource);
|
Task<bool> AuthorizeAsync(string policyName, HttpContext context, object resource = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if a user has specific claims for a specific context obj.
|
/// Checks if a user meets a specific authorization policy
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="claims">The claims to check against a specific user.</param>
|
/// <param name="policy">The policy to check against a specific context.</param>
|
||||||
/// <param name="user">The user to check claims against.</param>
|
/// <param name="context">The HttpContext to check the policy against.</param>
|
||||||
/// <param name="resource">The resource the claims should be check with.</param>
|
/// <param name="resource">The resource the policy should be checked with.</param>
|
||||||
/// <returns><value>true</value> when the user fulfills one of the claims, <value>false</value> otherwise.</returns>
|
/// <returns><value>true</value> when the user fulfills the policy, <value>false</value> otherwise.</returns>
|
||||||
bool Authorize(IEnumerable<Claim> claims, ClaimsPrincipal user, object resource);
|
Task<bool> AuthorizeAsync(AuthorizationPolicy policy, HttpContext context, object resource = null);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Security
|
||||||
|
{
|
||||||
|
public class PassThroughAuthorizationHandler : IAuthorizationHandler
|
||||||
|
{
|
||||||
|
public async Task HandleAsync(AuthorizationContext context)
|
||||||
|
{
|
||||||
|
foreach (var handler in context.Policy.Requirements.OfType<IAuthorizationHandler>())
|
||||||
|
{
|
||||||
|
await handler.HandleAsync(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNet.Security;
|
||||||
|
using Microsoft.Framework.ConfigurationModel;
|
||||||
|
|
||||||
|
namespace Microsoft.Framework.DependencyInjection
|
||||||
|
{
|
||||||
|
public static class ServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection ConfigureAuthorization([NotNull] this IServiceCollection services, [NotNull] Action<AuthorizationOptions> configure)
|
||||||
|
{
|
||||||
|
return services.Configure(configure);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Review: Need UseDefaultSubkey parameter?
|
||||||
|
public static IServiceCollection AddAuthorization([NotNull] this IServiceCollection services, IConfiguration config = null, Action<AuthorizationOptions> configureOptions = null)
|
||||||
|
{
|
||||||
|
var describe = new ServiceDescriber(config);
|
||||||
|
services.AddOptions(config);
|
||||||
|
services.TryAdd(describe.Transient<IAuthorizationService, DefaultAuthorizationService>());
|
||||||
|
services.Add(describe.Transient<IAuthorizationHandler, ClaimsAuthorizationHandler>());
|
||||||
|
services.Add(describe.Transient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>());
|
||||||
|
if (configureOptions != null)
|
||||||
|
{
|
||||||
|
services.Configure(configureOptions);
|
||||||
|
}
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,307 +3,588 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Security;
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.Http.Security;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||||
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Security.Test
|
namespace Microsoft.AspNet.Security.Test
|
||||||
{
|
{
|
||||||
public class DefaultAuthorizationServiceTests
|
public class DefaultAuthorizationServiceTests
|
||||||
{
|
{
|
||||||
|
private IAuthorizationService BuildAuthorizationService(Action<IServiceCollection> setupServices = null)
|
||||||
|
{
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.AddAuthorization();
|
||||||
|
if (setupServices != null)
|
||||||
|
{
|
||||||
|
setupServices(services);
|
||||||
|
}
|
||||||
|
return services.BuildServiceProvider().GetRequiredService<IAuthorizationService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mock<HttpContext> SetupContext(params ClaimsIdentity[] ids)
|
||||||
|
{
|
||||||
|
var context = new Mock<HttpContext>();
|
||||||
|
context.SetupProperty(c => c.User);
|
||||||
|
var user = new ClaimsPrincipal();
|
||||||
|
user.AddIdentities(ids);
|
||||||
|
context.Object.User = user;
|
||||||
|
if (ids != null)
|
||||||
|
{
|
||||||
|
var results = new List<AuthenticationResult>();
|
||||||
|
foreach (var id in ids)
|
||||||
|
{
|
||||||
|
results.Add(new AuthenticationResult(id, new AuthenticationProperties(), new AuthenticationDescription()));
|
||||||
|
}
|
||||||
|
context.Setup(c => c.AuthenticateAsync(It.IsAny<IEnumerable<string>>())).ReturnsAsync(results).Verifiable();
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Check_ShouldAllowIfClaimIsPresent()
|
public async Task Authorize_ShouldAllowIfClaimIsPresent()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
var user = new ClaimsPrincipal(
|
{
|
||||||
new ClaimsIdentity( new Claim[] { new Claim("Permission", "CanViewPage") }, "Basic")
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
);
|
{
|
||||||
|
options.AddPolicy("Basic", new AuthorizationPolicyBuilder()
|
||||||
|
.RequiresClaim("Permission", "CanViewPage")
|
||||||
|
.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(new ClaimsIdentity(new Claim[] { new Claim("Permission", "CanViewPage") }, "Basic"));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(allowed);
|
Assert.True(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Check_ShouldAllowIfClaimIsAmongValues()
|
public async Task Authorize_ShouldAllowIfClaimIsPresentWithSpecifiedAuthType()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
var user = new ClaimsPrincipal(
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder("Basic").RequiresClaim("Permission", "CanViewPage");
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(new ClaimsIdentity(new Claim[] { new Claim("Permission", "CanViewPage") }, "Basic"));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Authorize_ShouldAllowIfClaimIsAmongValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage", "CanViewAnything");
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(
|
||||||
new ClaimsIdentity(
|
new ClaimsIdentity(
|
||||||
new Claim[] {
|
new Claim[] {
|
||||||
new Claim("Permission", "CanViewPage"),
|
new Claim("Permission", "CanViewPage"),
|
||||||
new Claim("Permission", "CanViewAnything")
|
new Claim("Permission", "CanViewAnything")
|
||||||
},
|
},
|
||||||
"Basic")
|
"Basic")
|
||||||
);
|
);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(allowed);
|
Assert.True(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Check_ShouldNotAllowIfClaimTypeIsNotPresent()
|
public async Task Authorize_ShouldFailWhenAllRequirementsNotHandled()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
var user = new ClaimsPrincipal(
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage", "CanViewAnything");
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(
|
||||||
new ClaimsIdentity(
|
new ClaimsIdentity(
|
||||||
new Claim[] {
|
new Claim[] {
|
||||||
new Claim("SomethingElse", "CanViewPage"),
|
new Claim("SomethingElse", "CanViewPage"),
|
||||||
},
|
},
|
||||||
"Basic")
|
"Basic")
|
||||||
);
|
);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(allowed);
|
Assert.False(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Check_ShouldNotAllowIfClaimValueIsNotPresent()
|
public async Task Authorize_ShouldNotAllowIfClaimTypeIsNotPresent()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
var user = new ClaimsPrincipal(
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage", "CanViewAnything");
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(
|
||||||
new ClaimsIdentity(
|
new ClaimsIdentity(
|
||||||
new Claim[] {
|
new Claim[] {
|
||||||
new Claim("Permission", "CanViewComment"),
|
new Claim("SomethingElse", "CanViewPage"),
|
||||||
},
|
},
|
||||||
"Basic")
|
"Basic")
|
||||||
);
|
);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(allowed);
|
Assert.False(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Check_ShouldNotAllowIfNoClaims()
|
public async Task Authorize_ShouldNotAllowIfClaimValueIsNotPresent()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
var user = new ClaimsPrincipal(
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage");
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim("Permission", "CanViewComment"),
|
||||||
|
},
|
||||||
|
"Basic")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Authorize_ShouldNotAllowIfNoClaims()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage");
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(
|
||||||
new ClaimsIdentity(
|
new ClaimsIdentity(
|
||||||
new Claim[0],
|
new Claim[0],
|
||||||
"Basic")
|
"Basic")
|
||||||
);
|
);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(allowed);
|
Assert.False(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Check_ShouldNotAllowIfUserIsNull()
|
public async Task Authorize_ShouldNotAllowIfUserIsNull()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
ClaimsPrincipal user = null;
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage");
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext();
|
||||||
|
context.Object.User = null;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(allowed);
|
Assert.False(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Check_ShouldNotAllowIfUserIsNotAuthenticated()
|
public async Task Authorize_ShouldNotAllowIfNotCorrectAuthType()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
var user = new ClaimsPrincipal(
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder("Basic").RequiresClaim("Permission", "CanViewPage");
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(new ClaimsIdentity());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Authorize_ShouldAllowWithNoAuthType()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage");
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(
|
||||||
new ClaimsIdentity(
|
new ClaimsIdentity(
|
||||||
new Claim[] {
|
new Claim[] {
|
||||||
new Claim("Permission", "CanViewComment"),
|
new Claim("Permission", "CanViewPage"),
|
||||||
|
},
|
||||||
|
"Basic")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Authorize_ShouldNotAllowIfUnknownPolicy()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = BuildAuthorizationService();
|
||||||
|
var context = SetupContext(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim("Permission", "CanViewComment"),
|
||||||
},
|
},
|
||||||
null)
|
null)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var allowed = authorizationService.Authorize(new Claim[] { new Claim("Permission", "CanViewPage") }, user);
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(allowed);
|
Assert.False(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Check_ShouldApplyPoliciesInOrder()
|
public async Task Authorize_CustomRolePolicy()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
string result = "";
|
var policy = new AuthorizationPolicyBuilder().RequiresRole("Administrator")
|
||||||
var policies = new IAuthorizationPolicy[] {
|
.RequiresClaim(ClaimTypes.Role, "User");
|
||||||
new FakePolicy() {
|
var authorizationService = BuildAuthorizationService();
|
||||||
Order = 20,
|
var context = SetupContext(
|
||||||
ApplyingAsyncAction = (context) => { result += "20"; }
|
new ClaimsIdentity(
|
||||||
},
|
new Claim[] {
|
||||||
new FakePolicy() {
|
new Claim(ClaimTypes.Role, "User"),
|
||||||
Order = -1,
|
new Claim(ClaimTypes.Role, "Administrator")
|
||||||
ApplyingAsyncAction = (context) => { result += "-1"; }
|
},
|
||||||
},
|
"Basic")
|
||||||
new FakePolicy() {
|
|
||||||
Order = 30,
|
|
||||||
ApplyingAsyncAction = (context) => { result += "30"; }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var authorizationService = new DefaultAuthorizationService(policies);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var allowed = authorizationService.Authorize(Enumerable.Empty<Claim>(), 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(Enumerable.Empty<Claim>(), 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(Enumerable.Empty<Claim>(), 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<InvalidOperationException>(() => authorizationService.Authorize(Enumerable.Empty<Claim>(), null));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Check_ApplyCanMutateCheckedClaims()
|
|
||||||
{
|
|
||||||
|
|
||||||
// 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
|
// Act
|
||||||
var allowed = authorizationService.Authorize(Enumerable.Empty<Claim>(), user);
|
var allowed = await authorizationService.AuthorizeAsync(policy.Build(), context.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(allowed);
|
Assert.True(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Check_PoliciesCanMutateUsersClaims()
|
public async Task Authorize_HasAnyClaimOfTypePolicy()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Arrange
|
// Arrange
|
||||||
var user = new ClaimsPrincipal(
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim(ClaimTypes.Role);
|
||||||
new ClaimsIdentity(new Claim[0], "Basic")
|
var authorizationService = BuildAuthorizationService();
|
||||||
|
var context = SetupContext(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim(ClaimTypes.Role, ""),
|
||||||
|
},
|
||||||
|
"Basic")
|
||||||
);
|
);
|
||||||
|
|
||||||
var policies = new IAuthorizationPolicy[] {
|
|
||||||
new FakePolicy() {
|
|
||||||
ApplyAsyncAction = (context) => {
|
|
||||||
if (!context.Authorized)
|
|
||||||
{
|
|
||||||
context.UserClaims.Add(new Claim("Permission", "CanDeleteComments"));
|
|
||||||
context.Retry = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var authorizationService = new DefaultAuthorizationService(policies);
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var allowed = authorizationService.Authorize(new Claim("Permission", "CanDeleteComments"), user);
|
var allowed = await authorizationService.AuthorizeAsync(policy.Build(), context.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(allowed);
|
Assert.True(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Authorize_PolicyCanAuthenticationTypeWithNameClaim()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var policy = new AuthorizationPolicyBuilder("AuthType").RequiresClaim(ClaimTypes.Name);
|
||||||
|
var authorizationService = BuildAuthorizationService();
|
||||||
|
var context = SetupContext(
|
||||||
|
new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, "Name") }, "AuthType")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync(policy.Build(), context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RolePolicyCanRequireSingleRole()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var policy = new AuthorizationPolicyBuilder("AuthType").RequiresRole("Admin");
|
||||||
|
var authorizationService = BuildAuthorizationService();
|
||||||
|
var context = SetupContext(
|
||||||
|
new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Role, "Admin") }, "AuthType")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync(policy.Build(), context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RolePolicyCanRequireOneOfManyRoles()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var policy = new AuthorizationPolicyBuilder("AuthType").RequiresRole("Admin", "Users");
|
||||||
|
var authorizationService = BuildAuthorizationService();
|
||||||
|
var context = SetupContext(
|
||||||
|
new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Role, "Users") }, "AuthType"));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync(policy.Build(), context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RolePolicyCanBlockWrongRole()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage");
|
||||||
|
var authorizationService = BuildAuthorizationService();
|
||||||
|
var context = SetupContext(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim(ClaimTypes.Role, "Nope"),
|
||||||
|
},
|
||||||
|
"AuthType")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync(policy.Build(), context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RolePolicyCanBlockNoRole()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
|
||||||
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresRole("Admin", "Users");
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
},
|
||||||
|
"AuthType")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PolicyFailsWithNoRequirements()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder();
|
||||||
|
options.AddPolicy("Basic", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim(ClaimTypes.Name, "Name"),
|
||||||
|
},
|
||||||
|
"AuthType")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync("Basic", context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CanApproveAnyAuthenticatedUser()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser();
|
||||||
|
options.AddPolicy("Any", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim(ClaimTypes.Name, "Name"),
|
||||||
|
},
|
||||||
|
"AuthType")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync("Any", context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CanBlockNonAuthenticatedUser()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser();
|
||||||
|
options.AddPolicy("Any", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext(new ClaimsIdentity());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync("Any", context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CustomRequirement : IAuthorizationRequirement { }
|
||||||
|
public class CustomHandler : AuthorizationHandler<CustomRequirement>
|
||||||
|
{
|
||||||
|
public override Task<bool> CheckAsync(AuthorizationContext context, CustomRequirement requirement)
|
||||||
|
{
|
||||||
|
return Task.FromResult(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CustomReqWithNoHandlerFails()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
|
{
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder();
|
||||||
|
policy.Requirements.Add(new CustomRequirement());
|
||||||
|
options.AddPolicy("Custom", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync("Custom", context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CustomReqWithHandlerSucceeds()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizationService = BuildAuthorizationService(services =>
|
||||||
|
{
|
||||||
|
services.AddTransient<IAuthorizationHandler, CustomHandler>();
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder();
|
||||||
|
policy.Requirements.Add(new CustomRequirement());
|
||||||
|
options.AddPolicy("Custom", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var context = SetupContext();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var allowed = await authorizationService.AuthorizeAsync("Custom", context.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNet.Security;
|
|
||||||
|
|
||||||
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;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Runtime.Versioning;
|
|
||||||
using Microsoft.Framework.Runtime;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Security
|
|
||||||
{
|
|
||||||
public class TestApplicationEnvironment : IApplicationEnvironment
|
|
||||||
{
|
|
||||||
public string ApplicationBasePath
|
|
||||||
{
|
|
||||||
get { return Environment.CurrentDirectory; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ApplicationName
|
|
||||||
{
|
|
||||||
get { return "Test App environment"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Configuration
|
|
||||||
{
|
|
||||||
get { return "Test"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public FrameworkName RuntimeFramework
|
|
||||||
{
|
|
||||||
get { return new FrameworkName(".NETFramework", new Version(4, 5)); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Version
|
|
||||||
{
|
|
||||||
get { return "1.0.0"; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue