Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Use Microsoft.AspNetCore.Authorization but only for .NET Core #13

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#if (!NET46)
using System.Collections.Generic;
using GraphQL;
using GraphQL.Types;
using Xunit;

namespace GraphQL.Authorization.Tests
{
public class AuthorizationValidationRuleTests : ValidationTestBase
{
[Fact]
public void class_policy_success()
{
ConfigureAuthorizationOptions(
options =>
{
options.AddPolicy("ClassPolicy", x => x.RequireClaim("admin"));
});

ShouldPassRule(_ =>
{
_.Query = @"query { post }";
_.Schema = BasicSchema<BasicQueryWithAttributesAndClassPolicy>();
_.User = CreatePrincipal(claims: new Dictionary<string, string>
{
{"Admin", "true"}
});
});
}

[Fact]
public void class_policy_fail()
{
ConfigureAuthorizationOptions(
options =>
{
options.AddPolicy("ClassPolicy", x => x.RequireClaim("admin"));
});

ShouldFailRule(_ =>
{
_.Query = @"query { post }";
_.Schema = BasicSchema<BasicQueryWithAttributesAndClassPolicy>();
});
}

[Fact]
public void field_policy_success()
{
ConfigureAuthorizationOptions(
options =>
{
options.AddPolicy("FieldPolicy", x => x.RequireClaim("admin"));
});

ShouldPassRule(_ =>
{
_.Query = @"query { post }";
_.Schema = BasicSchema<BasicQueryWithAttributesAndFieldPolicy>();
_.User = CreatePrincipal(claims: new Dictionary<string, string>
{
{"Admin", "true"}
});
});
}

[Fact]
public void field_policy_fail()
{
ConfigureAuthorizationOptions(
options =>
{
options.AddPolicy("FieldPolicy", x => x.RequireClaim("admin"));
});

ShouldFailRule(_ =>
{
_.Query = @"query { post }";
_.Schema = BasicSchema<BasicQueryWithAttributesAndFieldPolicy>();
});
}

[Fact]
public void nested_type_policy_success()
{
ConfigureAuthorizationOptions(
options =>
{
options.AddPolicy("PostPolicy", x => x.RequireClaim("admin"));
});

ShouldPassRule(_ =>
{
_.Query = @"query { post }";
_.Schema = NestedSchema();
_.User = CreatePrincipal(claims: new Dictionary<string, string>
{
{"Admin", "true"}
});
});
}

[Fact]
public void nested_type_policy_fail()
{
ConfigureAuthorizationOptions(
options =>
{
options.AddPolicy("PostPolicy", x => x.RequireClaim("admin"));
});

ShouldFailRule(_ =>
{
_.Query = @"query { post }";
_.Schema = NestedSchema();
});
}

private ISchema BasicSchema<T>()
{
string defs = @"
type Query {
post(id: ID!): String
}
";

return Schema.For(defs, _ =>
{
_.Types.Include<T>();
});
}

[GraphQLMetadata("Query")]
[GraphQLAuthorize(Policy = "ClassPolicy")]
public class BasicQueryWithAttributesAndClassPolicy
{
public string Post(string id)
{
return "";
}
}

[GraphQLMetadata("Query")]
public class BasicQueryWithAttributesAndFieldPolicy
{
[GraphQLAuthorize(Policy = "FieldPolicy")]
public string Post(string id)
{
return "";
}
}

private ISchema NestedSchema()
{
string defs = @"
type Query {
post(id: ID!): Post
}

type Post {
id: ID!
}
";

return Schema.For(defs, _ =>
{
_.Types.Include<NestedQueryWithAttributes>();
_.Types.Include<Post>();
});
}

[GraphQLMetadata("Query")]
public class NestedQueryWithAttributes
{
public Post Post(string id)
{
return null;
}
}

[GraphQLAuthorize(Policy = "PostPolicy")]
public class Post
{
public string Id { get; set; }
}

public class Author
{
public string Name { get; set; }
}
}
}
#endif
119 changes: 119 additions & 0 deletions src/GraphQL.Authorization.Tests/CoreFramework/ValidationTestBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#if (!NET46)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using GraphQL;
using GraphQL.Execution;
using GraphQL.Http;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Shouldly;
using Xunit;

namespace GraphQL.Authorization.Tests
{
public class ValidationTestConfig
{
private readonly List<IValidationRule> _rules = new List<IValidationRule>();

public string Query { get; set; }
public ISchema Schema { get; set; }
public IEnumerable<IValidationRule> Rules => _rules;
public ClaimsPrincipal User { get; set; }
public Inputs Inputs { get; set; }

public void Rule(params IValidationRule[] rules)
{
_rules.AddRange(rules);
}
}

public class GraphQLUserContext : IProvideClaimsPrincipal
{
public ClaimsPrincipal User { get; set;}
}

public class ValidationTestBase
{
private IDocumentExecuter _executor = new DocumentExecuter();
private IDocumentWriter _writer = new DocumentWriter(indent: true);

protected AuthorizationValidationRule Rule { get; private set; }

protected void ConfigureAuthorizationOptions(Action<AuthorizationOptions> setupOptions)
{
var authorizationService = BuildAuthorizationService(setupOptions);
Rule = new AuthorizationValidationRule(authorizationService);
}

protected void ShouldPassRule(Action<ValidationTestConfig> configure)
{
var config = new ValidationTestConfig();
config.Rule(Rule);
configure(config);

config.Rules.Any().ShouldBeTrue("Must provide at least one rule to validate against.");

config.Schema.Initialize();

var result = Validate(config);

var message = "";
if (result.Errors?.Any() == true)
{
message = string.Join(", ", result.Errors.Select(x => x.Message));
}
result.IsValid.ShouldBeTrue(message);
}

protected void ShouldFailRule(Action<ValidationTestConfig> configure)
{
var config = new ValidationTestConfig();
config.Rule(Rule);
configure(config);

config.Rules.Any().ShouldBeTrue("Must provide at least one rule to validate against.");

config.Schema.Initialize();

var result = Validate(config);

result.IsValid.ShouldBeFalse("Expected validation errors though there were none.");
}

private IAuthorizationService BuildAuthorizationService(Action<AuthorizationOptions> setupOptions)
{
var services = new ServiceCollection();
services.AddAuthorization(setupOptions);
services.AddLogging();
services.AddOptions();
return services.BuildServiceProvider().GetRequiredService<IAuthorizationService>();
}

private IValidationResult Validate(ValidationTestConfig config)
{
var userContext = new GraphQLUserContext { User = config.User };
var documentBuilder = new GraphQLDocumentBuilder();
var document = documentBuilder.Build(config.Query);
var validator = new DocumentValidator();
return validator.Validate(config.Query, config.Schema, document, config.Rules, userContext, config.Inputs);
}

protected ClaimsPrincipal CreatePrincipal(string authenticationType = null, IDictionary<string, string> claims = null)
{
var claimsList = new List<Claim>();

claims?.Apply(c =>
{
claimsList.Add(new Claim(c.Key, c.Value));
});

return new ClaimsPrincipal(new ClaimsIdentity(claimsList, authenticationType));
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
#if (NET46)
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Shouldly;
Expand Down Expand Up @@ -142,3 +143,4 @@ private ClaimsPrincipal CreatePrincipal(string authenticationType = null, IDicti
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
#if (NET46)
using System.Linq;
using GraphQL.Types;
using Shouldly;
using Xunit;
Expand Down Expand Up @@ -44,3 +45,4 @@ public string Post(string id)
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
#if (NET46)
using System.Linq;
using Shouldly;
using Xunit;

Expand Down Expand Up @@ -28,3 +29,4 @@ public void can_add_a_claim_policy()
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if (NET46)
using System.Collections.Generic;
using GraphQL;
using GraphQL.Types;
Expand Down Expand Up @@ -174,3 +175,4 @@ public class Author
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
#if (NET46)
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
Expand Down Expand Up @@ -103,3 +104,4 @@ private ClaimsPrincipal CreatePrincipal(string authenticationType = null, IDicti
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if (NET46)
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -104,3 +105,4 @@ protected ClaimsPrincipal CreatePrincipal(string authenticationType = null, IDic
}
}
}
#endif
Loading