React to Security Auth changes
This commit is contained in:
parent
262bb9a732
commit
7b2fb55ef6
|
|
@ -50,14 +50,14 @@ namespace MvcSample.Web
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize("Permission", "CanViewPage")]
|
[Authorize("CanViewPage")]
|
||||||
public ActionResult NotGrantedClaim(int age = 20, string userName = "SampleUser")
|
public ActionResult NotGrantedClaim(int age = 20, string userName = "SampleUser")
|
||||||
{
|
{
|
||||||
return Index(age, userName);
|
return Index(age, userName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[FakeUser]
|
[FakeUser]
|
||||||
[Authorize("Permission", "CanViewPage", "CanViewAnything")]
|
[Authorize("CanViewAnything")]
|
||||||
public ActionResult AllGranted(int age = 20, string userName = "SampleUser")
|
public ActionResult AllGranted(int age = 20, string userName = "SampleUser")
|
||||||
{
|
{
|
||||||
return Index(age, userName);
|
return Index(age, userName);
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,12 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Security.Claims;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
using Microsoft.AspNet.Mvc.Razor;
|
using Microsoft.AspNet.Mvc.Razor;
|
||||||
using Microsoft.AspNet.Routing;
|
using Microsoft.AspNet.Routing;
|
||||||
|
using Microsoft.AspNet.Security;
|
||||||
using Microsoft.Framework.ConfigurationModel;
|
using Microsoft.Framework.ConfigurationModel;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using MvcSample.Web.Filters;
|
using MvcSample.Web.Filters;
|
||||||
|
|
@ -38,6 +40,19 @@ namespace MvcSample.Web
|
||||||
|
|
||||||
app.UseServices(services =>
|
app.UseServices(services =>
|
||||||
{
|
{
|
||||||
|
services.ConfigureAuthorization(auth =>
|
||||||
|
{
|
||||||
|
auth.AddPolicy("CanViewPage",
|
||||||
|
new AuthorizationPolicyBuilder()
|
||||||
|
.RequiresClaim("Permission", "CanViewPage", "CanViewAnything").Build());
|
||||||
|
auth.AddPolicy("CanViewAnything",
|
||||||
|
new AuthorizationPolicyBuilder()
|
||||||
|
.RequiresClaim("Permission", "CanViewAnything").Build());
|
||||||
|
// This policy basically requires that the auth type is present
|
||||||
|
var basicPolicy = new AuthorizationPolicyBuilder("Basic").RequiresClaim(ClaimTypes.NameIdentifier);
|
||||||
|
auth.AddPolicy("RequireBasic", basicPolicy.Build());
|
||||||
|
});
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
services.AddSingleton<PassThroughAttribute>();
|
services.AddSingleton<PassThroughAttribute>();
|
||||||
services.AddSingleton<UserNameService>();
|
services.AddSingleton<UserNameService>();
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,6 @@
|
||||||
// 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;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc.Core;
|
using Microsoft.AspNet.Mvc.Core;
|
||||||
using Microsoft.AspNet.Security;
|
using Microsoft.AspNet.Security;
|
||||||
|
|
@ -14,69 +11,74 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
public class AuthorizeAttribute : AuthorizationFilterAttribute
|
public class AuthorizeAttribute : AuthorizationFilterAttribute
|
||||||
{
|
{
|
||||||
protected Claim[] _claims;
|
private string _roles;
|
||||||
|
private string[] _rolesSplit;
|
||||||
|
|
||||||
public AuthorizeAttribute()
|
public AuthorizeAttribute() { }
|
||||||
|
|
||||||
|
public AuthorizeAttribute(string policy)
|
||||||
{
|
{
|
||||||
_claims = new Claim[0];
|
Policy = policy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthorizeAttribute([NotNull]IEnumerable<Claim> claims)
|
public string Policy { get; set; }
|
||||||
{
|
|
||||||
_claims = claims.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthorizeAttribute(string claimType, string claimValue)
|
public string Roles
|
||||||
{
|
{
|
||||||
_claims = new[] { new Claim(claimType, claimValue) };
|
get { return _roles; }
|
||||||
}
|
set
|
||||||
|
|
||||||
public AuthorizeAttribute(string claimType, string claimValue, params string[] otherClaimValues)
|
|
||||||
: this(claimType, claimValue)
|
|
||||||
{
|
|
||||||
if (otherClaimValues.Length > 0)
|
|
||||||
{
|
{
|
||||||
_claims = _claims.Concat(otherClaimValues.Select(claim => new Claim(claimType, claim))).ToArray();
|
_roles = value;
|
||||||
|
if (string.IsNullOrWhiteSpace(_roles))
|
||||||
|
{
|
||||||
|
_rolesSplit = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_rolesSplit = _roles.Split(',');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task OnAuthorizationAsync([NotNull] AuthorizationContext context)
|
public override async Task OnAuthorizationAsync([NotNull] AuthorizationContext context)
|
||||||
{
|
{
|
||||||
var httpContext = context.HttpContext;
|
var httpContext = context.HttpContext;
|
||||||
var user = httpContext.User;
|
|
||||||
|
|
||||||
// when no claims are specified, we just need to ensure the user is authenticated
|
// Allow Anonymous skips all authorization
|
||||||
if (_claims.Length == 0)
|
if (HasAllowAnonymous(context))
|
||||||
{
|
{
|
||||||
var userIsAnonymous =
|
return;
|
||||||
user == null ||
|
}
|
||||||
user.Identity == null ||
|
|
||||||
!user.Identity.IsAuthenticated;
|
|
||||||
|
|
||||||
if (userIsAnonymous && !HasAllowAnonymous(context))
|
var authService = httpContext.RequestServices.GetRequiredService<IAuthorizationService>();
|
||||||
|
|
||||||
|
// Build a policy for the requested roles if specified
|
||||||
|
if (_rolesSplit != null)
|
||||||
|
{
|
||||||
|
var rolesPolicy = new AuthorizationPolicyBuilder();
|
||||||
|
rolesPolicy.RequiresRole(_rolesSplit);
|
||||||
|
if (!await authService.AuthorizeAsync(rolesPolicy.Build(), httpContext, context))
|
||||||
{
|
{
|
||||||
Fail(context);
|
Fail(context);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
var authorized = (Policy == null)
|
||||||
|
// [Authorize] with no policy just requires any authenticated user
|
||||||
|
? await authService.AuthorizeAsync(BuildAnyAuthorizedUserPolicy(), httpContext, context)
|
||||||
|
: await authService.AuthorizeAsync(Policy, httpContext, context);
|
||||||
|
if (!authorized)
|
||||||
{
|
{
|
||||||
var authorizationService = httpContext.RequestServices.GetRequiredService<IAuthorizationService>();
|
Fail(context);
|
||||||
|
|
||||||
if (authorizationService == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
Resources.AuthorizeAttribute_AuthorizationServiceMustBeDefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
var authorized = await authorizationService.AuthorizeAsync(_claims, user);
|
|
||||||
|
|
||||||
if (!authorized)
|
|
||||||
{
|
|
||||||
Fail(context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static AuthorizationPolicy BuildAnyAuthorizedUserPolicy()
|
||||||
|
{
|
||||||
|
return new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
||||||
|
}
|
||||||
|
|
||||||
public sealed override void OnAuthorization([NotNull] AuthorizationContext context)
|
public sealed override void OnAuthorization([NotNull] AuthorizationContext context)
|
||||||
{
|
{
|
||||||
// The async filter will be called by the filter pipeline.
|
// The async filter will be called by the filter pipeline.
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
// 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.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
using Microsoft.AspNet.Routing;
|
using Microsoft.AspNet.Routing;
|
||||||
using Microsoft.AspNet.Security.DataProtection;
|
using Microsoft.AspNet.Security;
|
||||||
using Microsoft.Framework.ConfigurationModel;
|
using Microsoft.Framework.ConfigurationModel;
|
||||||
|
|
||||||
namespace Microsoft.Framework.DependencyInjection
|
namespace Microsoft.Framework.DependencyInjection
|
||||||
|
|
@ -23,10 +26,12 @@ namespace Microsoft.Framework.DependencyInjection
|
||||||
services.AddDataProtection(configuration);
|
services.AddDataProtection(configuration);
|
||||||
services.AddRouting(configuration);
|
services.AddRouting(configuration);
|
||||||
services.AddScopedInstance(configuration);
|
services.AddScopedInstance(configuration);
|
||||||
|
services.AddAuthorization(configuration);
|
||||||
services.Configure<RouteOptions>(routeOptions =>
|
services.Configure<RouteOptions>(routeOptions =>
|
||||||
routeOptions.ConstraintMap
|
routeOptions.ConstraintMap
|
||||||
.Add("exists",
|
.Add("exists",
|
||||||
typeof(KnownRouteValueConstraint)));
|
typeof(KnownRouteValueConstraint)));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,6 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
// Security and Authorization
|
// Security and Authorization
|
||||||
|
|
||||||
yield return describe.Transient<IAuthorizationService, DefaultAuthorizationService>();
|
|
||||||
yield return describe.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>();
|
yield return describe.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>();
|
||||||
yield return describe.Singleton<AntiForgery, AntiForgery>();
|
yield return describe.Singleton<AntiForgery, AntiForgery>();
|
||||||
yield return describe.Singleton<IAntiForgeryAdditionalDataProvider,
|
yield return describe.Singleton<IAntiForgeryAdditionalDataProvider,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
// 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.Linq;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Security;
|
using Microsoft.AspNet.Security;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
|
@ -17,11 +15,15 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
||||||
public async Task Invoke_ValidClaimShouldNotFail()
|
public async Task Invoke_ValidClaimShouldNotFail()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizeAttribute = new AuthorizeAttribute("CanViewPage");
|
||||||
var authorizeAttribute = new AuthorizeAttribute("Permission", "CanViewPage");
|
|
||||||
var authorizationContext = GetAuthorizationContext(services =>
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
services.AddInstance<IAuthorizationService>(authorizationService)
|
{
|
||||||
);
|
services.AddAuthorization(null, options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage");
|
||||||
|
options.AddPolicy("CanViewPage", policy.Build());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
@ -34,12 +36,11 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
||||||
public async Task Invoke_EmptyClaimsShouldRejectAnonymousUser()
|
public async Task Invoke_EmptyClaimsShouldRejectAnonymousUser()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizationOptions = new AuthorizationOptions();
|
||||||
var authorizeAttribute = new AuthorizeAttribute();
|
var authorizeAttribute = new AuthorizeAttribute();
|
||||||
var authorizationContext = GetAuthorizationContext(services =>
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
services.AddInstance<IAuthorizationService>(authorizationService),
|
services.AddAuthorization(),
|
||||||
anonymous: true
|
anonymous: true);
|
||||||
);
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
@ -52,12 +53,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
||||||
public async Task Invoke_EmptyClaimsWithAllowAnonymousAttributeShouldNotRejectAnonymousUser()
|
public async Task Invoke_EmptyClaimsWithAllowAnonymousAttributeShouldNotRejectAnonymousUser()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
|
||||||
var authorizeAttribute = new AuthorizeAttribute();
|
var authorizeAttribute = new AuthorizeAttribute();
|
||||||
var authorizationContext = GetAuthorizationContext(services =>
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
services.AddInstance<IAuthorizationService>(authorizationService),
|
{
|
||||||
anonymous: true
|
services.AddAuthorization();
|
||||||
);
|
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
|
||||||
|
},
|
||||||
|
anonymous: true);
|
||||||
|
|
||||||
authorizationContext.Filters.Add(new AllowAnonymousAttribute());
|
authorizationContext.Filters.Add(new AllowAnonymousAttribute());
|
||||||
|
|
||||||
|
|
@ -72,11 +74,12 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
||||||
public async Task Invoke_EmptyClaimsShouldAuthorizeAuthenticatedUser()
|
public async Task Invoke_EmptyClaimsShouldAuthorizeAuthenticatedUser()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
|
||||||
var authorizeAttribute = new AuthorizeAttribute();
|
var authorizeAttribute = new AuthorizeAttribute();
|
||||||
var authorizationContext = GetAuthorizationContext(services =>
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
services.AddInstance<IAuthorizationService>(authorizationService)
|
{
|
||||||
);
|
services.AddAuthorization();
|
||||||
|
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
|
||||||
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
@ -89,11 +92,16 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
||||||
public async Task Invoke_SingleValidClaimShouldSucceed()
|
public async Task Invoke_SingleValidClaimShouldSucceed()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizeAttribute = new AuthorizeAttribute("CanViewCommentOrPage");
|
||||||
var authorizeAttribute = new AuthorizeAttribute("Permission", "CanViewComment", "CanViewPage");
|
|
||||||
var authorizationContext = GetAuthorizationContext(services =>
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
services.AddInstance<IAuthorizationService>(authorizationService)
|
{
|
||||||
);
|
services.AddAuthorization(null, options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewComment", "CanViewPage");
|
||||||
|
options.AddPolicy("CanViewCommentOrPage", policy.Build());
|
||||||
|
});
|
||||||
|
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
|
||||||
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
@ -102,15 +110,96 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
||||||
Assert.Null(authorizationContext.Result);
|
Assert.Null(authorizationContext.Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_RequireAdminRoleShouldFailWithNoHandlers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizeAttribute = new AuthorizeAttribute { Roles = "Administrator" };
|
||||||
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
|
{
|
||||||
|
services.AddOptions();
|
||||||
|
services.AddTransient<IAuthorizationService, DefaultAuthorizationService>();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(authorizationContext.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_RequireAdminAndUserRoleWithNoPolicyShouldSucceed()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizeAttribute = new AuthorizeAttribute { Roles = "Administrator,User" };
|
||||||
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
|
{
|
||||||
|
services.AddAuthorization();
|
||||||
|
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Null(authorizationContext.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_RequireUnknownRoleShouldFail()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizeAttribute = new AuthorizeAttribute { Roles = "Wut" };
|
||||||
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
|
{
|
||||||
|
services.AddAuthorization();
|
||||||
|
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(authorizationContext.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_RequireAdminRoleButFailPolicyShouldFail()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizeAttribute = new AuthorizeAttribute { Roles = "Administrator", Policy = "Basic" };
|
||||||
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
|
{
|
||||||
|
services.AddAuthorization(null, options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewComment");
|
||||||
|
options.AddPolicy("CanViewComment", policy.Build());
|
||||||
|
});
|
||||||
|
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(authorizationContext.Result);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Invoke_InvalidClaimShouldFail()
|
public async Task Invoke_InvalidClaimShouldFail()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(Enumerable.Empty<IAuthorizationPolicy>());
|
var authorizeAttribute = new AuthorizeAttribute("CanViewComment");
|
||||||
var authorizeAttribute = new AuthorizeAttribute("Permission", "CanViewComment");
|
|
||||||
var authorizationContext = GetAuthorizationContext(services =>
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
services.AddInstance<IAuthorizationService>(authorizationService)
|
{
|
||||||
);
|
services.AddAuthorization(null, options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewComment");
|
||||||
|
options.AddPolicy("CanViewComment", policy.Build());
|
||||||
|
});
|
||||||
|
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
|
||||||
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
@ -126,16 +215,16 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
||||||
bool authorizationServiceIsCalled = false;
|
bool authorizationServiceIsCalled = false;
|
||||||
var authorizationService = new Mock<IAuthorizationService>();
|
var authorizationService = new Mock<IAuthorizationService>();
|
||||||
authorizationService
|
authorizationService
|
||||||
.Setup(x => x.AuthorizeAsync(Enumerable.Empty<Claim>(), null, null))
|
.Setup(x => x.AuthorizeAsync("CanViewComment", null, null))
|
||||||
.Returns(() =>
|
.Returns(() =>
|
||||||
{
|
{
|
||||||
authorizationServiceIsCalled = true;
|
authorizationServiceIsCalled = true;
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
var authorizeAttribute = new AuthorizeAttribute("Permission", "CanViewComment");
|
var authorizeAttribute = new AuthorizeAttribute("CanViewComment");
|
||||||
var authorizationContext = GetAuthorizationContext(services =>
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
services.AddInstance<IAuthorizationService>(authorizationService.Object)
|
services.AddInstance(authorizationService.Object)
|
||||||
);
|
);
|
||||||
|
|
||||||
authorizationContext.Result = new HttpStatusCodeResult(401);
|
authorizationContext.Result = new HttpStatusCodeResult(401);
|
||||||
|
|
@ -148,14 +237,60 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Invoke_NullPoliciesShouldNotFail()
|
public async Task Invoke_FailWhenLookingForClaimInOtherIdentity()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authorizationService = new DefaultAuthorizationService(policies: null);
|
var authorizeAttribute = new AuthorizeAttribute("CanViewComment");
|
||||||
var authorizeAttribute = new AuthorizeAttribute("Permission", "CanViewPage");
|
|
||||||
var authorizationContext = GetAuthorizationContext(services =>
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
services.AddInstance<IAuthorizationService>(authorizationService)
|
{
|
||||||
);
|
services.AddAuthorization(null, options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder("Bearer").RequiresClaim("Permission", "CanViewComment");
|
||||||
|
options.AddPolicy("CanViewComment", policy.Build());
|
||||||
|
});
|
||||||
|
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(authorizationContext.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_CanLookingForClaimsInMultipleIdentities()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizeAttribute = new AuthorizeAttribute("CanViewCommentCupBearer");
|
||||||
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
|
{
|
||||||
|
services.AddAuthorization(null, options =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder("Basic", "Bearer")
|
||||||
|
.RequiresClaim("Permission", "CanViewComment")
|
||||||
|
.RequiresClaim("Permission", "CupBearer");
|
||||||
|
options.AddPolicy("CanViewComment", policy.Build());
|
||||||
|
});
|
||||||
|
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(authorizationContext.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Invoke_NoPoliciesShouldNotFail()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var authorizeAttribute = new AuthorizeAttribute("CanViewPage");
|
||||||
|
var authorizationContext = GetAuthorizationContext(services =>
|
||||||
|
{
|
||||||
|
services.AddAuthorization();
|
||||||
|
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
|
||||||
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,18 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
||||||
new Claim[] {
|
new Claim[] {
|
||||||
new Claim("Permission", "CanViewPage"),
|
new Claim("Permission", "CanViewPage"),
|
||||||
new Claim(ClaimTypes.Role, "Administrator"),
|
new Claim(ClaimTypes.Role, "Administrator"),
|
||||||
|
new Claim(ClaimTypes.Role, "User"),
|
||||||
new Claim(ClaimTypes.NameIdentifier, "John")},
|
new Claim(ClaimTypes.NameIdentifier, "John")},
|
||||||
"Basic"));
|
"Basic"));
|
||||||
|
|
||||||
|
validUser.AddIdentity(
|
||||||
|
new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim("Permission", "CupBearer"),
|
||||||
|
new Claim(ClaimTypes.Role, "Token"),
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, "John Bear")},
|
||||||
|
"Bearer"));
|
||||||
|
|
||||||
// ServiceProvider
|
// ServiceProvider
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
if (registerServices != null)
|
if (registerServices != null)
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,37 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
Assert.Equal("Hello World!", await response.Content.ReadAsStringAsync());
|
Assert.Equal("Hello World!", await response.Content.ReadAsStringAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task AllowAnonymousOverridesAuthorize()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_services, _app);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await client.GetAsync(
|
||||||
|
"http://localhost/AuthorizeUser/AlwaysCanCallAllowAnonymous");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("Hello World!", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ImpossiblePolicyFailsAuthorize()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_services, _app);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await client.GetAsync(
|
||||||
|
"http://localhost/AuthorizeUser/Impossible");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ServiceFilterUsesRegisteredServicesAsFilter()
|
public async Task ServiceFilterUsesRegisteredServicesAsFilter()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using Microsoft.AspNet.Builder;
|
||||||
|
using Microsoft.AspNet.Http.Security;
|
||||||
|
using Microsoft.AspNet.Security;
|
||||||
|
using Microsoft.AspNet.Security.Infrastructure;
|
||||||
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
|
namespace FiltersWebSite
|
||||||
|
{
|
||||||
|
public class BasicOptions : AuthenticationOptions
|
||||||
|
{
|
||||||
|
public BasicOptions()
|
||||||
|
{
|
||||||
|
AuthenticationType = "Basic";
|
||||||
|
AuthenticationMode = AuthenticationMode.Passive;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AuthorizeBasicMiddleware : AuthenticationMiddleware<BasicOptions>
|
||||||
|
{
|
||||||
|
public AuthorizeBasicMiddleware(
|
||||||
|
RequestDelegate next,
|
||||||
|
IServiceProvider services,
|
||||||
|
IOptions<BasicOptions> options) :
|
||||||
|
base(next, services, options, null)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
protected override AuthenticationHandler<BasicOptions> CreateHandler()
|
||||||
|
{
|
||||||
|
return new BasicAuthenticationHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BasicAuthenticationHandler : AuthenticationHandler<BasicOptions>
|
||||||
|
{
|
||||||
|
protected override void ApplyResponseChallenge()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ApplyResponseGrant()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override AuthenticationTicket AuthenticateCore()
|
||||||
|
{
|
||||||
|
var id = new ClaimsIdentity(
|
||||||
|
new Claim[] {
|
||||||
|
new Claim("Permission", "CanViewPage"),
|
||||||
|
new Claim(ClaimTypes.Role, "Administrator"),
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, "John")},
|
||||||
|
"Basic");
|
||||||
|
|
||||||
|
return new AuthenticationTicket(id, new AuthenticationProperties());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,12 +6,27 @@ using Microsoft.AspNet.Mvc;
|
||||||
namespace FiltersWebSite
|
namespace FiltersWebSite
|
||||||
{
|
{
|
||||||
[AuthorizeUser]
|
[AuthorizeUser]
|
||||||
|
[Authorize("RequireBasic")]
|
||||||
public class AuthorizeUserController : Controller
|
public class AuthorizeUserController : Controller
|
||||||
{
|
{
|
||||||
[Authorize("Permission", "CanViewPage")]
|
[Authorize("CanViewPage")]
|
||||||
public string ReturnHelloWorldOnlyForAuthorizedUser()
|
public string ReturnHelloWorldOnlyForAuthorizedUser()
|
||||||
{
|
{
|
||||||
return "Hello World!";
|
return "Hello World!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize("Impossible")]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public string AlwaysCanCallAllowAnonymous()
|
||||||
|
{
|
||||||
|
return "Hello World!";
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize("Impossible")]
|
||||||
|
public string Impossible()
|
||||||
|
{
|
||||||
|
return "Hello World!";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
// 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.Security.Claims;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
|
using Microsoft.AspNet.Security;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
|
||||||
namespace FiltersWebSite
|
namespace FiltersWebSite
|
||||||
|
|
@ -16,6 +18,21 @@ namespace FiltersWebSite
|
||||||
app.UseServices(services =>
|
app.UseServices(services =>
|
||||||
{
|
{
|
||||||
services.AddMvc(configuration);
|
services.AddMvc(configuration);
|
||||||
|
services.Configure<AuthorizationOptions>(options =>
|
||||||
|
{
|
||||||
|
// This policy cannot succeed since it has no requirements
|
||||||
|
options.AddPolicy("Impossible",
|
||||||
|
new AuthorizationPolicyBuilder()
|
||||||
|
.Build());
|
||||||
|
options.AddPolicy("RequireBasic",
|
||||||
|
new AuthorizationPolicyBuilder("Basic")
|
||||||
|
.RequiresClaim(ClaimTypes.NameIdentifier)
|
||||||
|
.Build());
|
||||||
|
options.AddPolicy("CanViewPage",
|
||||||
|
new AuthorizationPolicyBuilder()
|
||||||
|
.RequiresClaim("Permission", "CanViewPage")
|
||||||
|
.Build());
|
||||||
|
});
|
||||||
services.AddSingleton<RandomNumberFilter>();
|
services.AddSingleton<RandomNumberFilter>();
|
||||||
services.AddSingleton<RandomNumberService>();
|
services.AddSingleton<RandomNumberService>();
|
||||||
|
|
||||||
|
|
@ -31,6 +48,8 @@ namespace FiltersWebSite
|
||||||
|
|
||||||
app.UseErrorReporter();
|
app.UseErrorReporter();
|
||||||
|
|
||||||
|
app.UseMiddleware<AuthorizeBasicMiddleware>();
|
||||||
|
|
||||||
app.UseMvc();
|
app.UseMvc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue