Skip to content

Commit d0b411f

Browse files
authored
Added authorization for VariableReference fields (#179)
1 parent a193954 commit d0b411f

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

src/GraphQL.Authorization.Tests/AuthorizationValidationRuleTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,48 @@ public void Issue61()
177177
});
178178
}
179179

180+
[Fact]
181+
public void passes_with_claim_on_variable_type()
182+
{
183+
Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));
184+
185+
ShouldPassRule(config =>
186+
{
187+
config.Query = @"query Author($input: AuthorInputType!) { author(input: $input) }";
188+
config.Schema = TypedSchema();
189+
config.Inputs = new Inputs(new Dictionary<string, object>()
190+
{
191+
{
192+
"input",
193+
new Dictionary<string,object>{ { "name","Quinn" } }
194+
}
195+
});
196+
config.User = CreatePrincipal(claims: new Dictionary<string, string>
197+
{
198+
{ "Admin", "true" }
199+
});
200+
});
201+
}
202+
203+
[Fact]
204+
public void fails_on_missing_claim_on_variable_type()
205+
{
206+
Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));
207+
208+
ShouldFailRule(config =>
209+
{
210+
config.Query = @"query Author($input: AuthorInputType!) { author(input: $input) }";
211+
config.Schema = TypedSchema();
212+
config.Inputs = new Inputs(new Dictionary<string, object>()
213+
{
214+
{
215+
"input",
216+
new Dictionary<string,object>{ { "name","Quinn" } }
217+
}
218+
});
219+
});
220+
}
221+
180222
[Fact]
181223
public void passes_with_policy_on_connection_type()
182224
{

src/GraphQL.Authorization/AuthorizationValidationRule.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Generic;
12
using System.Threading.Tasks;
23
using GraphQL.Language.AST;
34
using GraphQL.Types;
@@ -63,6 +64,30 @@ public Task<INodeVisitor> ValidateAsync(ValidationContext context)
6364
CheckAuth(fieldAst, fieldDef, userContext, context, operationType);
6465
// check returned graph type
6566
CheckAuth(fieldAst, fieldDef.ResolvedType.GetNamedType(), userContext, context, operationType);
67+
}),
68+
69+
new MatchingNodeVisitor<VariableReference>((variableRef, context) =>
70+
{
71+
if (!(context.TypeInfo.GetArgument().ResolvedType.GetNamedType() is IComplexGraphType variableType))
72+
return;
73+
74+
CheckAuth(variableRef, variableType, userContext, context, operationType);
75+
76+
// Check each supplied field in the variable that exists in the variable type.
77+
// If some supplied field does not exist in the variable type then some other
78+
// validation rule should check that but here we should just ignore that
79+
// "unknown" field.
80+
if (context.Inputs.TryGetValue(variableRef.Name, out object input) &&
81+
input is Dictionary<string, object> fieldsValues)
82+
{
83+
foreach (var field in variableType.Fields)
84+
{
85+
if (fieldsValues.ContainsKey(field.Name))
86+
{
87+
CheckAuth(variableRef, field, userContext, context, operationType);
88+
}
89+
}
90+
}
6691
})
6792
));
6893
}

0 commit comments

Comments
 (0)