Skip to content

Commit

Permalink
Check for AllowFrom attribute at controller level
Browse files Browse the repository at this point in the history
  • Loading branch information
j3parker committed Nov 27, 2015
1 parent fd1c7c5 commit cd9de48
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.Net;
using System.Threading.Tasks;
using NUnit.Framework;
using D2L.Services;

namespace D2L.Security.OAuth2.Authorization {
[TestFixture]
internal sealed class AllowFromControllerTests {
private const string SCOPE = "a:b:c";

[Test]
public async Task Default_NoAuthentication_403() {
await TestUtilities.RunBasicAuthTest( "/allowfrom/default", HttpStatusCode.Unauthorized )
.SafeAsync();
}

[Test]
public async Task Default_UserInvalidScope_401() {
string jwt = await TestUtilities.GetAccessTokenValidForAMinute(
userId: 123,
scope: SCOPE + "foo"
).SafeAsync();

await TestUtilities.RunBasicAuthTest( "/allowfrom/default", jwt, HttpStatusCode.Forbidden )
.SafeAsync();
}

[Test]
public async Task Default_UserValidScope_204() {
string jwt = await TestUtilities.GetAccessTokenValidForAMinute(
userId: 123,
scope: SCOPE
).SafeAsync();

await TestUtilities.RunBasicAuthTest( "/allowfrom/default", jwt, HttpStatusCode.NoContent )
.SafeAsync();
}

[TestCase( 0, "wrong:scope:ok", HttpStatusCode.Unauthorized, TestName="A service with the wrong scope" )]
[TestCase( 0, SCOPE, HttpStatusCode.Unauthorized, TestName= "A service with the right scope" )]
[TestCase( 123, "wrong:scope:ok", HttpStatusCode.Forbidden, TestName = "A user with the wrong scope" )]
[TestCase( 123, SCOPE, HttpStatusCode.NoContent, TestName = "A user with the right scope" )]
public async Task Default_Service_403( long userId, string scope, HttpStatusCode expectedStatusCode ) {
string jwt = await TestUtilities.GetAccessTokenValidForAMinute(
userId: userId == 0 ? (long?)null : userId,
scope: scope
).SafeAsync();

await TestUtilities.RunBasicAuthTest( "/allowfrom/default", jwt, expectedStatusCode )
.SafeAsync();
}

[TestCase( 0, "wrong:scope:ok", HttpStatusCode.Forbidden, TestName="A service with wrong scope fails authz" )]
[TestCase( 0, SCOPE, HttpStatusCode.NoContent, TestName="A service with the right scope succeeds" )]
[TestCase( 123, "wrong:scope:ok", HttpStatusCode.Forbidden, TestName="A user with the wrong scope fails authz (wrong kind of authn) TODO: does 401 instead of 403 (arguably) due to order of attributes" )]
[TestCase( 123, SCOPE, HttpStatusCode.Unauthorized, TestName="A user with the right scope fails authz (wrong kind of authn)" )]
public async Task ServicesOnly_AuthenticationOkCases( long userId, string scope, HttpStatusCode expectedStatusCode ) {
string jwt = await TestUtilities.GetAccessTokenValidForAMinute(
userId: userId == 0 ? (long?)null : userId,
scope: scope
).SafeAsync();

await TestUtilities.RunBasicAuthTest( "/allowfrom/servicesonly", jwt, expectedStatusCode )
.SafeAsync();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,11 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Authentication\OAuth2AuthenticationFilterTests.cs" />
<Compile Include="Authorization\AllowFromControllerTests.cs" />
<Compile Include="Authorization\DefaultAuthorizationAttributeTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SetUpFixture.cs" />
<Compile Include="TestWebService\Controllers\AllowFromController.cs" />
<Compile Include="TestWebService\Controllers\AuthenticationFilterTestsController.cs" />
<Compile Include="TestWebService\Controllers\AuthorizationAttributeTestsController.cs" />
<Compile Include="TestUtilities.cs" />
Expand Down
4 changes: 2 additions & 2 deletions D2L.Security.OAuth2.WebApi.IntegrationTests/SetupFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ private void OwinStartup( IAppBuilder appBuilder ) {
principalDependencyRegistry: new Mock<ID2LPrincipalDependencyRegistry>( MockBehavior.Loose ).Object
);

config.MapHttpAttributeRoutes();

// TODO: adding this globally might suck later depending on what we want to test
config.Filters.Add( authFilter );

config.MapHttpAttributeRoutes();

config.EnsureInitialized();

appBuilder.UseWebApi( config );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Web.Http;
using D2L.Security.OAuth2.Authorization;

namespace D2L.Security.OAuth2.TestWebService.Controllers {
[DefaultAuthorization]
[AllowFrom( users: true )]
public sealed class AllowFromController : ApiController {
[HttpGet]
[RequireScope("a","b","c")]
[Route("allowfrom/default")]
public void Default() {

}

[HttpGet]
[RequireScope("a","b","c")]
[Route("allowfrom/servicesonly")]
[AllowFrom( users: false, services: true )]
public void ServicesOnly() {

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ private static void RequireScopeSpecification( HttpActionContext context ) {
}

private static void RequirePrincipalTypeSpecification( HttpActionContext context ) {
AuthorizeAttribute allowFromAttribute = context.ActionDescriptor.GetCustomAttributes<AllowFromAttribute>().SingleOrDefault();
var allowFromAttribute = context.ActionDescriptor.GetCustomAttributes<AllowFromAttribute>().SingleOrDefault();
var allowFromAttribute2 = context.ActionDescriptor.ControllerDescriptor.ControllerType.GetCustomAttributes( typeof( AllowFromAttribute ), inherit: false ).SingleOrDefault();

if ( allowFromAttribute == null ) {
if ( allowFromAttribute == null && allowFromAttribute2 == null ) {
throw new Exception( "You must specify the types of callers for this API with [AllowFrom(...)]" );
}
}
Expand Down

0 comments on commit cd9de48

Please sign in to comment.