Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- ubuntu-latest
- windows-latest
graphqlversion:
- 5.0.0-preview-362
- 5.0.0-preview-411
steps:
- name: Checkout source
uses: actions/checkout@v2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ namespace GraphQL.Authorization
public AuthorizationContext() { }
public System.Collections.Generic.IEnumerable<string> Errors { get; }
public bool HasErrors { get; }
public System.Collections.Generic.IReadOnlyDictionary<string, object>? Inputs { get; set; }
public System.Security.Claims.ClaimsPrincipal? User { get; set; }
public System.Collections.Generic.IDictionary<string, object?>? UserContext { get; set; }
public GraphQL.Inputs? Variables { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs extensions also?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDocumentValidator has no access to extensions. Another PR.

public void ReportError(string error) { }
}
public class AuthorizationEvaluator : GraphQL.Authorization.IAuthorizationEvaluator
{
public AuthorizationEvaluator(GraphQL.Authorization.AuthorizationSettings settings) { }
public System.Threading.Tasks.Task<GraphQL.Authorization.AuthorizationResult> Evaluate(System.Security.Claims.ClaimsPrincipal? principal, System.Collections.Generic.IDictionary<string, object?>? userContext, System.Collections.Generic.IReadOnlyDictionary<string, object>? inputs, System.Collections.Generic.IEnumerable<string>? requiredPolicies) { }
public System.Threading.Tasks.Task<GraphQL.Authorization.AuthorizationResult> Evaluate(System.Security.Claims.ClaimsPrincipal? principal, System.Collections.Generic.IDictionary<string, object?>? userContext, GraphQL.Inputs? variables, System.Collections.Generic.IEnumerable<string>? requiredPolicies) { }
}
public class AuthorizationPolicy : GraphQL.Authorization.IAuthorizationPolicy
{
Expand Down Expand Up @@ -70,12 +70,12 @@ namespace GraphQL.Authorization
}
public static class GraphQLBuilderExtensions
{
public static void AddAuthorization(this GraphQL.DI.IGraphQLBuilder builder, System.Action<GraphQL.Authorization.AuthorizationSettings> configure) { }
public static void AddAuthorization(this GraphQL.DI.IGraphQLBuilder builder, System.Action<GraphQL.Authorization.AuthorizationSettings, System.IServiceProvider> configure) { }
public static GraphQL.DI.IGraphQLBuilder AddAuthorization(this GraphQL.DI.IGraphQLBuilder builder, System.Action<GraphQL.Authorization.AuthorizationSettings> configure) { }
public static GraphQL.DI.IGraphQLBuilder AddAuthorization(this GraphQL.DI.IGraphQLBuilder builder, System.Action<GraphQL.Authorization.AuthorizationSettings, System.IServiceProvider> configure) { }
}
public interface IAuthorizationEvaluator
{
System.Threading.Tasks.Task<GraphQL.Authorization.AuthorizationResult> Evaluate(System.Security.Claims.ClaimsPrincipal? principal, System.Collections.Generic.IDictionary<string, object?>? userContext, System.Collections.Generic.IReadOnlyDictionary<string, object>? inputs, System.Collections.Generic.IEnumerable<string>? requiredPolicies);
System.Threading.Tasks.Task<GraphQL.Authorization.AuthorizationResult> Evaluate(System.Security.Claims.ClaimsPrincipal? principal, System.Collections.Generic.IDictionary<string, object?>? userContext, GraphQL.Inputs? variables, System.Collections.Generic.IEnumerable<string>? requiredPolicies);
}
public interface IAuthorizationPolicy
{
Expand Down
38 changes: 19 additions & 19 deletions src/GraphQL.Authorization.Tests/AuthorizationValidationRuleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public void class_policy_success()
config.Query = @"query { post }";
config.Schema = BasicSchema();
config.User = CreatePrincipal(claims: new Dictionary<string, string>
{
{ "Admin", "true" }
});
{
{ "Admin", "true" }
});
});
}

Expand Down Expand Up @@ -77,9 +77,9 @@ public void nested_type_policy_success()
config.Query = @"query { post }";
config.Schema = NestedSchema();
config.User = CreatePrincipal(claims: new Dictionary<string, string>
{
{ "Admin", "true" }
});
{
{ "Admin", "true" }
});
});
}

Expand Down Expand Up @@ -174,9 +174,9 @@ public void passes_with_claim_on_input_type()
config.Query = @"query { author(input: { name: ""Quinn"" }) }";
config.Schema = TypedSchema();
config.User = CreatePrincipal(claims: new Dictionary<string, string>
{
{ "Admin", "true" }
});
{
{ "Admin", "true" }
});
});
}

Expand Down Expand Up @@ -233,17 +233,17 @@ public void passes_with_claim_on_variable_type()
{
config.Query = @"query Author($input: AuthorInputType!) { author(input: $input) }";
config.Schema = TypedSchema();
config.Inputs = new Inputs(new Dictionary<string, object>()
config.Variables = new Inputs(new Dictionary<string, object?>()
{
{
"input",
new Dictionary<string,object>{ { "name","Quinn" } }
"input",
new Dictionary<string,object>{ { "name","Quinn" } }
}
});
config.User = CreatePrincipal(claims: new Dictionary<string, string>
{
{ "Admin", "true" }
});
{
{ "Admin", "true" }
});
});
}

Expand All @@ -263,7 +263,7 @@ public void passes_with_claim_on_variable_type_without_inputs_but_fails_later_ei
};
config.Query = @"query Author($input: AuthorInputType!) { author(input: $input) }";
config.Schema = TypedSchema();
config.Inputs = null;
config.Variables = null;
config.User = CreatePrincipal(claims: new Dictionary<string, string>
{
{ "Admin", "true" }
Expand All @@ -280,11 +280,11 @@ public void fails_on_missing_claim_on_variable_type()
{
config.Query = @"query Author($input: AuthorInputType!) { author(input: $input) }";
config.Schema = TypedSchema();
config.Inputs = new Inputs(new Dictionary<string, object>()
config.Variables = new Inputs(new Dictionary<string, object?>()
{
{
"input",
new Dictionary<string,object>{ { "name","Quinn" } }
"input",
new Dictionary<string,object>{ { "name","Quinn" } }
}
});
});
Expand Down
2 changes: 1 addition & 1 deletion src/GraphQL.Authorization.Tests/ValidationTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private static IValidationResult Validate(ValidationTestConfig config)
var documentBuilder = new GraphQLDocumentBuilder();
var document = documentBuilder.Build(config.Query);
var validator = new DocumentValidator();
return validator.ValidateAsync(config.Schema, document, document.Operations.First().Variables, config.Rules, userContext, config.Inputs, config.OperationName).GetAwaiter().GetResult().validationResult;
return validator.ValidateAsync(config.Schema, document, document.Operations.First().Variables, config.Rules, userContext, config.Variables, config.OperationName).GetAwaiter().GetResult().validationResult;
}

internal static ClaimsPrincipal CreatePrincipal(string? authenticationType = null, IDictionary<string, string>? claims = null)
Expand Down
2 changes: 1 addition & 1 deletion src/GraphQL.Authorization.Tests/ValidationTestConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class ValidationTestConfig

public ClaimsPrincipal? User { get; set; }

public Inputs? Inputs { get; set; }
public Inputs? Variables { get; set; }

public Action<IValidationResult> ValidateResult = _ => { };
}
Expand Down
4 changes: 2 additions & 2 deletions src/GraphQL.Authorization/AuthorizationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public class AuthorizationContext
public IDictionary<string, object?>? UserContext { get; set; }

/// <summary>
/// Represents a readonly dictionary of variable inputs to an executed document.
/// Represents a readonly dictionary of variables to an executed document.
/// </summary>
public IReadOnlyDictionary<string, object>? Inputs { get; set; }
public Inputs? Variables { get; set; }

/// <summary>
/// Returns a set of authorization errors.
Expand Down
4 changes: 2 additions & 2 deletions src/GraphQL.Authorization/AuthorizationEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public AuthorizationEvaluator(AuthorizationSettings settings)
public async Task<AuthorizationResult> Evaluate(
ClaimsPrincipal? principal,
IDictionary<string, object?>? userContext,
IReadOnlyDictionary<string, object>? inputs,
Inputs? variables,
IEnumerable<string>? requiredPolicies)
{
if (requiredPolicies == null)
Expand All @@ -34,7 +34,7 @@ public async Task<AuthorizationResult> Evaluate(
{
User = principal ?? new ClaimsPrincipal(new ClaimsIdentity()),
UserContext = userContext,
Inputs = inputs
Variables = variables
};

var tasks = new List<Task>();
Expand Down
6 changes: 3 additions & 3 deletions src/GraphQL.Authorization/AuthorizationValidationRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ void Visit(INode node, int _)
// If some supplied field does not exist in the variable type then some other
// validation rule should check that but here we should just ignore that
// "unknown" field.
if (context.Inputs != null &&
context.Inputs.TryGetValue(variableRef.Name, out object input) &&
if (context.Variables != null &&
context.Variables.TryGetValue(variableRef.Name, out object? input) &&
input is Dictionary<string, object> fieldsValues)
{
foreach (var field in variableType.Fields)
Expand All @@ -163,7 +163,7 @@ private void CheckAuth(

// TODO: async -> sync transition
var result = _evaluator
.Evaluate(userContext?.User, context.UserContext, context.Inputs, provider.GetPolicies())
.Evaluate(userContext?.User, context.UserContext, context.Variables, provider.GetPolicies())
.GetAwaiter()
.GetResult();

Expand Down
14 changes: 8 additions & 6 deletions src/GraphQL.Authorization/GraphQLBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,21 @@ public static class GraphQLBuilderExtensions
/// within <see cref="ExecutionOptions.ValidationRules"/> and <see cref="ExecutionOptions.CachedDocumentValidationRules"/>
/// upon document execution. Configures authorization settings with the specified configuration delegate.
/// </summary>
public static void AddAuthorization(this IGraphQLBuilder builder, Action<AuthorizationSettings, IServiceProvider> configure)
public static IGraphQLBuilder AddAuthorization(this IGraphQLBuilder builder, Action<AuthorizationSettings, IServiceProvider> configure)
{
builder.TryRegister<IAuthorizationEvaluator, AuthorizationEvaluator>(ServiceLifetime.Singleton);
builder.Services.TryRegister<IAuthorizationEvaluator, AuthorizationEvaluator>(ServiceLifetime.Singleton);
builder.AddValidationRule<AuthorizationValidationRule>(true);
builder.Configure(configure);
builder.Services.Configure(configure);
return builder;
}

/// <inheritdoc cref="AddAuthorization(IGraphQLBuilder, Action{AuthorizationSettings, IServiceProvider})"/>
public static void AddAuthorization(this IGraphQLBuilder builder, Action<AuthorizationSettings> configure)
public static IGraphQLBuilder AddAuthorization(this IGraphQLBuilder builder, Action<AuthorizationSettings> configure)
{
builder.TryRegister<IAuthorizationEvaluator, AuthorizationEvaluator>(ServiceLifetime.Singleton);
builder.Services.TryRegister<IAuthorizationEvaluator, AuthorizationEvaluator>(ServiceLifetime.Singleton);
builder.AddValidationRule<AuthorizationValidationRule>(true);
builder.Configure(configure);
builder.Services.Configure(configure);
return builder;
}
}
}
4 changes: 2 additions & 2 deletions src/GraphQL.Authorization/IAuthorizationEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ public interface IAuthorizationEvaluator
/// </summary>
/// <param name="principal">Represents the current user.</param>
/// <param name="userContext">Arbitrary user defined context represented as dictionary.</param>
/// <param name="inputs">Represents a readonly dictionary of variable inputs to an executed document.</param>
/// <param name="variables">Represents a readonly dictionary of variables to an executed document.</param>
/// <param name="requiredPolicies">A set of policies names to authorize.</param>
/// <returns></returns>
Task<AuthorizationResult> Evaluate(
ClaimsPrincipal? principal,
IDictionary<string, object?>? userContext,
IReadOnlyDictionary<string, object>? inputs,
Inputs? variables,
IEnumerable<string>? requiredPolicies);
}
}