Full Code of graphql-dotnet/authorization for AI

master 21a629e1eb42 cached
57 files
113.0 KB
28.8k tokens
128 symbols
1 requests
Download .txt
Repository: graphql-dotnet/authorization
Branch: master
Commit: 21a629e1eb42
Files: 57
Total size: 113.0 KB

Directory structure:
gitextract_vfdy268n/

├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   ├── codecov.yaml
│   ├── dependabot.yml
│   ├── labeler.yml
│   └── workflows/
│       ├── build.yml
│       ├── codeql-analysis.yml
│       ├── format.yml
│       ├── label.yml
│       ├── publish.yml
│       ├── test.yml
│       └── wipcheck.yml
├── .gitignore
├── .vscode/
│   ├── launch.json
│   └── tasks.json
├── LICENSE.md
├── README.md
├── codeql/
│   └── GraphQL.Authorization.CodeQL.sln
└── src/
    ├── BasicSample/
    │   ├── BasicSample.csproj
    │   └── Program.cs
    ├── Directory.Build.props
    ├── Directory.Build.targets
    ├── GraphQL.Authorization/
    │   ├── AuthorizationContext.cs
    │   ├── AuthorizationEvaluator.cs
    │   ├── AuthorizationPolicy.cs
    │   ├── AuthorizationPolicyBuilder.cs
    │   ├── AuthorizationResult.cs
    │   ├── AuthorizationSettings.cs
    │   ├── AuthorizationValidationRule.cs
    │   ├── Extensions/
    │   │   └── AuthorizationGraphQLBuilderExtensions.cs
    │   ├── GraphQL.Authorization.csproj
    │   ├── IAuthorizationEvaluator.cs
    │   ├── IAuthorizationPolicy.cs
    │   └── Requirements/
    │       ├── AuthenticatedUserRequirement.cs
    │       ├── ClaimAuthorizationRequirement.cs
    │       └── IAuthorizationRequirement.cs
    ├── GraphQL.Authorization.ApiTests/
    │   ├── ApiApprovalTests.cs
    │   ├── GraphQL.Authorization.ApiTests.csproj
    │   └── GraphQL.Authorization.approved.txt
    ├── GraphQL.Authorization.Tests/
    │   ├── AuthenticatedUserRequirementTests.cs
    │   ├── AuthorizationEvaluatorTests.cs
    │   ├── AuthorizationSchemaBuilderTests.cs
    │   ├── AuthorizationSettingsTests.cs
    │   ├── AuthorizationValidationRuleTests.cs
    │   ├── ClaimAuthorizationRequirementTests.cs
    │   ├── GraphQL.Authorization.Tests.csproj
    │   ├── ValidationTestBase.cs
    │   └── ValidationTestConfig.cs
    ├── GraphQL.Authorization.sln
    ├── Harness/
    │   ├── GraphQL.cs
    │   ├── Harness.csproj
    │   ├── Program.cs
    │   ├── Properties/
    │   │   └── launchSettings.json
    │   ├── appsettings.Development.json
    │   └── appsettings.json
    ├── Tests.props
    └── xunit.runner.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# EditorConfig is awesome: http://EditorConfig.org

# Create portable, custom editor settings with EditorConfig
# https://docs.microsoft.com/en-us/visualstudio/ide/create-portable-custom-editor-options

# .NET coding convention settings for EditorConfig
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference?view=vs-2019

# Language conventions
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019

# Formatting conventions
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions?view=vs-2019

# .NET naming conventions for EditorConfig
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-naming-conventions?view=vs-2019

# Top-most EditorConfig file
root = true

# Editor default newlines with a newline ending every file
[*]
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 2
trim_trailing_whitespace = true

[*.json]
insert_final_newline = false

[*.cs]
indent_size = 4

[*.txt]
insert_final_newline = false

# Code files
[*.{cs,vb}]

# .NET code style settings - "This." and "Me." qualifiers
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#this-and-me
dotnet_style_qualification_for_field = false:warning
dotnet_style_qualification_for_property = false:warning
dotnet_style_qualification_for_method = false:warning
dotnet_style_qualification_for_event = false:warning

# .NET code style settings - Language keywords instead of framework type names for type references
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#language-keywords
dotnet_style_predefined_type_for_locals_parameters_members = true:error
dotnet_style_predefined_type_for_member_access = true:error

# .NET code style settings - Modifier preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#normalize-modifiers
dotnet_style_require_accessibility_modifiers = always:warning
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning
dotnet_style_readonly_field = true:warning

# .NET code style settings - Parentheses preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#parentheses-preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:suggestion
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:suggestion
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:suggestion
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion

# .NET code style settings - Expression-level preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#expression-level-preferences
dotnet_style_object_initializer = true:error
dotnet_style_collection_initializer = true:error
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
dotnet_style_prefer_compound_assignment = true:warning

# .NET code style settings - Null-checking preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#null-checking-preferences
dotnet_style_coalesce_expression = true:warning
dotnet_style_null_propagation = true:error

# .NET code quality settings - Parameter preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#parameter-preferences
dotnet_code_quality_unused_parameters = all:warning

# C# code style settings - Implicit and explicit types
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#implicit-and-explicit-types
csharp_style_var_for_built_in_types = false:suggestion
csharp_style_var_when_type_is_apparent = true:warning
csharp_style_var_elsewhere = true:suggestion

# C# code style settings - Expression-bodied members
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#expression-bodied-members
csharp_style_expression_bodied_methods = when_on_single_line:suggestion
csharp_style_expression_bodied_constructors = false:warning
csharp_style_expression_bodied_operators = when_on_single_line:warning
csharp_style_expression_bodied_properties = when_on_single_line:warning
csharp_style_expression_bodied_indexers = when_on_single_line:warning
csharp_style_expression_bodied_accessors = when_on_single_line:warning
csharp_style_expression_bodied_lambdas = when_on_single_line:warning
csharp_style_expression_bodied_local_functions = when_on_single_line:warning

# C# code style settings - Pattern matching
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#pattern-matching
csharp_style_pattern_matching_over_is_with_cast_check = true:error
csharp_style_pattern_matching_over_as_with_null_check = true:error

# C# code style settings - Inlined variable declaration
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#inlined-variable-declarations
csharp_style_inlined_variable_declaration = true:error

# C# code style settings - C# expression-level preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#c-expression-level-preferences
csharp_prefer_simple_default_expression = true:suggestion

# C# code style settings - C# null-checking preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#c-null-checking-preferences
csharp_style_throw_expression = true:warning
csharp_style_conditional_delegate_call = true:warning

# C# code style settings - Code block preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#code-block-preferences
csharp_prefer_braces = when_multiline:suggestion

# C# code style - Unused value preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#unused-value-preferences
csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:suggestion

# C# code style - Index and range preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#index-and-range-preferences
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion

# C# code style - Miscellaneous preferences
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-language-conventions?view=vs-2019#miscellaneous-preferences
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_using_directive_placement = outside_namespace:warning
csharp_prefer_static_local_function = true:suggestion
csharp_prefer_simple_using_statement = false:suggestion
csharp_style_prefer_switch_expression = true:suggestion

# .NET formatting settings - Organize using directives
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions?view=vs-2019#organize-using-directives
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false

# C# formatting settings - New-line options
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions?view=vs-2019#new-line-options
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true

# C# formatting settings - Indentation options
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions?view=vs-2019#indentation-options
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = one_less_than_current
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents_when_block = false

# C# formatting settings - Spacing options
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_after_comma = true
csharp_space_before_comma = false
csharp_space_after_dot = false
csharp_space_before_dot = false
csharp_space_after_semicolon_in_for_statement = true
csharp_space_before_semicolon_in_for_statement = false
csharp_space_around_declaration_statements = false
csharp_space_before_open_square_brackets = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_square_brackets = false

# C# formatting settings - Wrap options
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-formatting-conventions?view=vs-2019#wrap-options
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false

# C# formatting settings - Namespace options
csharp_style_namespace_declarations = file_scoped:suggestion

########## name all private fields using camelCase with underscore prefix ##########
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-naming-conventions?view=vs-2019
# dotnet_naming_rule.<namingRuleTitle>.symbols = <symbolTitle>
dotnet_naming_rule.private_fields_with_underscore.symbols = private_fields

# dotnet_naming_symbols.<symbolTitle>.<property> = <value>
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private

# dotnet_naming_rule.<namingRuleTitle>.style = <styleTitle>
dotnet_naming_rule.private_fields_with_underscore.style = prefix_underscore

# dotnet_naming_style.<styleTitle>.<property> = <value>
dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _

# dotnet_naming_rule.<namingRuleTitle>.severity = <value>
dotnet_naming_rule.private_fields_with_underscore.severity = warning

########## name all constant fields using UPPER_CASE ##########
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-naming-conventions?view=vs-2019
# dotnet_naming_rule.<namingRuleTitle>.symbols = <symbolTitle>
dotnet_naming_rule.constant_fields_should_be_upper_case.symbols = constant_fields

# dotnet_naming_symbols.<symbolTitle>.<property> = <value>
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
dotnet_naming_symbols.constant_fields.required_modifiers = const

# dotnet_naming_rule.<namingRuleTitle>.style = <styleTitle>
dotnet_naming_rule.constant_fields_should_be_upper_case.style = upper_case_style

# dotnet_naming_style.<styleTitle>.<property> = <value>
dotnet_naming_style.upper_case_style.capitalization = all_upper
dotnet_naming_style.upper_case_style.word_separator = _

# dotnet_naming_rule.<namingRuleTitle>.severity = <value>
dotnet_naming_rule.constant_fields_should_be_upper_case.severity = warning

########## Async methods should have "Async" suffix ##########
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-naming-conventions?view=vs-2019
# dotnet_naming_rule.<namingRuleTitle>.symbols = <symbolTitle>
dotnet_naming_rule.async_methods_end_in_async.symbols = any_async_methods

# dotnet_naming_symbols.<symbolTitle>.<property> = <value>
dotnet_naming_symbols.any_async_methods.applicable_kinds = method
dotnet_naming_symbols.any_async_methods.applicable_accessibilities = *
dotnet_naming_symbols.any_async_methods.required_modifiers = async

# dotnet_naming_rule.<namingRuleTitle>.style = <styleTitle>
dotnet_naming_rule.async_methods_end_in_async.style = end_in_async_style

# dotnet_naming_style.<styleTitle>.<property> = <value>
dotnet_naming_style.end_in_async_style.capitalization = pascal_case
dotnet_naming_style.end_in_async_style.word_separator =
dotnet_naming_style.end_in_async_style.required_prefix =
dotnet_naming_style.end_in_async_style.required_suffix = Async

# dotnet_naming_rule.<namingRuleTitle>.severity = <value>
dotnet_naming_rule.async_methods_end_in_async.severity = warning

# Remove unnecessary import https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005
dotnet_diagnostic.IDE0005.severity = error

# Enforce formatting https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#rule-id-ide0055-fix-formatting
dotnet_diagnostic.IDE0055.severity = error

# https://github.com/JosefPihrt/Roslynator/blob/master/docs/analyzers/RCS0060.md
dotnet_diagnostic.RCS0060.severity = warning
roslynator_blank_line_after_file_scoped_namespace_declaration = true

# https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1080.md
dotnet_diagnostic.RCS1080.severity = warning

# ConfigureAwait https://github.com/JosefPihrt/Roslynator/blob/master/docs/analyzers/RCS1090.md
dotnet_diagnostic.RCS1090.severity = warning
roslynator_configure_await = true

# https://github.com/JosefPihrt/Roslynator/blob/master/docs/analyzers/RCS1102.md
# TODO: NullabilityInfo issue in Patching.cs in internal class SR
dotnet_diagnostic.RCS1102.severity = suggestion

# https://github.com/JosefPihrt/Roslynator/blob/master/docs/analyzers/RCS1194.md
dotnet_diagnostic.RCS1194.severity = suggestion


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

open_collective: graphql-net


================================================
FILE: .github/codecov.yaml
================================================
# https://docs.codecov.com/docs/codecov-yaml
comment:
  behavior: new


================================================
FILE: .github/dependabot.yml
================================================
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:

- package-ecosystem: "nuget"
  directory: "/"
  schedule:
    interval: "daily"
  ignore:
    - dependency-name: "GraphQL"
    - dependency-name: "GraphQL.MicrosoftDI"
    - dependency-name: "GraphQL.SystemTextJson"
    - dependency-name: "GraphQL.Server.Transports.AspNetCore"
    - dependency-name: "GraphQL.Server.Ui.GraphiQL"
    - dependency-name: "GraphQL.Server.Ui.Playground"

- package-ecosystem: "github-actions"
  directory: "/"
  schedule:
    interval: "daily"


================================================
FILE: .github/labeler.yml
================================================
test:
  - src/GraphQL.Authorization.Tests/**/*
  - src/GraphQL.Authorization.ApiTests/**/*

CI:
  - .github/workflows/**/*
  - .github/dependabot.yml
  - .github/labeler.yml
  - .github/codecov.yml

code style:
  - .editorconfig

documentation:
  - README.md


================================================
FILE: .github/workflows/build.yml
================================================
name: Build artifacts

# ==== NOTE: do not rename this yml file or the run_number will be reset ====

on:
  push:
    branches:
      - master
      - develop
    paths:
      - src/**
      - .github/workflows/**

env:
  DOTNET_NOLOGO: true
  DOTNET_CLI_TELEMETRY_OPTOUT: true

jobs:
  pack:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup .NET SDK
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: "8.0.x"
          source-url: https://nuget.pkg.github.com/graphql-dotnet/index.json
        env:
          NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
      - name: Install dependencies
        working-directory: src
        run: dotnet restore
      - name: Build solution [Release]
        working-directory: src
        run: dotnet build --no-restore -c Release -p:VersionSuffix=$GITHUB_RUN_NUMBER
      - name: Pack solution [Release]
        working-directory: src
        run: dotnet pack --no-restore --no-build -c Release -p:VersionSuffix=$GITHUB_RUN_NUMBER -o out
      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: Nuget packages
          path: |
            src/out/*
      - name: Publish Nuget packages to GitHub registry
        working-directory: src
        run: dotnet nuget push "out/*" -k ${{secrets.GITHUB_TOKEN}}


================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
# https://github.com/github/codeql
# https://github.com/github/codeql-action
name: CodeQL analysis

on:
  push:
    branches: [master, develop]
  pull_request:
    branches: [master, develop]

jobs:
  analyze:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout source
      uses: actions/checkout@v4

    - name: Setup .NET SDK
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: "8.0.x"
        source-url: https://nuget.pkg.github.com/graphql-dotnet/index.json
      env:
        NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}

    - name: Initialize CodeQL
      uses: github/codeql-action/init@v2
      with:
        queries: security-and-quality
        languages: csharp

    - name: Install dependencies
      working-directory: src
      run: dotnet restore

    - name: Build CodeQL solution
      # https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/troubleshooting-the-codeql-workflow#reduce-the-amount-of-code-being-analyzed-in-a-single-workflow
      working-directory: codeql
      run: dotnet build --no-restore

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v2


================================================
FILE: .github/workflows/format.yml
================================================
name: Check formatting

on:
  pull_request:
    paths:
      - src/**
      - .github/workflows/**

env:
  DOTNET_NOLOGO: true
  DOTNET_CLI_TELEMETRY_OPTOUT: true

jobs:
  format:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout source
        uses: actions/checkout@v4
      - name: Setup .NET SDK
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: 8.0.x
          source-url: https://nuget.pkg.github.com/graphql-dotnet/index.json
        env:
          NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
      - name: Install dependencies
        working-directory: src
        run: dotnet restore
      - name: Check formatting
        working-directory: src
        run: |
          dotnet format --no-restore --verify-no-changes --severity warn || (echo "Run 'dotnet format' to fix issues" && exit 1)


================================================
FILE: .github/workflows/label.yml
================================================
# This workflow will triage pull requests and apply a label based on the
# paths that are modified in the pull request.
#
# To use this workflow, you will need to set up a .github/labeler.yml
# file with configuration. For more information, see:
# https://github.com/actions/labeler/blob/master/README.md

name: Labeler
on:
  pull_request_target:
    types:
      - opened        # when PR is opened

jobs:
  label:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/labeler@v4
      with:
        sync-labels: ""
        repo-token: "${{ secrets.GITHUB_TOKEN }}"
      continue-on-error: true


================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish release

on:
  release:
    types:
      - published

env:
  DOTNET_NOLOGO: true
  DOTNET_CLI_TELEMETRY_OPTOUT: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Check github.ref starts with 'refs/tags/'
        if: ${{ !startsWith(github.ref, 'refs/tags/') }}
        run: |
          echo Error! github.ref does not start with 'refs/tags'
          echo github.ref: ${{ github.ref }}
          exit 1
      - name: Set version number environment variable
        env:
          github_ref: ${{ github.ref }}
        run: |
          version="${github_ref:10}"
          echo version=$version
          echo "version=$version" >> $GITHUB_ENV
      - name: Setup .NET SDK
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: "8.0.x"
          source-url: https://api.nuget.org/v3/index.json
        env:
          NUGET_AUTH_TOKEN: ${{secrets.NUGET_AUTH_TOKEN}}
      - name: Install dependencies
        working-directory: src
        run: dotnet restore
      - name: Build solution [Release]
        working-directory: src
        run: dotnet build --no-restore -c Release -p:Version=$version
      - name: Pack solution [Release]
        working-directory: src
        run: dotnet pack --no-restore --no-build -c Release -p:Version=$version -o out
      - name: Upload Nuget packages as workflow artifacts
        uses: actions/upload-artifact@v3
        with:
          name: Nuget packages
          path: |
            src/out/*
      - name: Publish Nuget packages to Nuget registry
        working-directory: src
        run: dotnet nuget push "out/*" -k ${{secrets.NUGET_AUTH_TOKEN}}
      - name: Upload Nuget packages as release artifacts
        uses: actions/github-script@v6
        with:
          github-token: ${{secrets.GITHUB_TOKEN}}
          script: |
            console.log('environment', process.versions);
            const fs = require('fs').promises;
            const { repo: { owner, repo }, sha } = context;

            for (let file of await fs.readdir('src/out')) {
              console.log('uploading', file);

              await github.rest.repos.uploadReleaseAsset({
                owner,
                repo,
                release_id: ${{ github.event.release.id }},
                name: file,
                data: await fs.readFile(`src/out/${file}`)
              });
            }


================================================
FILE: .github/workflows/test.yml
================================================
name: Run code tests

on:
  pull_request:
    paths:
      - src/**
      - .github/workflows/**
  # Upload code coverage results when PRs are merged
  push:
    branches:
      - master
      - develop
    paths:
      - src/**
      - .github/workflows/**

env:
  DOTNET_NOLOGO: true
  DOTNET_CLI_TELEMETRY_OPTOUT: true

jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]
        graphqlversion:
          - 8.0.0
    name: ${{ matrix.os }}/${{ matrix.graphqlversion }}
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout source
        uses: actions/checkout@v4
      - name: Setup .NET SDKs
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: |
            3.1.x
            5.0.x
            6.0.x
            7.0.x
            8.0.x
          source-url: https://nuget.pkg.github.com/graphql-dotnet/index.json
        env:
          NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
      - name: Install dependencies with GraphQL version ${{ matrix.graphqlversion }}
        working-directory: src
        run: dotnet restore -p:GraphQLTestVersion=${{ matrix.graphqlversion }}
      - name: Build solution [Release]
        if: ${{ startsWith(matrix.os, 'ubuntu') }}
        working-directory: src
        run: dotnet build --no-restore -c Release -p:GraphQLTestVersion=${{ matrix.graphqlversion }}
      - name: Build solution [Debug]
        working-directory: src
        run: dotnet build --no-restore -c Debug -p:GraphQLTestVersion=${{ matrix.graphqlversion }}
      - name: Test solution [Debug] with code coverage
        if: ${{ startsWith(matrix.os, 'ubuntu') }}
        working-directory: src
        run: >
          dotnet test
          --no-restore
          --no-build
          --collect "XPlat Code Coverage"
          --results-directory .coverage
          --
          DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover
          DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Exclude=[BasicSample]*,[Harness]*
      - name: Test solution [Debug] without code coverage
        if: ${{ startsWith(matrix.os, 'windows') }}
        working-directory: src
        run: dotnet test --no-restore --no-build
      - name: Upload coverage to codecov
        if: ${{ startsWith(matrix.os, 'ubuntu') }}
        uses: codecov/codecov-action@v3
        with:
          files: 'src/.coverage/**/coverage.opencover.xml'

  buildcheck:
    needs:
      - test
    runs-on: ubuntu-latest
    if: always()
    steps:
      - name: Pass build check
        if: ${{ needs.test.result == 'success' }}
        run: exit 0
      - name: Fail build check
        if: ${{ needs.test.result != 'success' }}
        run: exit 1


================================================
FILE: .github/workflows/wipcheck.yml
================================================
name: Check if PR title contains [WIP]

on:
  pull_request:
    types:
      - opened        # when PR is opened
      - edited        # when PR is edited
      - synchronize   # when code is added
      - reopened      # when a closed PR is reopened

jobs:
  check-title:
    runs-on: ubuntu-latest

    steps:
      - name: Fail build if pull request title contains [WIP]
        env:
          TITLE: ${{ github.event.pull_request.title }}
        if: ${{ contains(github.event.pull_request.title, '[WIP]') }} # This function is case insensitive.
        run: |
          echo Warning! PR title "$TITLE" contains [WIP]. Remove [WIP] from the title when PR is ready.
          exit 1


================================================
FILE: .gitignore
================================================
*.DS_Store

.vs/
.idea/
*.user
*.suo
*.nupkg

[Oo]bj/
[Bb]in/

*.received.txt


================================================
FILE: .vscode/launch.json
================================================
{
  // Use IntelliSense to find out which attributes exist for C# debugging
  // Use hover for the description of the existing attributes
  // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
  "version": "0.2.0",
  "configurations": [
    {
      "name": ".NET Core Launch (web)",
      "type": "coreclr",
      "request": "launch",
      "preLaunchTask": "build-harness",
      "program": "${workspaceFolder}/src/Harness/bin/Debug/netcoreapp3.1/Harness.dll",
      "args": [],
      "cwd": "${workspaceFolder}/src/Harness",
      "stopAtEntry": false,
      "internalConsoleOptions": "openOnSessionStart",
      "launchBrowser": {
        "enabled": true,
        "args": "${auto-detect-url}",
        "windows": {
          "command": "cmd.exe",
          "args": "/C start ${auto-detect-url}"
        },
        "osx": {
          "command": "open",
          "args": "http://localhost:3000/ui/graphiql"
        },
        "linux": {
          "command": "xdg-open"
        }
      },
      "env": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_URLS": "http://localhost:3000"
      },
      "sourceFileMap": {
        "/Views": "${workspaceFolder}/Views"
      }
    },
    {
      "name": ".NET Core Launch (console)",
      "type": "coreclr",
      "request": "launch",
      "preLaunchTask": "build-tests",
      "program": "${workspaceFolder}/src/GraphQL.Authorization.Tests/bin/Debug/netcoreapp3.1/GraphQL.Authorization.Tests.dll",
      "args": [],
      "cwd": "${workspaceFolder}/src/GraphQL.Authorization.Tests",
      "console": "internalConsole",
      "stopAtEntry": false,
      "internalConsoleOptions": "openOnSessionStart"
    },
    {
      "name": ".NET Core Attach",
      "type": "coreclr",
      "request": "attach",
      "processId": "${command:pickProcess}"
    }
  ]
}


================================================
FILE: .vscode/tasks.json
================================================
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build-harness",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build",
                "${workspaceFolder}/src/Harness/Harness.csproj"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "build-tests",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build",
                "${workspaceFolder}/src/GraphQL.Authorization.Tests/GraphQL.Authorization.Tests.csproj"
            ],
            "problemMatcher": "$msCompile"
        }
    ]
}


================================================
FILE: LICENSE.md
================================================
The MIT License (MIT)

Copyright (c) 2017 Joseph T. McBride

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: README.md
================================================
# GraphQL Authorization

[![License](https://img.shields.io/github/license/graphql-dotnet/authorization)](LICENSE.md)
[![codecov](https://codecov.io/gh/graphql-dotnet/authorization/branch/master/graph/badge.svg?token=TODO)](https://codecov.io/gh/graphql-dotnet/authorization)
[![Nuget](https://img.shields.io/nuget/dt/GraphQL.Authorization)](https://www.nuget.org/packages/GraphQL.Authorization)
[![Nuget](https://img.shields.io/nuget/v/GraphQL.Authorization)](https://www.nuget.org/packages/GraphQL.Authorization)
[![GitHub Release Date](https://img.shields.io/github/release-date/graphql-dotnet/authorization?label=released)](https://github.com/graphql-dotnet/authorization/releases)
[![GitHub commits since latest release (by date)](https://img.shields.io/github/commits-since/graphql-dotnet/authorization/latest?label=new+commits)](https://github.com/graphql-dotnet/authorization/commits/master)
![Size](https://img.shields.io/github/repo-size/graphql-dotnet/authorization)

[![GitHub contributors](https://img.shields.io/github/contributors/graphql-dotnet/authorization)](https://github.com/graphql-dotnet/authorization/graphs/contributors)
![Activity](https://img.shields.io/github/commit-activity/w/graphql-dotnet/authorization)
![Activity](https://img.shields.io/github/commit-activity/m/graphql-dotnet/authorization)
![Activity](https://img.shields.io/github/commit-activity/y/graphql-dotnet/authorization)

A toolset for authorizing access to graph types for [GraphQL.NET](https://github.com/graphql-dotnet/graphql-dotnet).

Provides the following packages:

| Package               | Downloads                                                                                                               | NuGet Latest                                                                                                           |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| GraphQL.Authorization | [![Nuget](https://img.shields.io/nuget/dt/GraphQL.Authorization)](https://www.nuget.org/packages/GraphQL.Authorization) | [![Nuget](https://img.shields.io/nuget/v/GraphQL.Authorization)](https://www.nuget.org/packages/GraphQL.Authorization) |

You can get all preview versions from [GitHub Packages](https://github.com/orgs/graphql-dotnet/packages?repo_name=authorization).
Note that GitHub requires authentication to consume the feed. See [here](https://docs.github.com/en/free-pro-team@latest/packages/publishing-and-managing-packages/about-github-packages#authenticating-to-github-packages).

# Usage

- Register the authorization classes in your DI container - call `AddAuthorization` on the provided `IGraphQLBuilder` inside `AddGraphQL` extension method.
- Provide the `ClaimsPrincipal` through `ExecutionOptions.User`.
- Add policies to the `AuthorizationSettings`.
- Apply a policy to a GraphType or Field - both implement `IProvideMetadata`:
  - using `AuthorizeWithPolicy(string policy)` extension method
  - or with `AuthorizeAttribute` attribute if using Schema + Handler syntax.
- The `AuthorizationValidationRule` will run and verify the policies based on the registered policies.
- You can write your own `IAuthorizationRequirement`.

# Limitations

`@skip` and `@include` directives are ignored; all selected fields of the selected operation will
be checked for authentication requirements, including referenced fragments. (Other operations
in the same document will correctly be skipped.)

This authorization framework only supports policy-based authorization. It does not support role-based authorization, or the
`[AllowAnonymous]` attribute/extension, or the `[Authorize]` attribute/extension indicating authorization is required
but without specifying a policy. It also does not integrate with ASP.NET Core's authorization framework.

The [GraphQL.Server](https://www.github.com/graphql-dotnet/server) repository contains an authorization rule which has the above
missing features, intended for use with ASP.NET Core. It may also be tailored with custom authentication code if desired, rather than
relying on ASP.NET Core's authentication framework.

# Examples

1. Fully functional basic [Console sample](src/BasicSample/Program.cs).

2. Fully functional [ASP.NET Core sample](src/Harness/Program.cs).

3. GraphType first syntax - use `AuthorizeWithPolicy` extension method on `IGraphType` or `IFieldType`.

```csharp
public class MyType : ObjectGraphType
{
    public MyType()
    {
        this.AuthorizeWithPolicy("AdminPolicy");
        Field<StringGraphType>("name").AuthorizeWithPolicy("SomePolicy");
    }
}
```

4. Schema first syntax - use `AuthorizeAttribute` attribute on type, method or property.

```csharp
[Authorize("MyPolicy")]
public class MutationType
{
    [Authorize("AnotherPolicy")]
    public async Task<string> CreateSomething(MyInput input)
    {
        return await SomeMethodAsync(input);
    }

    [Authorize("SuperPolicy")]
    public string SomeProperty => Guid.NewGuid().ToString();
}
```

# Known Issues

- It is currently not possible to add a policy to Input objects using Schema first approach.


================================================
FILE: codeql/GraphQL.Authorization.CodeQL.sln
================================================

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31919.166
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphQL.Authorization", "..\src\GraphQL.Authorization\GraphQL.Authorization.csproj", "{C9953353-2407-4A2D-8E2A-A5F62DEED89C}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{C9953353-2407-4A2D-8E2A-A5F62DEED89C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{C9953353-2407-4A2D-8E2A-A5F62DEED89C}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{C9953353-2407-4A2D-8E2A-A5F62DEED89C}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{C9953353-2407-4A2D-8E2A-A5F62DEED89C}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {A0696AC3-8123-4422-B489-C58B78E24B27}
	EndGlobalSection
EndGlobal


================================================
FILE: src/BasicSample/BasicSample.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="..\Harness\GraphQL.cs" Link="GraphQL.cs" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\GraphQL.Authorization\GraphQL.Authorization.csproj" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="GraphQL.MicrosoftDI" Version="8.*" />
    <PackageReference Include="GraphQL.SystemTextJson" Version="8.*" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.*" />
  </ItemGroup>

</Project>


================================================
FILE: src/BasicSample/Program.cs
================================================
using System.Security.Claims;
using GraphQL;
using GraphQL.SystemTextJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection().AddGraphQL(builder => builder
    .AddAuthorization(settings => settings.AddPolicy("AdminPolicy", p => p.RequireClaim("role", "Admin"))));

using var serviceProvider = services.BuildServiceProvider();

const string definitions = """
    type User {
        id: ID
        name: String
    }

    type Query {
        viewer: User
        users: [User]
    }
    """;
var schema = Schema.For(definitions, builder => builder.Types.Include<Query>());

// Claims principal must look something like this to allow access.
// GraphQLUserContext.User alternates below for demonstration purposes.
int counter = 0;
var authorizedUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("role", "Admin") }));
var nonAuthorizedUser = new ClaimsPrincipal(new ClaimsIdentity());

while (true)
{
    string json = await schema.ExecuteAsync(options =>
    {
        options.Query = "{ viewer { id name } }";
        options.Root = new Query();
        options.ValidationRules = DocumentValidator.CoreRules.Concat(serviceProvider.GetServices<IValidationRule>());
        options.RequestServices = serviceProvider;
        options.User = counter++ % 2 == 0 ? authorizedUser : nonAuthorizedUser;
    }).ConfigureAwait(false);

    Console.WriteLine(json);
    Console.WriteLine();
    Console.WriteLine("Press ENTER to continue");
    Console.ReadLine();
}


================================================
FILE: src/Directory.Build.props
================================================
<Project>

  <PropertyGroup>
    <VersionPrefix>8.0.0-preview</VersionPrefix>
    <NextVersion>9.0.0</NextVersion>
    <LangVersion>latest</LangVersion>
    <Authors>Joe McBride</Authors>
    <PackageLicenseExpression>MIT</PackageLicenseExpression>
    <PackageIcon>logo.64x64.png</PackageIcon>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
    <RepositoryType>git</RepositoryType>
    <PublishRepositoryUrl>true</PublishRepositoryUrl>
    <Deterministic>true</Deterministic>
    <!-- https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables -->
    <!-- https://github.com/clairernovotny/DeterministicBuilds -->
    <ContinuousIntegrationBuild Condition="'$(GITHUB_ACTIONS)' == 'true'">True</ContinuousIntegrationBuild>
    <DebugType>embedded</DebugType>
    <ImplicitUsings>enable</ImplicitUsings>
    <EmbedUntrackedSources>true</EmbedUntrackedSources>
    <EnableNETAnalyzers>true</EnableNETAnalyzers>
    <IsPackable>true</IsPackable>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <CheckEolTargetFramework>false</CheckEolTargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Roslynator.Analyzers" Version="4.4.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Roslynator.Formatting.Analyzers" Version="4.4.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

</Project>


================================================
FILE: src/Directory.Build.targets
================================================
<Project>

  <PropertyGroup Condition="'$(IsPackable)' == 'true'">
    <PackageReadmeFile>README.md</PackageReadmeFile>
    <PackageReleaseNotes>See https://github.com/graphql-dotnet/authorization/releases</PackageReleaseNotes>
  </PropertyGroup>

  <PropertyGroup Condition="'$(IsPackable)' != 'true'">
    <NoWarn>$(NoWarn);1591</NoWarn>
    <WarningsNotAsErrors>$(WarningsNotAsErrors);IDE0053</WarningsNotAsErrors>
  </PropertyGroup>

  <ItemGroup Condition="'$(IsPackable)' == 'true'">
    <None Include="..\..\assets\logo.64x64.png" Pack="true" PackagePath="\" Visible="false" />
    <None Include="..\..\README.md" Pack="true" PackagePath="\" Visible="false" />
    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
  </ItemGroup>

  <!--Workaround for https://github.com/NuGet/Home/issues/5556 and https://github.com/NuGet/Home/issues/5525-->
  <Target Name="UseExplicitPackageVersions" BeforeTargets="GenerateNuspec">
    <ItemGroup>
      <_ProjectReferenceWithExplicitPackageVersion Include="@(ProjectReference->'%(FullPath)')" Condition="'%(ProjectReference.PackageVersion)' != ''" />
      <_ProjectReferenceWithExactPackageVersion Include="@(ProjectReference->'%(FullPath)')" Condition="'%(ProjectReference.ExactVersion)' == 'true'" />
      <_ProjectReferenceWithReassignedVersion Include="@(_ProjectReferencesWithVersions)" Condition="'%(Identity)' != '' And '@(_ProjectReferenceWithExplicitPackageVersion)' == '@(_ProjectReferencesWithVersions)'">
        <ProjectVersion>@(_ProjectReferenceWithExplicitPackageVersion->'%(PackageVersion)')</ProjectVersion>
      </_ProjectReferenceWithReassignedVersion>
      <_ProjectReferenceWithReassignedVersion Include="@(_ProjectReferencesWithVersions)" Condition="'%(Identity)' != '' And '@(_ProjectReferenceWithExactPackageVersion)' == '@(_ProjectReferencesWithVersions)'">
        <ProjectVersion>[@(_ProjectReferencesWithVersions->'%(ProjectVersion)')]</ProjectVersion>
      </_ProjectReferenceWithReassignedVersion>
      <_ProjectReferencesWithVersions Remove="@(_ProjectReferenceWithReassignedVersion)" />
      <_ProjectReferencesWithVersions Include="@(_ProjectReferenceWithReassignedVersion)" />
    </ItemGroup>
  </Target>

</Project>


================================================
FILE: src/GraphQL.Authorization/AuthorizationContext.cs
================================================
using System.Security.Claims;

namespace GraphQL.Authorization;

/// <summary>
/// Provides context information for <see cref="IAuthorizationRequirement"/>.
/// </summary>
public class AuthorizationContext
{
    private List<string>? _errors;

    /// <summary>
    /// Current user.
    /// </summary>
    public ClaimsPrincipal? User { get; set; }

    /// <summary>
    /// Arbitrary user defined context represented as dictionary.
    /// </summary>
    public IDictionary<string, object?>? UserContext { get; set; }

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

    /// <summary>
    /// Returns a set of authorization errors.
    /// </summary>
    public IEnumerable<string> Errors => _errors ?? Enumerable.Empty<string>();

    /// <summary>
    /// Returns whether there are any errors.
    /// </summary>
    public bool HasErrors => _errors?.Count > 0;

    /// <summary>
    /// Reports an error during evaluation of policy requirement.
    /// </summary>
    /// <param name="error">Error message.</param>
    public void ReportError(string error) => (_errors ??= new()).Add(error);
}


================================================
FILE: src/GraphQL.Authorization/AuthorizationEvaluator.cs
================================================
using System.Security.Claims;

namespace GraphQL.Authorization;

/// <summary>
/// Default implementation of <see cref="IAuthorizationEvaluator"/>.
/// </summary>
public class AuthorizationEvaluator : IAuthorizationEvaluator
{
    private readonly AuthorizationSettings _settings;

    /// <summary>
    /// Creates an instance of <see cref="AuthorizationEvaluator"/> with the
    /// specified authorization settings.
    /// </summary>
    public AuthorizationEvaluator(AuthorizationSettings settings)
    {
        _settings = settings;
    }

    /// <inheritdoc />
    public async Task<AuthorizationResult> Evaluate(
        ClaimsPrincipal? principal,
        IDictionary<string, object?>? userContext,
        Inputs? variables,
        IEnumerable<string>? requiredPolicies)
    {
        if (requiredPolicies == null)
            return AuthorizationResult.Success();

        var context = new AuthorizationContext
        {
            User = principal ?? new ClaimsPrincipal(new ClaimsIdentity()),
            UserContext = userContext,
            Variables = variables
        };

        var tasks = new List<Task>();

        foreach (string requiredPolicy in requiredPolicies)
        {
            var authorizationPolicy = _settings.GetPolicy(requiredPolicy);
            if (authorizationPolicy == null)
            {
                context.ReportError($"Required policy '{requiredPolicy}' is not present.");
            }
            else
            {
                foreach (var r in authorizationPolicy.Requirements)
                {
                    var task = r.Authorize(context);
                    tasks.Add(task);
                }
            }
        }

        await Task.WhenAll(tasks).ConfigureAwait(false);

        return context.HasErrors
            ? AuthorizationResult.Fail(context.Errors)
            : AuthorizationResult.Success();
    }
}


================================================
FILE: src/GraphQL.Authorization/AuthorizationPolicy.cs
================================================
namespace GraphQL.Authorization;

/// <summary>
/// Default implementation for <see cref="IAuthorizationPolicy"/>.
/// </summary>
public class AuthorizationPolicy : IAuthorizationPolicy
{
    private readonly List<IAuthorizationRequirement> _requirements = new();

    /// <summary>
    /// Creates a policy with a set of specified requirements.
    /// </summary>
    /// <param name="requirements">Specified requirements.</param>
    public AuthorizationPolicy(IEnumerable<IAuthorizationRequirement> requirements)
    {
        if (requirements != null)
        {
            _requirements.AddRange(requirements);
            _requirements.ForEach(req =>
            {
                if (req == null)
                    throw new ArgumentNullException(nameof(requirements), $"One of the ({_requirements.Count}) requirements is null");
            });
        }
    }

    /// <inheritdoc />
    public IEnumerable<IAuthorizationRequirement> Requirements => _requirements;
}


================================================
FILE: src/GraphQL.Authorization/AuthorizationPolicyBuilder.cs
================================================
namespace GraphQL.Authorization;

/// <summary>
/// Configures and then builds authorization policy from various authorization requirements.
/// Provides fluent API.
/// </summary>
public class AuthorizationPolicyBuilder
{
    private readonly List<IAuthorizationRequirement> _requirements = new();

    /// <summary>
    /// Build authorization policy.
    /// </summary>
    /// <returns>Created policy.</returns>
    public AuthorizationPolicy Build() => new(_requirements);

    /// <summary>
    /// Adds <see cref="ClaimAuthorizationRequirement"/> with the specified claim type.
    /// </summary>
    /// <param name="claimType">Type of the claim.</param>
    /// <returns>Reference to the same builder.</returns>
    public AuthorizationPolicyBuilder RequireClaim(string claimType)
    {
        _requirements.Add(new ClaimAuthorizationRequirement(claimType));
        return this;
    }

    /// <summary>
    /// Adds <see cref="ClaimAuthorizationRequirement"/> with the specified claim type and allowed values.
    /// </summary>
    /// <param name="claimType">Type of the claim.</param>
    /// <param name="allowedValues">Allowed values for this claim.</param>
    /// <returns>Reference to the same builder.</returns>
    public AuthorizationPolicyBuilder RequireClaim(string claimType, params string[] allowedValues)
    {
        _requirements.Add(new ClaimAuthorizationRequirement(claimType, allowedValues));
        return this;
    }

    /// <summary>
    /// Adds <see cref="ClaimAuthorizationRequirement"/> with the specified claim type, allowed values and display values.
    /// </summary>
    /// <param name="claimType">Type of the claim.</param>
    /// <param name="allowedValues">Allowed values for this claim.</param>
    /// <param name="displayValues">
    /// Display values for this claim. If no allowed claims are found, display values will be used to generate
    /// an error message for <see cref="AuthorizationContext.Errors"/>.
    /// </param>
    /// <returns>Reference to the same builder.</returns>
    public AuthorizationPolicyBuilder RequireClaim(string claimType, IEnumerable<string>? allowedValues, IEnumerable<string>? displayValues)
    {
        _requirements.Add(new ClaimAuthorizationRequirement(claimType, allowedValues, displayValues));
        return this;
    }

    /// <summary>
    /// Adds <see cref="AuthenticatedUserRequirement"/>.
    /// </summary>
    /// <returns>Reference to the same builder.</returns>
    public AuthorizationPolicyBuilder RequireAuthenticatedUser()
    {
        _requirements.Add(AuthenticatedUserRequirement.Instance);
        return this;
    }

    /// <summary>
    /// Adds specified authorization requirement.
    /// </summary>
    /// <param name="requirement">Authorization requirement.</param>
    /// <returns>Reference to the same builder.</returns>
    public AuthorizationPolicyBuilder AddRequirement(IAuthorizationRequirement requirement)
    {
        _requirements.Add(requirement ?? throw new ArgumentNullException(nameof(requirement)));
        return this;
    }
}


================================================
FILE: src/GraphQL.Authorization/AuthorizationResult.cs
================================================
namespace GraphQL.Authorization;

/// <summary>
/// Represents the result of an authorization evaluation.
/// </summary>
public class AuthorizationResult
{
    // allocation optimization for green path
    private static readonly AuthorizationResult _success = new() { Succeeded = true };

    /// <summary>
    /// Is the authorization result successful?
    /// </summary>
    public bool Succeeded { get; private set; }

    /// <summary>
    /// Returns a set of authorization errors if the authorization result is unsuccessful.
    /// </summary>
    public IEnumerable<string>? Errors { get; private set; }

    /// <summary>
    /// Creates successful authorization result.
    /// </summary>
    /// <returns>Instance of <see cref="AuthorizationResult"/>.</returns>
    public static AuthorizationResult Success() => _success;

    /// <summary>
    /// Creates unsuccessful authorization result
    /// </summary>
    /// <param name="errors">A set of authorization errors.</param>
    /// <returns>Instance of <see cref="AuthorizationResult"/>.</returns>
    public static AuthorizationResult Fail(IEnumerable<string> errors) => new() { Errors = errors };
}


================================================
FILE: src/GraphQL.Authorization/AuthorizationSettings.cs
================================================
namespace GraphQL.Authorization;

/// <summary>
/// Authorization settings are represented by a set of named policies
/// where each policy has a set of authorization requirements.
/// </summary>
public class AuthorizationSettings
{
    private readonly IDictionary<string, IAuthorizationPolicy> _policies = new Dictionary<string, IAuthorizationPolicy>(StringComparer.OrdinalIgnoreCase);

    /// <summary>
    /// Returns all policies.
    /// </summary>
    public IEnumerable<IAuthorizationPolicy> Policies => _policies.Values;

    /// <summary>
    /// Returns policies with the specified names.
    /// </summary>
    /// <param name="policies">A set of policies names.</param>
    /// <returns>Policies with matched names.</returns>
    public IEnumerable<IAuthorizationPolicy> GetPolicies(IEnumerable<string> policies)
    {
        List<IAuthorizationPolicy>? found = null;

        if (policies != null)
        {
            foreach (string name in policies)
            {
                var policy = GetPolicy(name);
                if (policy != null)
                    (found ??= new()).Add(policy);
            }
        }

        return found ?? Enumerable.Empty<IAuthorizationPolicy>();
    }

    /// <summary>
    /// Returns one policy with the specified name.
    /// </summary>
    /// <param name="name">Name of the required policy.</param>
    /// <returns>Required policy if exists, otherwise <see langword="null"/>.</returns>
    public IAuthorizationPolicy? GetPolicy(string name) => _policies.TryGetValue(name, out var policy) ? policy : null;

    /// <summary>
    /// Adds a policy with the specified name. If a policy with that name already exists then it will be replaced.
    /// </summary>
    /// <param name="name">Policy name.</param>
    /// <param name="policy">Policy to add.</param>
    public void AddPolicy(string name, IAuthorizationPolicy policy) => _policies[name] = policy;

    /// <summary>
    /// Adds a policy built from <see cref="AuthorizationPolicyBuilder"/> with the specified name.
    /// </summary>
    /// <param name="name">Policy name.</param>
    /// <param name="configure">Delegate to configure provided policy builder.</param>
    public void AddPolicy(string name, Action<AuthorizationPolicyBuilder> configure)
    {
        if (configure == null)
            throw new ArgumentNullException(nameof(configure));

        var builder = new AuthorizationPolicyBuilder();
        configure(builder);

        _policies[name] = builder.Build();
    }
}


================================================
FILE: src/GraphQL.Authorization/AuthorizationValidationRule.cs
================================================
using GraphQL.Types;
using GraphQL.Validation;
using GraphQLParser.AST;

namespace GraphQL.Authorization;

/// <summary>
/// GraphQL authorization validation rule which evaluates configured
/// (via policies) requirements on schema elements: types, fields, etc.
/// </summary>
public class AuthorizationValidationRule : ValidationRuleBase
{
    private readonly IAuthorizationEvaluator _evaluator;

    /// <summary>
    /// Creates an instance of <see cref="AuthorizationValidationRule"/> with
    /// the specified authorization evaluator.
    /// </summary>
    public AuthorizationValidationRule(IAuthorizationEvaluator evaluator)
    {
        _evaluator = evaluator;
    }

    /// <inheritdoc />
    public override async ValueTask<INodeVisitor?> GetPreNodeVisitorAsync(ValidationContext context)
    {
        var visitor = new Visitor(_evaluator);

        await visitor.AuthorizeAsync(null, context.Schema, context).ConfigureAwait(false);

        // this could leak info about hidden fields or types in error messages
        // it would be better to implement a filter on the Schema so it
        // acts as if they just don't exist vs. an auth denied error
        // - filtering the Schema is not currently supported
        // TODO: apply ISchemaFilter - context.Schema.Filter.AllowXXX
        return visitor;
    }

    private class Visitor : INodeVisitor
    {
        private readonly IAuthorizationEvaluator _evaluator;
        private bool _validate;

        public Visitor(IAuthorizationEvaluator evaluator)
        {
            _evaluator = evaluator;
        }

        public async ValueTask EnterAsync(ASTNode node, ValidationContext context)
        {
            if ((node is GraphQLOperationDefinition astType && astType == context.Operation) ||
                (node is GraphQLFragmentDefinition fragment && (context.GetRecursivelyReferencedFragments(context.Operation)?.Contains(fragment) ?? false)))
            {
                var type = context.TypeInfo.GetLastType();
                await AuthorizeAsync(node, type, context).ConfigureAwait(false);
                _validate = true;
            }

            if (!_validate)
                return;

            if (node is GraphQLObjectField objectFieldAst &&
                context.TypeInfo.GetArgument()?.ResolvedType?.GetNamedType() is IComplexGraphType argumentType)
            {
                var fieldType = argumentType.GetField(objectFieldAst.Name);
                await AuthorizeAsync(objectFieldAst, fieldType, context).ConfigureAwait(false);
            }

            if (node is GraphQLField fieldAst)
            {
                var fieldDef = context.TypeInfo.GetFieldDef();

                if (fieldDef == null)
                    return;

                // check target field
                await AuthorizeAsync(fieldAst, fieldDef, context).ConfigureAwait(false);
                // check returned graph type
                await AuthorizeAsync(fieldAst, fieldDef.ResolvedType?.GetNamedType(), context).ConfigureAwait(false);
            }

            if (node is GraphQLVariable variableRef)
            {
                if (context.TypeInfo.GetArgument()?.ResolvedType?.GetNamedType() is not IComplexGraphType variableType)
                    return;

                await AuthorizeAsync(variableRef, variableType, context).ConfigureAwait(false);

                // Check each supplied field in the variable that exists in the variable type.
                // 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.Variables != null &&
                    context.Variables.TryGetValue(variableRef.Name.StringValue, out object? input) && //ISSUE:allocation
                    input is Dictionary<string, object> fieldsValues)
                {
                    foreach (var field in variableType.Fields)
                    {
                        if (fieldsValues.ContainsKey(field.Name))
                        {
                            await AuthorizeAsync(variableRef, field, context).ConfigureAwait(false);
                        }
                    }
                }
            }
        }

        public ValueTask LeaveAsync(ASTNode node, ValidationContext context)
        {
            if (node is GraphQLOperationDefinition || node is GraphQLFragmentDefinition)
                _validate = false;

            return default;
        }

        public async ValueTask AuthorizeAsync(ASTNode? node, IMetadataReader? provider, ValidationContext context)
        {
            if (provider == null || !provider.IsAuthorizationRequired())
                return;

            var result = await _evaluator.Evaluate(context.User, context.UserContext, context.Variables, provider.GetPolicies()).ConfigureAwait(false);

            if (result.Succeeded)
                return;

            string errors = string.Join("\n", result.Errors);

            context.ReportError(new ValidationError(
                context.Document.Source,
                "authorization",
                $"You are not authorized to run this {context.Operation.Operation.ToString().ToLower()}.\n{errors}",
                node == null ? Array.Empty<ASTNode>() : new ASTNode[] { node }));
        }
    }
}


================================================
FILE: src/GraphQL.Authorization/Extensions/AuthorizationGraphQLBuilderExtensions.cs
================================================
using GraphQL.Authorization;
using GraphQL.DI;

namespace GraphQL;

/// <summary>
/// Authorization extension methods for <see cref="IGraphQLBuilder"/>.
/// </summary>
public static class AuthorizationGraphQLBuilderExtensions
{
    /// <summary>
    /// Registers <see cref="AuthorizationEvaluator"/> and <see cref="AuthorizationValidationRule"/> within the
    /// dependency injection framework and configures the validation rule to be added to the list of validation rules
    /// within <see cref="ExecutionOptions.ValidationRules"/> and <see cref="ExecutionOptions.CachedDocumentValidationRules"/>
    /// upon document execution. Configures authorization settings with the specified configuration delegate.
    /// </summary>
    public static IGraphQLBuilder AddAuthorization(this IGraphQLBuilder builder, Action<AuthorizationSettings, IServiceProvider> configure)
    {
        builder.Services.TryRegister<IAuthorizationEvaluator, AuthorizationEvaluator>(ServiceLifetime.Singleton);
        builder.AddValidationRule<AuthorizationValidationRule>(true);
        builder.Services.Configure(configure);
        return builder;
    }

    /// <inheritdoc cref="AddAuthorization(IGraphQLBuilder, Action{AuthorizationSettings, IServiceProvider})"/>
    public static IGraphQLBuilder AddAuthorization(this IGraphQLBuilder builder, Action<AuthorizationSettings> configure)
    {
        builder.Services.TryRegister<IAuthorizationEvaluator, AuthorizationEvaluator>(ServiceLifetime.Singleton);
        builder.AddValidationRule<AuthorizationValidationRule>(true);
        builder.Services.Configure(configure);
        return builder;
    }
}


================================================
FILE: src/GraphQL.Authorization/GraphQL.Authorization.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <Description>A toolset for authorizing access to graph types for GraphQL.NET</Description>
    <PackageTags>GraphQL;json;api</PackageTags>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="GraphQL" Version="8.0.0" />
  </ItemGroup>

</Project>


================================================
FILE: src/GraphQL.Authorization/IAuthorizationEvaluator.cs
================================================
using System.Security.Claims;

namespace GraphQL.Authorization;

/// <summary>
/// Interface to evaluate the authorization result.
/// </summary>
public interface IAuthorizationEvaluator
{
    /// <summary>
    /// Evaluates authorization result.
    /// </summary>
    /// <param name="principal">Represents the current user.</param>
    /// <param name="userContext">Arbitrary user defined context represented as dictionary.</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,
        Inputs? variables,
        IEnumerable<string>? requiredPolicies);
}


================================================
FILE: src/GraphQL.Authorization/IAuthorizationPolicy.cs
================================================
namespace GraphQL.Authorization;

/// <summary>
/// Policy is a named set of <see cref="IAuthorizationRequirement"/>.
/// </summary>
public interface IAuthorizationPolicy
{
    /// <summary>
    /// Returns all requirements of this policy.
    /// </summary>
    IEnumerable<IAuthorizationRequirement> Requirements { get; }
}


================================================
FILE: src/GraphQL.Authorization/Requirements/AuthenticatedUserRequirement.cs
================================================
namespace GraphQL.Authorization;

/// <summary>
/// Implements an <see cref="IAuthorizationRequirement"/> which requires that
/// current user from <see cref="AuthorizationContext.User"/> must be authenticated.
/// </summary>
public class AuthenticatedUserRequirement : IAuthorizationRequirement
{
    internal static readonly AuthenticatedUserRequirement Instance = new();

    /// <inheritdoc />
    public Task Authorize(AuthorizationContext context)
    {
        if (context.User == null || !context.User.Identities.Any(x => x.IsAuthenticated))
        {
            context.ReportError("An authenticated user is required.");
        }

        return Task.CompletedTask;
    }
}


================================================
FILE: src/GraphQL.Authorization/Requirements/ClaimAuthorizationRequirement.cs
================================================
namespace GraphQL.Authorization;

/// <summary>
/// Implements an <see cref="IAuthorizationRequirement"/> which requires an instance of the specified
/// claim type, and, if allowed values are specified, the claim value must be any of the allowed values.
/// </summary>
public class ClaimAuthorizationRequirement : IAuthorizationRequirement
{
    /// <summary>
    /// Creates a new instance of <see cref="ClaimAuthorizationRequirement"/> with
    /// the specified claim type.
    /// </summary>
    public ClaimAuthorizationRequirement(string claimType)
        : this(claimType, (IEnumerable<string>?)null, null)
    {
    }

    /// <summary>
    /// Creates a new instance of <see cref="ClaimAuthorizationRequirement"/> with
    /// the specified claim type and optional list of claim values, which, if present,
    /// the claim must match.
    /// </summary>
    public ClaimAuthorizationRequirement(string claimType, IEnumerable<string> allowedValues)
        : this(claimType, allowedValues, null)
    {
    }

    /// <summary>
    /// Creates a new instance of <see cref="ClaimAuthorizationRequirement"/> with
    /// the specified claim type and optional list of claim values, which, if present,
    /// the claim must match.
    /// </summary>
    public ClaimAuthorizationRequirement(string claimType, params string[] allowedValues)
        : this(claimType, allowedValues, null)
    {
    }

    /// <summary>
    /// Creates a new instance of <see cref="ClaimAuthorizationRequirement"/> with
    /// the specified claim type and optional list of claim values, which, if present,
    /// the claim must match. Additional <paramref name="displayValues"/> argument
    /// specifies the set of displayed claim values that will be used to generate an
    /// error message if the requirement is not met.
    /// </summary>
    public ClaimAuthorizationRequirement(string claimType, IEnumerable<string>? allowedValues, IEnumerable<string>? displayValues)
    {
        ClaimType = claimType ?? throw new ArgumentNullException(nameof(claimType));
        AllowedValues = allowedValues ?? Enumerable.Empty<string>();
        DisplayValues = displayValues;
    }

    /// <summary>
    /// Claim type that claims principal from <see cref="AuthorizationContext"/> should have.
    /// </summary>
    public string ClaimType { get; }

    /// <summary>
    /// List of claim values, which, if present, the claim must match.
    /// </summary>
    public IEnumerable<string> AllowedValues { get; }

    /// <summary>
    /// Specifies the set of displayed claim values that will be used
    /// to generate an error message if the requirement is not met.
    /// If null then values from <see cref="AllowedValues"/> are used.
    /// </summary>
    public IEnumerable<string>? DisplayValues { get; }

    /// <inheritdoc />
    public Task Authorize(AuthorizationContext context)
    {
        bool found = false;

        if (context.User != null)
        {
            if (AllowedValues == null || !AllowedValues.Any())
            {
                found = context.User.Claims.Any(
                    claim => string.Equals(claim.Type, ClaimType, StringComparison.OrdinalIgnoreCase));
            }
            else
            {
                found = context.User.Claims.Any(
                    claim => string.Equals(claim.Type, ClaimType, StringComparison.OrdinalIgnoreCase)
                         && AllowedValues.Contains(claim.Value, StringComparer.Ordinal));
            }
        }

        if (!found)
        {
            if (AllowedValues != null && AllowedValues.Any())
            {
                string values = string.Join(", ", DisplayValues ?? AllowedValues);
                context.ReportError($"Required claim '{ClaimType}' with any value of '{values}' is not present.");
            }
            else
            {
                context.ReportError($"Required claim '{ClaimType}' is not present.");
            }
        }

        return Task.CompletedTask;
    }
}


================================================
FILE: src/GraphQL.Authorization/Requirements/IAuthorizationRequirement.cs
================================================
namespace GraphQL.Authorization;

/// <summary>
/// Represents an authorization requirement.
/// One of the requirements in <see cref="IAuthorizationPolicy"/>.
/// </summary>
public interface IAuthorizationRequirement
{
    /// <summary>
    /// Execute requirement. If the requirement is not met then this method
    /// should call <see cref="AuthorizationContext.ReportError(string)"/>.
    /// </summary>
    Task Authorize(AuthorizationContext context);
}


================================================
FILE: src/GraphQL.Authorization.ApiTests/ApiApprovalTests.cs
================================================
using PublicApiGenerator;

namespace GraphQL.Authorization.ApiTests;

/// <summary>
/// See more info about API approval tests here <see href="https://github.com/JakeGinnivan/ApiApprover"/>.
/// </summary>
public class ApiApprovalTests
{
    [Theory]
    [InlineData(typeof(IAuthorizationRequirement))]
    public void public_api_should_not_change_unintentionally(Type type)
    {
        string publicApi = type.Assembly.GeneratePublicApi(new ApiGeneratorOptions
        {
            IncludeAssemblyAttributes = false,
        });

        // See: https://shouldly.readthedocs.io/en/latest/assertions/shouldMatchApproved.html
        // Note: If the AssemblyName.approved.txt file doesn't match the latest publicApi value,
        // this call will try to launch a diff tool to help you out but that can fail on
        // your machine if a diff tool isn't configured/setup.
        publicApi.ShouldMatchApproved(options => options.NoDiff().WithFilenameGenerator((_, _, fileType, fileExtension) => $"{type.Assembly.GetName().Name}.{fileType}.{fileExtension}"));
    }
}


================================================
FILE: src/GraphQL.Authorization.ApiTests/GraphQL.Authorization.ApiTests.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="../Tests.props" />

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="PublicApiGenerator" Version="11.0.0" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\GraphQL.Authorization\GraphQL.Authorization.csproj" />
  </ItemGroup>

</Project>


================================================
FILE: src/GraphQL.Authorization.ApiTests/GraphQL.Authorization.approved.txt
================================================
namespace GraphQL.Authorization
{
    public class AuthenticatedUserRequirement : GraphQL.Authorization.IAuthorizationRequirement
    {
        public AuthenticatedUserRequirement() { }
        public System.Threading.Tasks.Task Authorize(GraphQL.Authorization.AuthorizationContext context) { }
    }
    public class AuthorizationContext
    {
        public AuthorizationContext() { }
        public System.Collections.Generic.IEnumerable<string> Errors { get; }
        public bool HasErrors { get; }
        public System.Security.Claims.ClaimsPrincipal? User { get; set; }
        public System.Collections.Generic.IDictionary<string, object?>? UserContext { get; set; }
        public GraphQL.Inputs? Variables { get; set; }
        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, GraphQL.Inputs? variables, System.Collections.Generic.IEnumerable<string>? requiredPolicies) { }
    }
    public class AuthorizationPolicy : GraphQL.Authorization.IAuthorizationPolicy
    {
        public AuthorizationPolicy(System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationRequirement> requirements) { }
        public System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationRequirement> Requirements { get; }
    }
    public class AuthorizationPolicyBuilder
    {
        public AuthorizationPolicyBuilder() { }
        public GraphQL.Authorization.AuthorizationPolicyBuilder AddRequirement(GraphQL.Authorization.IAuthorizationRequirement requirement) { }
        public GraphQL.Authorization.AuthorizationPolicy Build() { }
        public GraphQL.Authorization.AuthorizationPolicyBuilder RequireAuthenticatedUser() { }
        public GraphQL.Authorization.AuthorizationPolicyBuilder RequireClaim(string claimType) { }
        public GraphQL.Authorization.AuthorizationPolicyBuilder RequireClaim(string claimType, params string[] allowedValues) { }
        public GraphQL.Authorization.AuthorizationPolicyBuilder RequireClaim(string claimType, System.Collections.Generic.IEnumerable<string>? allowedValues, System.Collections.Generic.IEnumerable<string>? displayValues) { }
    }
    public class AuthorizationResult
    {
        public AuthorizationResult() { }
        public System.Collections.Generic.IEnumerable<string>? Errors { get; }
        public bool Succeeded { get; }
        public static GraphQL.Authorization.AuthorizationResult Fail(System.Collections.Generic.IEnumerable<string> errors) { }
        public static GraphQL.Authorization.AuthorizationResult Success() { }
    }
    public class AuthorizationSettings
    {
        public AuthorizationSettings() { }
        public System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationPolicy> Policies { get; }
        public void AddPolicy(string name, GraphQL.Authorization.IAuthorizationPolicy policy) { }
        public void AddPolicy(string name, System.Action<GraphQL.Authorization.AuthorizationPolicyBuilder> configure) { }
        public System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationPolicy> GetPolicies(System.Collections.Generic.IEnumerable<string> policies) { }
        public GraphQL.Authorization.IAuthorizationPolicy? GetPolicy(string name) { }
    }
    public class AuthorizationValidationRule : GraphQL.Validation.ValidationRuleBase
    {
        public AuthorizationValidationRule(GraphQL.Authorization.IAuthorizationEvaluator evaluator) { }
        public override System.Threading.Tasks.ValueTask<GraphQL.Validation.INodeVisitor?> GetPreNodeVisitorAsync(GraphQL.Validation.ValidationContext context) { }
    }
    public class ClaimAuthorizationRequirement : GraphQL.Authorization.IAuthorizationRequirement
    {
        public ClaimAuthorizationRequirement(string claimType) { }
        public ClaimAuthorizationRequirement(string claimType, System.Collections.Generic.IEnumerable<string> allowedValues) { }
        public ClaimAuthorizationRequirement(string claimType, params string[] allowedValues) { }
        public ClaimAuthorizationRequirement(string claimType, System.Collections.Generic.IEnumerable<string>? allowedValues, System.Collections.Generic.IEnumerable<string>? displayValues) { }
        public System.Collections.Generic.IEnumerable<string> AllowedValues { get; }
        public string ClaimType { get; }
        public System.Collections.Generic.IEnumerable<string>? DisplayValues { get; }
        public System.Threading.Tasks.Task Authorize(GraphQL.Authorization.AuthorizationContext context) { }
    }
    public interface IAuthorizationEvaluator
    {
        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
    {
        System.Collections.Generic.IEnumerable<GraphQL.Authorization.IAuthorizationRequirement> Requirements { get; }
    }
    public interface IAuthorizationRequirement
    {
        System.Threading.Tasks.Task Authorize(GraphQL.Authorization.AuthorizationContext context);
    }
}
namespace GraphQL
{
    public static class AuthorizationGraphQLBuilderExtensions
    {
        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) { }
    }
}

================================================
FILE: src/GraphQL.Authorization.Tests/AuthenticatedUserRequirementTests.cs
================================================
namespace GraphQL.Authorization.Tests;

public class AuthenticatedUserRequirementTests
{
    [Fact]
    public async Task produces_error_when_not_authenticated()
    {
        var req = new AuthenticatedUserRequirement();

        var context = new AuthorizationContext
        {
            User = ValidationTestBase.CreatePrincipal()
        };

        await req.Authorize(context).ConfigureAwait(false);

        context.HasErrors.ShouldBeTrue();
        context.Errors.Single().ShouldBe("An authenticated user is required.");
    }

    [Fact]
    public async Task no_errors_when_authenticated()
    {
        var req = new AuthenticatedUserRequirement();

        var context = new AuthorizationContext
        {
            User = ValidationTestBase.CreatePrincipal("jwt")
        };

        await req.Authorize(context).ConfigureAwait(false);

        context.HasErrors.ShouldBeFalse();
    }
}


================================================
FILE: src/GraphQL.Authorization.Tests/AuthorizationEvaluatorTests.cs
================================================
namespace GraphQL.Authorization.Tests;

public class AuthorizationEvaluatorTests
{
    private readonly AuthorizationEvaluator _evaluator;
    private readonly AuthorizationSettings _settings;

    public AuthorizationEvaluatorTests()
    {
        _settings = new AuthorizationSettings();
        _evaluator = new AuthorizationEvaluator(_settings);
    }

    [Fact]
    public async Task fails_with_null_principal()
    {
        _settings.AddPolicy("MyPolicy", builder => builder.RequireClaim("Admin"));

        var result = await _evaluator.Evaluate(
            null,
            null,
            null,
            new[] { "MyPolicy" }
        ).ConfigureAwait(false);

        result.Succeeded.ShouldBeFalse();
    }

    [Fact]
    public async Task fails_when_missing_claim()
    {
        _settings.AddPolicy("MyPolicy", builder => builder.RequireClaim("Admin"));

        var result = await _evaluator.Evaluate(
            ValidationTestBase.CreatePrincipal(),
            null,
            null,
            new[] { "MyPolicy" }
        ).ConfigureAwait(false);

        result.Succeeded.ShouldBeFalse();
    }

    [Fact]
    public async Task fails_when_missing_policy()
    {
        _settings.AddPolicy("MyPolicy", builder => builder.RequireClaim("Admin"));

        var result = await _evaluator.Evaluate(
            ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            }),
            null,
            null,
            new[] { "PolicyDoesNotExist" }
        ).ConfigureAwait(false);

        result.Succeeded.ShouldBeFalse();
    }

    [Fact]
    public async Task succeeds_when_policy_applied()
    {
        _settings.AddPolicy("MyPolicy", builder => builder.RequireClaim("Admin"));

        var result = await _evaluator.Evaluate(
            ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            }),
            null,
            null,
            new[] { "MyPolicy" }
        ).ConfigureAwait(false);

        result.Succeeded.ShouldBeTrue();
    }

    [Fact]
    public async Task succeeds_with_claim_value()
    {
        _settings.AddPolicy("MyPolicy", builder => builder.RequireClaim("Admin", "true"));

        var result = await _evaluator.Evaluate(
            ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            }),
            null,
            null,
            new[] { "MyPolicy" }
        ).ConfigureAwait(false);

        result.Succeeded.ShouldBeTrue();
    }

    [Fact]
    public async Task succeeds_when_null_policies()
    {
        _settings.AddPolicy("MyPolicy", builder => builder.RequireClaim("Admin"));

        var result = await _evaluator.Evaluate(
            ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            }),
            null,
            null,
            null
        ).ConfigureAwait(false);

        result.Succeeded.ShouldBeTrue();
    }

    [Fact]
    public async Task succeeds_when_empty_policies()
    {
        _settings.AddPolicy("MyPolicy", _ => { });

        var result = await _evaluator.Evaluate(
            ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            }),
            null,
            null,
            Array.Empty<string>()
        ).ConfigureAwait(false);

        result.Succeeded.ShouldBeTrue();
    }

    [Fact]
    public async Task succeeds_when_null_principal()
    {
        var result = await _evaluator.Evaluate(
            null,
            null,
            null,
            null
        ).ConfigureAwait(false);

        result.Succeeded.ShouldBeTrue();
    }
}


================================================
FILE: src/GraphQL.Authorization.Tests/AuthorizationSchemaBuilderTests.cs
================================================
using GraphQL.Types;

namespace GraphQL.Authorization.Tests;

public class AuthorizationSchemaBuilderTests
{
    [Fact]
    public void can_set_policy_from_authorize_attribute()
    {
        string defs = """
            type Query {
              post(id: ID!): String
            }
            """;

        var schema = Schema.For(defs, builder => builder.Types.Include<QueryWithAttributes>());

        schema.Initialize();

        var query = (IObjectGraphType)schema.AllTypes["Query"]!;
        query.IsAuthorizationRequired().ShouldBeTrue();
        query.GetPolicies()!.Single().ShouldBe("ClassPolicy");

        var field = query.Fields.Single(x => x.Name == "post");
        field.IsAuthorizationRequired().ShouldBeTrue();
        field.GetPolicies()!.Single().ShouldBe("FieldPolicy");
    }

    [GraphQLMetadata("Query")]
    [Authorize("ClassPolicy")]
    public class QueryWithAttributes
    {
        [Authorize("FieldPolicy")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "test")]
        public string Post(string id) => "";
    }
}


================================================
FILE: src/GraphQL.Authorization.Tests/AuthorizationSettingsTests.cs
================================================
namespace GraphQL.Authorization.Tests;

public class AuthorizationSettingsTests
{
    private readonly AuthorizationSettings _settings;

    public AuthorizationSettingsTests()
    {
        _settings = new AuthorizationSettings();
    }

    [Fact]
    public void can_add_a_claim_policy()
    {
        _settings.AddPolicy("MyPolicy", builder => builder.RequireClaim("Admin"));

        _settings.Policies.Count().ShouldBe(1);

        var policy = _settings.Policies.Single();
        policy.Requirements.Single().ShouldBeOfType<ClaimAuthorizationRequirement>();
    }
}


================================================
FILE: src/GraphQL.Authorization.Tests/AuthorizationValidationRuleTests.cs
================================================
using GraphQL.Types;
using GraphQL.Types.Relay.DataObjects;

namespace GraphQL.Authorization.Tests;

public class AuthorizationValidationRuleTests : ValidationTestBase
{
    [Fact]
    public void class_policy_success()
    {
        Settings.AddPolicy("ClassPolicy", builder => builder.RequireClaim("admin"));
        Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));

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

    [Fact]
    public void class_policy_fail()
    {
        Settings.AddPolicy("ClassPolicy", builder => builder.RequireClaim("admin"));

        ShouldFailRule(config =>
        {
            config.Query = "query { post }";
            config.Schema = BasicSchema();
        });
    }

    [Fact]
    public void field_policy_success()
    {
        Settings.AddPolicy("ClassPolicy", builder => builder.RequireClaim("admin"));
        Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));

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

    [Fact]
    public void field_policy_fail()
    {
        Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));

        ShouldFailRule(config =>
        {
            config.Query = "query { post }";
            config.Schema = BasicSchema();
        });
    }

    [Fact]
    public void nested_type_policy_success()
    {
        Settings.AddPolicy("PostPolicy", builder => builder.RequireClaim("admin"));

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

    [Fact]
    public void nested_type_policy_fail()
    {
        Settings.AddPolicy("PostPolicy", builder => builder.RequireClaim("admin"));

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

    [Fact]
    public void nested_type_list_policy_fail()
    {
        Settings.AddPolicy("PostPolicy", builder => builder.RequireClaim("admin"));

        ShouldFailRule(config =>
        {
            config.Query = "query { posts }";
            config.Schema = NestedSchema();
        });
    }

    // https://github.com/graphql-dotnet/authorization/issues/5
    [Theory]
    [InlineData("c", "query p { posts } query c { comment }")]
    [InlineData(null, "query c { comment } query p { posts }")]
    public void issue5_should_pass(string operationName, string query)
    {
        Settings.AddPolicy("PostPolicy", builder => builder.RequireClaim("admin"));

        ShouldPassRule(config =>
        {
            config.OperationName = operationName;
            config.Query = query;
            config.Schema = NestedSchema();
        });
    }

    // https://github.com/graphql-dotnet/authorization/issues/5
    [Theory]
    [InlineData("query a { article { id } } query b { article { ...frag } } fragment frag on Article { content }")]
    [InlineData("query a { article { ...frag1 author } } query b { article { ...frag2 } } fragment frag1 on Article { id } fragment frag2 on Article { content }")]
    public void issue5_with_fragment_should_pass(string query)
    {
        Settings.AddPolicy("AdminPolicy", builder => builder.RequireClaim("admin"));

        ShouldPassRule(config =>
        {
            config.Query = query;
            config.Schema = TypedSchema();
        });
    }

    // https://github.com/graphql-dotnet/authorization/issues/5
    [Fact]
    public void issue5_with_fragment_should_fail()
    {
        Settings.AddPolicy("AdminPolicy", builder => builder.RequireClaim("admin"));

        ShouldFailRule(config =>
        {
            config.Query = "query a { article { ...frag } } query b { article { ...frag } } fragment frag on Article { content }";
            config.Schema = TypedSchema();
            config.ValidateResult = result => _ = result.Errors.Single(x => x.Message == $"You are not authorized to run this query.\nRequired claim 'admin' is not present.");
        });
    }

    [Fact]
    public void nested_fragment_should_fail()
    {
        Settings.AddPolicy("AdminPolicy", builder => builder.RequireClaim("admin"));

        ShouldFailRule(config =>
        {
            config.Query = "query a { article { ...frag } } query b { article { ...frag } } fragment frag on Article { ...frag2 } fragment frag2 on Article { content }";
            config.Schema = TypedSchema();
            config.ValidateResult = result => _ = result.Errors.Single(x => x.Message == $"You are not authorized to run this query.\nRequired claim 'admin' is not present.");
        });
    }

    [Fact]
    public void nested_type_list_non_null_policy_fail()
    {
        Settings.AddPolicy("PostPolicy", builder => builder.RequireClaim("admin"));

        ShouldFailRule(config =>
        {
            config.Query = "query { postsNonNull }";
            config.Schema = NestedSchema();
        });
    }

    [Fact]
    public void passes_with_claim_on_input_type()
    {
        Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));

        ShouldPassRule(config =>
        {
            config.Query = """query { author(input: { name: "Quinn" }) }""";
            config.Schema = TypedSchema();
            config.User = CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            });
        });
    }

    [Fact]
    public void fails_on_missing_claim_on_input_type()
    {
        Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));

        ShouldFailRule(config =>
        {
            config.Query = """query { author(input: { name: "Quinn" }) }""";
            config.Schema = TypedSchema();
        });
    }

    [Fact]
    public void passes_with_multiple_policies_on_field_and_single_on_input_type()
    {
        Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));
        Settings.AddPolicy("AdminPolicy", builder => builder.RequireClaim("admin"));
        Settings.AddPolicy("ConfidentialPolicy", builder => builder.RequireClaim("admin"));

        ShouldPassRule(config =>
        {
            config.Query = """query { author(input: { name: "Quinn" }) project(input: { name: "TEST" }) }""";
            config.Schema = TypedSchema();
            config.User = CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            });
        });
    }

    [Fact]
    public void Issue61()
    {
        ShouldPassRule(config =>
        {
            config.Query = "query { unknown(obj: {id: 7}) }";
            config.Schema = TypedSchema();
            config.User = CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            });
        });
    }

    [Fact]
    public void passes_with_claim_on_variable_type()
    {
        Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));

        ShouldPassRule(config =>
        {
            config.Query = "query Author($input: AuthorInputType!) { author(input: $input) }";
            config.Schema = TypedSchema();
            config.Variables = new Inputs(new Dictionary<string, object?>()
            {
                {
                    "input",
                    new Dictionary<string,object>{ { "name","Quinn" } }
                }
            });
            config.User = CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            });
        });
    }

    [Fact]
    public void passes_with_claim_on_variable_type_without_inputs_but_fails_later_either()
    {
        Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));

        ShouldFailRule(config =>
        {
            config.ValidateResult = result =>
            {
                // no auth error on null inputs, only INVALID_VALUE
                result.Errors.Count.ShouldBe(1);
                result.Errors[0].Code.ShouldBe("INVALID_VALUE");
                result.Errors[0].Message.ShouldBe("Variable '$input' is invalid. No value provided for a non-null variable.");
            };
            config.Query = "query Author($input: AuthorInputType!) { author(input: $input) }";
            config.Schema = TypedSchema();
            config.Variables = null;
            config.User = CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            });
        });
    }

    [Fact]
    public void fails_on_missing_claim_on_variable_type()
    {
        Settings.AddPolicy("FieldPolicy", builder => builder.RequireClaim("admin"));

        ShouldFailRule(config =>
        {
            config.Query = "query Author($input: AuthorInputType!) { author(input: $input) }";
            config.Schema = TypedSchema();
            config.Variables = new Inputs(new Dictionary<string, object?>()
            {
                {
                    "input",
                    new Dictionary<string,object>{ { "name","Quinn" } }
                }
            });
        });
    }

    [Fact]
    public void passes_with_policy_on_connection_type()
    {
        Settings.AddPolicy("ConnectionPolicy", _ => _.RequireClaim("admin"));

        ShouldPassRule(config =>
        {
            config.Query = "query { posts { items { id } } }";
            config.Schema = TypedSchema();
            config.User = CreatePrincipal(claims: new Dictionary<string, string>
            {
                { "Admin", "true" }
            });
        });
    }

    [Fact]
    public void fails_on_missing_claim_on_connection_type()
    {
        Settings.AddPolicy("ConnectionPolicy", _ => _.RequireClaim("admin"));

        ShouldFailRule(config =>
        {
            config.Query = "query { posts { items { id } } }";
            config.Schema = TypedSchema();
            config.User = CreatePrincipal();
        });
    }

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

        return Schema.For(defs, builder => builder.Types.Include<BasicQueryWithAttributes>());
    }

    [GraphQLMetadata("Query")]
    [Authorize("ClassPolicy")]
    public class BasicQueryWithAttributes
    {
        [Authorize("FieldPolicy")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "test")]
        public string Post(string id) => "";
    }

    private static ISchema NestedSchema()
    {
        string defs = """
            type Query {
              post(id: ID!): Post
              posts: [Post]
              postsNonNull: [Post!]!
              comment: String
            }

            type Post {
              id: ID!
            }
            """;

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

    [GraphQLMetadata("Query")]
    public class NestedQueryWithAttributes
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "test")]
        public Post? Post(string id) => null;

        public IEnumerable<Post>? Posts() => null;

        public IEnumerable<Post>? PostsNonNull() => null;

        public string? Comment() => null;
    }

    [Authorize("PostPolicy")]
    public class Post
    {
        public string? Id { get; set; }
    }

    public class PostGraphType : ObjectGraphType<Post>
    {
        public PostGraphType()
        {
            Field(p => p.Id);
        }
    }

    public class Article
    {
        public string? Id { get; set; }

        public string? Author { get; set; }

        public string? Content { get; set; }
    }

    public class ArticleGraphType : ObjectGraphType<Article>
    {
        public ArticleGraphType()
        {
            Field(p => p.Id);
            Field(p => p.Author);
            Field(p => p.Content).AuthorizeWithPolicy("AdminPolicy");
        }
    }

    public class Author
    {
        public string? Name { get; set; }
    }

    private static ISchema TypedSchema()
    {
        var query = new ObjectGraphType();
        query.Field<StringGraphType>("author")
            .Arguments(new QueryArguments(new QueryArgument<AuthorInputType> { Name = "input" }))
            .Resolve(_ => "testing");

        query.Connection<PostGraphType>("posts")
            .AuthorizeWithPolicy("ConnectionPolicy")
            .Resolve(_ => new Connection<Post>());

        query.Field<StringGraphType>("project")
            .Arguments(new QueryArguments(new QueryArgument<AuthorInputType> { Name = "input" }))
            .Resolve(_ => "testing").AuthorizeWithPolicy("AdminPolicy").AuthorizeWithPolicy("ConfidentialPolicy");

        query.Field<ArticleGraphType>("article")
            .Resolve(_ => null);

        return new Schema { Query = query };
    }

    public class AuthorInputType : InputObjectGraphType<Author>
    {
        public AuthorInputType()
        {
            Name = "AuthorInputType";
            Field(x => x.Name).AuthorizeWithPolicy("FieldPolicy");
        }
    }
}


================================================
FILE: src/GraphQL.Authorization.Tests/ClaimAuthorizationRequirementTests.cs
================================================
namespace GraphQL.Authorization.Tests;

public class ClaimAuthorizationRequirementTests
{
    [Fact]
    public async Task produces_error_when_missing_claim_ignoring_value()
    {
        var req = new ClaimAuthorizationRequirement("Admin");

        var context = new AuthorizationContext
        {
            User = ValidationTestBase.CreatePrincipal()
        };

        await req.Authorize(context).ConfigureAwait(false);

        context.HasErrors.ShouldBeTrue();
        context.Errors.Single().ShouldBe("Required claim 'Admin' is not present.");
    }

    [Fact]
    public async Task produces_error_when_missing_claim_with_single_value()
    {
        var req = new ClaimAuthorizationRequirement("Admin", "true");

        var context = new AuthorizationContext
        {
            User = ValidationTestBase.CreatePrincipal()
        };

        await req.Authorize(context).ConfigureAwait(false);

        context.HasErrors.ShouldBeTrue();
        context.Errors.Single().ShouldBe("Required claim 'Admin' with any value of 'true' is not present.");
    }

    [Fact]
    public async Task produces_error_when_missing_claim_with_multiple_values()
    {
        var req = new ClaimAuthorizationRequirement("Admin", "true", "maybe");

        var context = new AuthorizationContext
        {
            User = ValidationTestBase.CreatePrincipal()
        };

        await req.Authorize(context).ConfigureAwait(false);

        context.HasErrors.ShouldBeTrue();
        context.Errors.Single().ShouldBe("Required claim 'Admin' with any value of 'true, maybe' is not present.");
    }

    [Fact]
    public async Task succeeds_when_claim_with_ignoring_value()
    {
        var req = new ClaimAuthorizationRequirement("Admin");

        var context = new AuthorizationContext
        {
            User = ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string> { { "Admin", "true" } })
        };

        await req.Authorize(context).ConfigureAwait(false);

        context.HasErrors.ShouldBeFalse();
    }

    [Fact]
    public async Task succeeds_when_claim_with_single_value()
    {
        var req = new ClaimAuthorizationRequirement("Admin", "true");

        var context = new AuthorizationContext
        {
            User = ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string> { { "Admin", "true" } })
        };

        await req.Authorize(context).ConfigureAwait(false);

        context.HasErrors.ShouldBeFalse();
    }

    [Fact]
    public async Task succeeds_when_claim_with_multiple_values()
    {
        var req = new ClaimAuthorizationRequirement("Admin", "true", "maybe");

        var context = new AuthorizationContext
        {
            User = ValidationTestBase.CreatePrincipal(claims: new Dictionary<string, string> { { "Admin", "maybe" } })
        };

        await req.Authorize(context).ConfigureAwait(false);

        context.HasErrors.ShouldBeFalse();
    }
}


================================================
FILE: src/GraphQL.Authorization.Tests/GraphQL.Authorization.Tests.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="../Tests.props" />

  <PropertyGroup Condition="'$(SingleTestPlatform)' == 'true'">
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>

  <PropertyGroup Condition="'$(SingleTestPlatform)' != 'true'">
    <TargetFrameworks>net8.0;net7.0;net6.0;net5.0;netcoreapp3.1</TargetFrameworks>
  </PropertyGroup>

  <PropertyGroup>
    <GraphQLTestVersion>8.0.0</GraphQLTestVersion>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\GraphQL.Authorization\GraphQL.Authorization.csproj" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="GraphQL" Version="$(GraphQLTestVersion)" />
  </ItemGroup>

</Project>


================================================
FILE: src/GraphQL.Authorization.Tests/ValidationTestBase.cs
================================================
using System.Security.Claims;
using GraphQL.Execution;
using GraphQL.Validation;
using GraphQLParser;

namespace GraphQL.Authorization.Tests;

public class ValidationTestBase
{
    public ValidationTestBase()
    {
        Settings = new AuthorizationSettings();
        Rule = new AuthorizationValidationRule(new AuthorizationEvaluator(Settings));
    }

    protected AuthorizationValidationRule Rule { get; }

    protected AuthorizationSettings Settings { get; }

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

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

        config.Schema.Initialize();

        var result = Validate(config);

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

    protected void ShouldFailRule(Action<ValidationTestConfig> configure)
    {
        var config = new ValidationTestConfig();
        config.Rules.Add(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.");
        config.ValidateResult(result);
    }

    private static IValidationResult Validate(ValidationTestConfig config)
    {
        var documentBuilder = new GraphQLDocumentBuilder();
        var document = documentBuilder.Build(config.Query);
        var validator = new DocumentValidator();
        return validator.ValidateAsync(new ValidationOptions
        {
            Schema = config.Schema,
            Document = document,
            Operation = document.OperationWithName(config.OperationName) ?? throw new InvalidOperationException("Could not find specified operation"),
            Rules = config.Rules,
            Variables = config.Variables ?? Inputs.Empty,
            User = config.User
        }).GetAwaiter().GetResult();
    }

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

        if (claims != null)
        {
            foreach (var c in claims)
                claimsList.Add(new Claim(c.Key, c.Value));
        }

        return new ClaimsPrincipal(new ClaimsIdentity(claimsList, authenticationType));
    }
}


================================================
FILE: src/GraphQL.Authorization.Tests/ValidationTestConfig.cs
================================================
using System.Security.Claims;
using GraphQL.Types;
using GraphQL.Validation;

namespace GraphQL.Authorization.Tests;

public class ValidationTestConfig
{
    public string OperationName { get; set; } = null!;

    public string Query { get; set; } = null!;

    public ISchema Schema { get; set; } = null!;

    public List<IValidationRule> Rules { get; set; } = new();

    public ClaimsPrincipal? User { get; set; }

    public Inputs? Variables { get; set; }

    public Action<IValidationResult> ValidateResult = _ => { };
}


================================================
FILE: src/GraphQL.Authorization.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphQL.Authorization", "GraphQL.Authorization\GraphQL.Authorization.csproj", "{21771B0C-0FCE-41DA-BF0B-67D70368BB00}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphQL.Authorization.Tests", "GraphQL.Authorization.Tests\GraphQL.Authorization.Tests.csproj", "{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Harness", "Harness\Harness.csproj", "{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Solution Items", ".Solution Items", "{F1263413-6A34-42F2-ABA7-E38AB3DCB548}"
	ProjectSection(SolutionItems) = preProject
		..\.editorconfig = ..\.editorconfig
		..\.gitignore = ..\.gitignore
		Directory.Build.props = Directory.Build.props
		Directory.Build.targets = Directory.Build.targets
		..\LICENSE.md = ..\LICENSE.md
		..\README.md = ..\README.md
		Tests.props = Tests.props
	EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{84514A09-9BB4-4C85-8A8E-92AF5AA26445}"
	ProjectSection(SolutionItems) = preProject
		..\.github\codecov.yaml = ..\.github\codecov.yaml
		..\.github\dependabot.yml = ..\.github\dependabot.yml
		..\.github\FUNDING.yml = ..\.github\FUNDING.yml
		..\.github\labeler.yml = ..\.github\labeler.yml
	EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{C1216C18-FAAE-46CA-95EB-B2202FBC994A}"
	ProjectSection(SolutionItems) = preProject
		..\.github\workflows\build.yml = ..\.github\workflows\build.yml
		..\.github\workflows\codeql-analysis.yml = ..\.github\workflows\codeql-analysis.yml
		..\.github\workflows\format.yml = ..\.github\workflows\format.yml
		..\.github\workflows\label.yml = ..\.github\workflows\label.yml
		..\.github\workflows\publish.yml = ..\.github\workflows\publish.yml
		..\.github\workflows\test.yml = ..\.github\workflows\test.yml
		..\.github\workflows\wipcheck.yml = ..\.github\workflows\wipcheck.yml
	EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicSample", "BasicSample\BasicSample.csproj", "{49174102-8BD4-4193-8CB6-026881BF1B6B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphQL.Authorization.ApiTests", "GraphQL.Authorization.ApiTests\GraphQL.Authorization.ApiTests.csproj", "{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{A5C2458F-F60E-4340-ADF6-C8DF6A6601AF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{70F571C2-0255-457D-BAAA-3BFDC60B6BC9}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|x64 = Debug|x64
		Debug|x86 = Debug|x86
		Release|Any CPU = Release|Any CPU
		Release|x64 = Release|x64
		Release|x86 = Release|x86
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|x64.ActiveCfg = Debug|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|x64.Build.0 = Debug|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|x86.ActiveCfg = Debug|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Debug|x86.Build.0 = Debug|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|Any CPU.Build.0 = Release|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|x64.ActiveCfg = Release|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|x64.Build.0 = Release|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|x86.ActiveCfg = Release|Any CPU
		{21771B0C-0FCE-41DA-BF0B-67D70368BB00}.Release|x86.Build.0 = Release|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|x64.ActiveCfg = Debug|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|x64.Build.0 = Debug|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|x86.ActiveCfg = Debug|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Debug|x86.Build.0 = Debug|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|Any CPU.Build.0 = Release|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|x64.ActiveCfg = Release|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|x64.Build.0 = Release|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|x86.ActiveCfg = Release|Any CPU
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66}.Release|x86.Build.0 = Release|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|x64.ActiveCfg = Debug|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|x64.Build.0 = Debug|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|x86.ActiveCfg = Debug|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Debug|x86.Build.0 = Debug|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|Any CPU.Build.0 = Release|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|x64.ActiveCfg = Release|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|x64.Build.0 = Release|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|x86.ActiveCfg = Release|Any CPU
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F}.Release|x86.Build.0 = Release|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|x64.ActiveCfg = Debug|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|x64.Build.0 = Debug|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|x86.ActiveCfg = Debug|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Debug|x86.Build.0 = Debug|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|Any CPU.Build.0 = Release|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|x64.ActiveCfg = Release|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|x64.Build.0 = Release|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|x86.ActiveCfg = Release|Any CPU
		{49174102-8BD4-4193-8CB6-026881BF1B6B}.Release|x86.Build.0 = Release|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|x64.ActiveCfg = Debug|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|x64.Build.0 = Debug|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|x86.ActiveCfg = Debug|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Debug|x86.Build.0 = Debug|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|Any CPU.Build.0 = Release|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|x64.ActiveCfg = Release|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|x64.Build.0 = Release|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|x86.ActiveCfg = Release|Any CPU
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0}.Release|x86.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(NestedProjects) = preSolution
		{C482F1AF-6E9D-4D1C-96D7-3C0206312B66} = {70F571C2-0255-457D-BAAA-3BFDC60B6BC9}
		{DEA32495-F7AA-45F0-8AF6-DE4FB089994F} = {A5C2458F-F60E-4340-ADF6-C8DF6A6601AF}
		{C1216C18-FAAE-46CA-95EB-B2202FBC994A} = {84514A09-9BB4-4C85-8A8E-92AF5AA26445}
		{49174102-8BD4-4193-8CB6-026881BF1B6B} = {A5C2458F-F60E-4340-ADF6-C8DF6A6601AF}
		{0A74FD44-76DD-4FD1-BFA1-8A0B950021E0} = {70F571C2-0255-457D-BAAA-3BFDC60B6BC9}
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {B582AABA-5414-45C5-920C-1A00B5B1FDB4}
	EndGlobalSection
EndGlobal


================================================
FILE: src/Harness/GraphQL.cs
================================================
namespace GraphQL;

/// <summary>
/// CLR type to map to the 'Query' graph type.
/// </summary>
public class Query
{
    /// <summary>
    /// Resolver for 'Query.viewer' field.
    /// </summary>
    [Authorize("AdminPolicy")]
    public User Viewer() => new() { Id = Guid.NewGuid().ToString(), Name = "Quinn" };

    /// <summary>
    /// Resolver for 'Query.users' field.
    /// </summary>
    public List<User> Users() => new() { new User { Id = Guid.NewGuid().ToString(), Name = "Quinn" } };

    /// <summary>
    /// Resolver for 'Query.guest' field.
    /// </summary>
    public string Guest() => "guest42";
}

/// <summary>
/// CLR type to map to the 'User' graph type.
/// </summary>
public class User
{
    /// <summary>
    /// Resolver for 'User.id' field. Just a simple property.
    /// </summary>
    public string? Id { get; set; }

    /// <summary>
    /// Resolver for 'User.name' field. Just a simple property.
    /// </summary>
    public string? Name { get; set; }
}


================================================
FILE: src/Harness/Harness.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Description>Example ASP.NET Core project to demonstrate GraphQL.NET Authorization setup</Description>
    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\GraphQL.Authorization\GraphQL.Authorization.csproj" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="GraphQL.MicrosoftDI" Version="8.*" />
    <PackageReference Include="GraphQL.Server.Ui.GraphiQL" Version="8.*" />
    <PackageReference Include="GraphQL.Server.Ui.Playground" Version="8.*" />
    <PackageReference Include="GraphQL.Server.Transports.AspNetCore" Version="8.*" />
  </ItemGroup>

  <ItemGroup>
    <Using Remove="System.Net.Http.Json" />
  </ItemGroup>

</Project>


================================================
FILE: src/Harness/Program.cs
================================================
using GraphQL;
using GraphQL.Types;
using Microsoft.Extensions.DependencyInjection.Extensions;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpContextAccessor();
builder.Services.TryAddSingleton<ISchema>(_ =>
{
    const string definitions = """
        type User {
          id: ID
          name: String
        }

        type Query {
          viewer: User
          users: [User]
          guest: String
        }
        """;
    var schema = Schema.For(definitions, builder => builder.Types.Include<Query>());
    schema.AllTypes["User"]!.AuthorizeWithPolicy("AdminPolicy");
    return schema;
});

// Claims principal must look something like this to allow access.
// var user = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("role", "Admin") }));

builder.Services.AddGraphQL(builder => builder
    .AddSystemTextJson()
    .ConfigureExecutionOptions(opt =>
    {
        opt.Root = new Query();
        // opt.User = user; // User property has already been initialized. Uncomment to play with ClaimsPrincipal.
    })
    .AddErrorInfoProvider(opt => opt.ExposeExceptionDetails = true)
    .AddAuthorization(settings => settings.AddPolicy("AdminPolicy", p => p.RequireClaim("role", "Admin"))));

var app = builder.Build();

if (app.Environment.IsDevelopment())
    app.UseDeveloperExceptionPage();

app.UseGraphQL();
app.UseGraphQLGraphiQL();
app.UseGraphQLPlayground(options: new GraphQL.Server.Ui.Playground.PlaygroundOptions { SchemaPollingEnabled = false });

app.Run();


================================================
FILE: src/Harness/Properties/launchSettings.json
================================================
{
  "profiles": {
    "Harness [GraphiQL]": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "ui/graphiql",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:5000"
    },
    "Harness [Playground]": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "ui/playground",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:5000"
    }
  }
}

================================================
FILE: src/Harness/appsettings.Development.json
================================================
{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}


================================================
FILE: src/Harness/appsettings.json
================================================
{
  "Logging": {
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "IncludeScopes": false,
      "LogLevel": {
        "Default": "Warning"
      }
    }
  }
}


================================================
FILE: src/Tests.props
================================================
<Project>
  <Import Project="$(MSBuildThisFileDirectory)Tests.local.props" Condition="Exists('$(MSBuildThisFileDirectory)Tests.local.props')" />

  <PropertyGroup>
    <NoWarn>$(NoWarn);IDE1006;CS0618</NoWarn>
    <SingleTestPlatform Condition="'$(SingleTestPlatform)' == ''">false</SingleTestPlatform>
    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="coverlet.collector" Version="6.0.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.0" />
    <PackageReference Include="Shouldly" Version="4.2.1" />
    <PackageReference Include="xunit" Version="2.5.0" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5" />
    <PackageReference Include="Moq" Version="4.20.2" />
  </ItemGroup>

  <ItemGroup>
    <Using Include="Shouldly" />
    <Using Include="Xunit" />
  </ItemGroup>

  <ItemGroup>
    <Content Include="..\xunit.runner.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

</Project>


================================================
FILE: src/xunit.runner.json
================================================
{
  "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
  "diagnosticMessages": true,
  "longRunningTestSeconds": 10
}
Download .txt
gitextract_vfdy268n/

├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   ├── codecov.yaml
│   ├── dependabot.yml
│   ├── labeler.yml
│   └── workflows/
│       ├── build.yml
│       ├── codeql-analysis.yml
│       ├── format.yml
│       ├── label.yml
│       ├── publish.yml
│       ├── test.yml
│       └── wipcheck.yml
├── .gitignore
├── .vscode/
│   ├── launch.json
│   └── tasks.json
├── LICENSE.md
├── README.md
├── codeql/
│   └── GraphQL.Authorization.CodeQL.sln
└── src/
    ├── BasicSample/
    │   ├── BasicSample.csproj
    │   └── Program.cs
    ├── Directory.Build.props
    ├── Directory.Build.targets
    ├── GraphQL.Authorization/
    │   ├── AuthorizationContext.cs
    │   ├── AuthorizationEvaluator.cs
    │   ├── AuthorizationPolicy.cs
    │   ├── AuthorizationPolicyBuilder.cs
    │   ├── AuthorizationResult.cs
    │   ├── AuthorizationSettings.cs
    │   ├── AuthorizationValidationRule.cs
    │   ├── Extensions/
    │   │   └── AuthorizationGraphQLBuilderExtensions.cs
    │   ├── GraphQL.Authorization.csproj
    │   ├── IAuthorizationEvaluator.cs
    │   ├── IAuthorizationPolicy.cs
    │   └── Requirements/
    │       ├── AuthenticatedUserRequirement.cs
    │       ├── ClaimAuthorizationRequirement.cs
    │       └── IAuthorizationRequirement.cs
    ├── GraphQL.Authorization.ApiTests/
    │   ├── ApiApprovalTests.cs
    │   ├── GraphQL.Authorization.ApiTests.csproj
    │   └── GraphQL.Authorization.approved.txt
    ├── GraphQL.Authorization.Tests/
    │   ├── AuthenticatedUserRequirementTests.cs
    │   ├── AuthorizationEvaluatorTests.cs
    │   ├── AuthorizationSchemaBuilderTests.cs
    │   ├── AuthorizationSettingsTests.cs
    │   ├── AuthorizationValidationRuleTests.cs
    │   ├── ClaimAuthorizationRequirementTests.cs
    │   ├── GraphQL.Authorization.Tests.csproj
    │   ├── ValidationTestBase.cs
    │   └── ValidationTestConfig.cs
    ├── GraphQL.Authorization.sln
    ├── Harness/
    │   ├── GraphQL.cs
    │   ├── Harness.csproj
    │   ├── Program.cs
    │   ├── Properties/
    │   │   └── launchSettings.json
    │   ├── appsettings.Development.json
    │   └── appsettings.json
    ├── Tests.props
    └── xunit.runner.json
Download .txt
SYMBOL INDEX (128 symbols across 23 files)

FILE: src/GraphQL.Authorization.ApiTests/ApiApprovalTests.cs
  class ApiApprovalTests (line 8) | public class ApiApprovalTests
    method public_api_should_not_change_unintentionally (line 10) | [Theory]

FILE: src/GraphQL.Authorization.Tests/AuthenticatedUserRequirementTests.cs
  class AuthenticatedUserRequirementTests (line 3) | public class AuthenticatedUserRequirementTests
    method produces_error_when_not_authenticated (line 5) | [Fact]
    method no_errors_when_authenticated (line 21) | [Fact]

FILE: src/GraphQL.Authorization.Tests/AuthorizationEvaluatorTests.cs
  class AuthorizationEvaluatorTests (line 3) | public class AuthorizationEvaluatorTests
    method AuthorizationEvaluatorTests (line 8) | public AuthorizationEvaluatorTests()
    method fails_with_null_principal (line 14) | [Fact]
    method fails_when_missing_claim (line 29) | [Fact]
    method fails_when_missing_policy (line 44) | [Fact]
    method succeeds_when_policy_applied (line 62) | [Fact]
    method succeeds_with_claim_value (line 80) | [Fact]
    method succeeds_when_null_policies (line 98) | [Fact]
    method succeeds_when_empty_policies (line 116) | [Fact]
    method succeeds_when_null_principal (line 134) | [Fact]

FILE: src/GraphQL.Authorization.Tests/AuthorizationSchemaBuilderTests.cs
  class AuthorizationSchemaBuilderTests (line 5) | public class AuthorizationSchemaBuilderTests
    method can_set_policy_from_authorize_attribute (line 7) | [Fact]
    class QueryWithAttributes (line 29) | [GraphQLMetadata("Query")]
      method Post (line 33) | [Authorize("FieldPolicy")]

FILE: src/GraphQL.Authorization.Tests/AuthorizationSettingsTests.cs
  class AuthorizationSettingsTests (line 3) | public class AuthorizationSettingsTests
    method AuthorizationSettingsTests (line 7) | public AuthorizationSettingsTests()
    method can_add_a_claim_policy (line 12) | [Fact]

FILE: src/GraphQL.Authorization.Tests/AuthorizationValidationRuleTests.cs
  class AuthorizationValidationRuleTests (line 6) | public class AuthorizationValidationRuleTests : ValidationTestBase
    method class_policy_success (line 8) | [Fact]
    method class_policy_fail (line 25) | [Fact]
    method field_policy_success (line 37) | [Fact]
    method field_policy_fail (line 54) | [Fact]
    method nested_type_policy_success (line 66) | [Fact]
    method nested_type_policy_fail (line 82) | [Fact]
    method nested_type_list_policy_fail (line 94) | [Fact]
    method issue5_should_pass (line 107) | [Theory]
    method issue5_with_fragment_should_pass (line 123) | [Theory]
    method issue5_with_fragment_should_fail (line 138) | [Fact]
    method nested_fragment_should_fail (line 151) | [Fact]
    method nested_type_list_non_null_policy_fail (line 164) | [Fact]
    method passes_with_claim_on_input_type (line 176) | [Fact]
    method fails_on_missing_claim_on_input_type (line 192) | [Fact]
    method passes_with_multiple_policies_on_field_and_single_on_input_type (line 204) | [Fact]
    method Issue61 (line 222) | [Fact]
    method passes_with_claim_on_variable_type (line 236) | [Fact]
    method passes_with_claim_on_variable_type_without_inputs_but_fails_later_either (line 259) | [Fact]
    method fails_on_missing_claim_on_variable_type (line 283) | [Fact]
    method passes_with_policy_on_connection_type (line 302) | [Fact]
    method fails_on_missing_claim_on_connection_type (line 318) | [Fact]
    method BasicSchema (line 331) | private static ISchema BasicSchema()
    class BasicQueryWithAttributes (line 342) | [GraphQLMetadata("Query")]
      method Post (line 346) | [Authorize("FieldPolicy")]
    method NestedSchema (line 351) | private static ISchema NestedSchema()
    class NestedQueryWithAttributes (line 373) | [GraphQLMetadata("Query")]
      method Post (line 376) | [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:R...
      method Posts (line 379) | public IEnumerable<Post>? Posts() => null;
      method PostsNonNull (line 381) | public IEnumerable<Post>? PostsNonNull() => null;
      method Comment (line 383) | public string? Comment() => null;
    class Post (line 386) | [Authorize("PostPolicy")]
    class PostGraphType (line 392) | public class PostGraphType : ObjectGraphType<Post>
      method PostGraphType (line 394) | public PostGraphType()
    class Article (line 400) | public class Article
    class ArticleGraphType (line 409) | public class ArticleGraphType : ObjectGraphType<Article>
      method ArticleGraphType (line 411) | public ArticleGraphType()
    class Author (line 419) | public class Author
    method TypedSchema (line 424) | private static ISchema TypedSchema()
    class AuthorInputType (line 445) | public class AuthorInputType : InputObjectGraphType<Author>
      method AuthorInputType (line 447) | public AuthorInputType()

FILE: src/GraphQL.Authorization.Tests/ClaimAuthorizationRequirementTests.cs
  class ClaimAuthorizationRequirementTests (line 3) | public class ClaimAuthorizationRequirementTests
    method produces_error_when_missing_claim_ignoring_value (line 5) | [Fact]
    method produces_error_when_missing_claim_with_single_value (line 21) | [Fact]
    method produces_error_when_missing_claim_with_multiple_values (line 37) | [Fact]
    method succeeds_when_claim_with_ignoring_value (line 53) | [Fact]
    method succeeds_when_claim_with_single_value (line 68) | [Fact]
    method succeeds_when_claim_with_multiple_values (line 83) | [Fact]

FILE: src/GraphQL.Authorization.Tests/ValidationTestBase.cs
  class ValidationTestBase (line 8) | public class ValidationTestBase
    method ValidationTestBase (line 10) | public ValidationTestBase()
    method ShouldPassRule (line 20) | protected void ShouldPassRule(Action<ValidationTestConfig> configure)
    method ShouldFailRule (line 41) | protected void ShouldFailRule(Action<ValidationTestConfig> configure)
    method Validate (line 57) | private static IValidationResult Validate(ValidationTestConfig config)
    method CreatePrincipal (line 73) | internal static ClaimsPrincipal CreatePrincipal(string? authentication...

FILE: src/GraphQL.Authorization.Tests/ValidationTestConfig.cs
  class ValidationTestConfig (line 7) | public class ValidationTestConfig

FILE: src/GraphQL.Authorization/AuthorizationContext.cs
  class AuthorizationContext (line 8) | public class AuthorizationContext
    method ReportError (line 41) | public void ReportError(string error) => (_errors ??= new()).Add(error);

FILE: src/GraphQL.Authorization/AuthorizationEvaluator.cs
  class AuthorizationEvaluator (line 8) | public class AuthorizationEvaluator : IAuthorizationEvaluator
    method AuthorizationEvaluator (line 16) | public AuthorizationEvaluator(AuthorizationSettings settings)
    method Evaluate (line 22) | public async Task<AuthorizationResult> Evaluate(

FILE: src/GraphQL.Authorization/AuthorizationPolicy.cs
  class AuthorizationPolicy (line 6) | public class AuthorizationPolicy : IAuthorizationPolicy
    method AuthorizationPolicy (line 14) | public AuthorizationPolicy(IEnumerable<IAuthorizationRequirement> requ...

FILE: src/GraphQL.Authorization/AuthorizationPolicyBuilder.cs
  class AuthorizationPolicyBuilder (line 7) | public class AuthorizationPolicyBuilder
    method Build (line 15) | public AuthorizationPolicy Build() => new(_requirements);
    method RequireClaim (line 22) | public AuthorizationPolicyBuilder RequireClaim(string claimType)
    method RequireClaim (line 34) | public AuthorizationPolicyBuilder RequireClaim(string claimType, param...
    method RequireClaim (line 50) | public AuthorizationPolicyBuilder RequireClaim(string claimType, IEnum...
    method RequireAuthenticatedUser (line 60) | public AuthorizationPolicyBuilder RequireAuthenticatedUser()
    method AddRequirement (line 71) | public AuthorizationPolicyBuilder AddRequirement(IAuthorizationRequire...

FILE: src/GraphQL.Authorization/AuthorizationResult.cs
  class AuthorizationResult (line 6) | public class AuthorizationResult
    method Success (line 25) | public static AuthorizationResult Success() => _success;
    method Fail (line 32) | public static AuthorizationResult Fail(IEnumerable<string> errors) => ...

FILE: src/GraphQL.Authorization/AuthorizationSettings.cs
  class AuthorizationSettings (line 7) | public class AuthorizationSettings
    method GetPolicies (line 21) | public IEnumerable<IAuthorizationPolicy> GetPolicies(IEnumerable<strin...
    method GetPolicy (line 43) | public IAuthorizationPolicy? GetPolicy(string name) => _policies.TryGe...
    method AddPolicy (line 50) | public void AddPolicy(string name, IAuthorizationPolicy policy) => _po...
    method AddPolicy (line 57) | public void AddPolicy(string name, Action<AuthorizationPolicyBuilder> ...

FILE: src/GraphQL.Authorization/AuthorizationValidationRule.cs
  class AuthorizationValidationRule (line 11) | public class AuthorizationValidationRule : ValidationRuleBase
    method AuthorizationValidationRule (line 19) | public AuthorizationValidationRule(IAuthorizationEvaluator evaluator)
    method GetPreNodeVisitorAsync (line 25) | public override async ValueTask<INodeVisitor?> GetPreNodeVisitorAsync(...
    class Visitor (line 39) | private class Visitor : INodeVisitor
      method Visitor (line 44) | public Visitor(IAuthorizationEvaluator evaluator)
      method EnterAsync (line 49) | public async ValueTask EnterAsync(ASTNode node, ValidationContext co...
      method LeaveAsync (line 108) | public ValueTask LeaveAsync(ASTNode node, ValidationContext context)
      method AuthorizeAsync (line 116) | public async ValueTask AuthorizeAsync(ASTNode? node, IMetadataReader...

FILE: src/GraphQL.Authorization/Extensions/AuthorizationGraphQLBuilderExtensions.cs
  class AuthorizationGraphQLBuilderExtensions (line 9) | public static class AuthorizationGraphQLBuilderExtensions
    method AddAuthorization (line 17) | public static IGraphQLBuilder AddAuthorization(this IGraphQLBuilder bu...
    method AddAuthorization (line 26) | public static IGraphQLBuilder AddAuthorization(this IGraphQLBuilder bu...

FILE: src/GraphQL.Authorization/IAuthorizationEvaluator.cs
  type IAuthorizationEvaluator (line 8) | public interface IAuthorizationEvaluator
    method Evaluate (line 18) | Task<AuthorizationResult> Evaluate(

FILE: src/GraphQL.Authorization/IAuthorizationPolicy.cs
  type IAuthorizationPolicy (line 6) | public interface IAuthorizationPolicy

FILE: src/GraphQL.Authorization/Requirements/AuthenticatedUserRequirement.cs
  class AuthenticatedUserRequirement (line 7) | public class AuthenticatedUserRequirement : IAuthorizationRequirement
    method Authorize (line 12) | public Task Authorize(AuthorizationContext context)

FILE: src/GraphQL.Authorization/Requirements/ClaimAuthorizationRequirement.cs
  class ClaimAuthorizationRequirement (line 7) | public class ClaimAuthorizationRequirement : IAuthorizationRequirement
    method ClaimAuthorizationRequirement (line 13) | public ClaimAuthorizationRequirement(string claimType)
    method ClaimAuthorizationRequirement (line 23) | public ClaimAuthorizationRequirement(string claimType, IEnumerable<str...
    method ClaimAuthorizationRequirement (line 33) | public ClaimAuthorizationRequirement(string claimType, params string[]...
    method ClaimAuthorizationRequirement (line 45) | public ClaimAuthorizationRequirement(string claimType, IEnumerable<str...
    method Authorize (line 70) | public Task Authorize(AuthorizationContext context)

FILE: src/GraphQL.Authorization/Requirements/IAuthorizationRequirement.cs
  type IAuthorizationRequirement (line 7) | public interface IAuthorizationRequirement
    method Authorize (line 13) | Task Authorize(AuthorizationContext context);

FILE: src/Harness/GraphQL.cs
  class Query (line 6) | public class Query
    method Viewer (line 11) | [Authorize("AdminPolicy")]
    method Users (line 17) | public List<User> Users() => new() { new User { Id = Guid.NewGuid().To...
    method Guest (line 22) | public string Guest() => "guest42";
  class User (line 28) | public class User
Condensed preview — 57 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (124K chars).
[
  {
    "path": ".editorconfig",
    "chars": 14600,
    "preview": "# EditorConfig is awesome: http://EditorConfig.org\n\n# Create portable, custom editor settings with EditorConfig\n# https:"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 76,
    "preview": "# These are supported funding model platforms\n\nopen_collective: graphql-net\n"
  },
  {
    "path": ".github/codecov.yaml",
    "chars": 70,
    "preview": "# https://docs.codecov.com/docs/codecov-yaml\ncomment:\n  behavior: new\n"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 626,
    "preview": "# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabo"
  },
  {
    "path": ".github/labeler.yml",
    "chars": 259,
    "preview": "test:\n  - src/GraphQL.Authorization.Tests/**/*\n  - src/GraphQL.Authorization.ApiTests/**/*\n\nCI:\n  - .github/workflows/**"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 1358,
    "preview": "name: Build artifacts\n\n# ==== NOTE: do not rename this yml file or the run_number will be reset ====\n\non:\n  push:\n    br"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "chars": 1202,
    "preview": "# https://github.com/github/codeql\n# https://github.com/github/codeql-action\nname: CodeQL analysis\n\non:\n  push:\n    bran"
  },
  {
    "path": ".github/workflows/format.yml",
    "chars": 839,
    "preview": "name: Check formatting\n\non:\n  pull_request:\n    paths:\n      - src/**\n      - .github/workflows/**\n\nenv:\n  DOTNET_NOLOGO"
  },
  {
    "path": ".github/workflows/label.yml",
    "chars": 601,
    "preview": "# This workflow will triage pull requests and apply a label based on the\n# paths that are modified in the pull request.\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "chars": 2426,
    "preview": "name: Publish release\n\non:\n  release:\n    types:\n      - published\n\nenv:\n  DOTNET_NOLOGO: true\n  DOTNET_CLI_TELEMETRY_OP"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 2753,
    "preview": "name: Run code tests\n\non:\n  pull_request:\n    paths:\n      - src/**\n      - .github/workflows/**\n  # Upload code coverag"
  },
  {
    "path": ".github/workflows/wipcheck.yml",
    "chars": 686,
    "preview": "name: Check if PR title contains [WIP]\n\non:\n  pull_request:\n    types:\n      - opened        # when PR is opened\n      -"
  },
  {
    "path": ".gitignore",
    "chars": 78,
    "preview": "*.DS_Store\n\n.vs/\n.idea/\n*.user\n*.suo\n*.nupkg\n\n[Oo]bj/\n[Bb]in/\n\n*.received.txt\n"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 1884,
    "preview": "{\n  // Use IntelliSense to find out which attributes exist for C# debugging\n  // Use hover for the description of the ex"
  },
  {
    "path": ".vscode/tasks.json",
    "chars": 670,
    "preview": "{\n    \"version\": \"2.0.0\",\n    \"tasks\": [\n        {\n            \"label\": \"build-harness\",\n            \"command\": \"dotnet\""
  },
  {
    "path": "LICENSE.md",
    "chars": 1084,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2017 Joseph T. McBride\n\nPermission is hereby granted, free of charge, to any person"
  },
  {
    "path": "README.md",
    "chars": 5286,
    "preview": "# GraphQL Authorization\n\n[![License](https://img.shields.io/github/license/graphql-dotnet/authorization)](LICENSE.md)\n[!"
  },
  {
    "path": "codeql/GraphQL.Authorization.CodeQL.sln",
    "chars": 1149,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.0.3191"
  },
  {
    "path": "src/BasicSample/BasicSample.csproj",
    "chars": 674,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</Targe"
  },
  {
    "path": "src/BasicSample/Program.cs",
    "chars": 1555,
    "preview": "using System.Security.Claims;\nusing GraphQL;\nusing GraphQL.SystemTextJson;\nusing GraphQL.Types;\nusing GraphQL.Validation"
  },
  {
    "path": "src/Directory.Build.props",
    "chars": 1695,
    "preview": "<Project>\n\n  <PropertyGroup>\n    <VersionPrefix>8.0.0-preview</VersionPrefix>\n    <NextVersion>9.0.0</NextVersion>\n    <"
  },
  {
    "path": "src/Directory.Build.targets",
    "chars": 2250,
    "preview": "<Project>\n\n  <PropertyGroup Condition=\"'$(IsPackable)' == 'true'\">\n    <PackageReadmeFile>README.md</PackageReadmeFile>\n"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationContext.cs",
    "chars": 1213,
    "preview": "using System.Security.Claims;\n\nnamespace GraphQL.Authorization;\n\n/// <summary>\n/// Provides context information for <see"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationEvaluator.cs",
    "chars": 1894,
    "preview": "using System.Security.Claims;\n\nnamespace GraphQL.Authorization;\n\n/// <summary>\n/// Default implementation of <see cref=\""
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationPolicy.cs",
    "chars": 978,
    "preview": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Default implementation for <see cref=\"IAuthorizationPolicy\"/>.\n/// <"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationPolicyBuilder.cs",
    "chars": 3076,
    "preview": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Configures and then builds authorization policy from various authori"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationResult.cs",
    "chars": 1168,
    "preview": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Represents the result of an authorization evaluation.\n/// </summary>"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationSettings.cs",
    "chars": 2521,
    "preview": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Authorization settings are represented by a set of named policies\n//"
  },
  {
    "path": "src/GraphQL.Authorization/AuthorizationValidationRule.cs",
    "chars": 5408,
    "preview": "using GraphQL.Types;\nusing GraphQL.Validation;\nusing GraphQLParser.AST;\n\nnamespace GraphQL.Authorization;\n\n/// <summary>"
  },
  {
    "path": "src/GraphQL.Authorization/Extensions/AuthorizationGraphQLBuilderExtensions.cs",
    "chars": 1643,
    "preview": "using GraphQL.Authorization;\nusing GraphQL.DI;\n\nnamespace GraphQL;\n\n/// <summary>\n/// Authorization extension methods fo"
  },
  {
    "path": "src/GraphQL.Authorization/GraphQL.Authorization.csproj",
    "chars": 370,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <Descript"
  },
  {
    "path": "src/GraphQL.Authorization/IAuthorizationEvaluator.cs",
    "chars": 863,
    "preview": "using System.Security.Claims;\n\nnamespace GraphQL.Authorization;\n\n/// <summary>\n/// Interface to evaluate the authorizati"
  },
  {
    "path": "src/GraphQL.Authorization/IAuthorizationPolicy.cs",
    "chars": 326,
    "preview": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Policy is a named set of <see cref=\"IAuthorizationRequirement\"/>.\n//"
  },
  {
    "path": "src/GraphQL.Authorization/Requirements/AuthenticatedUserRequirement.cs",
    "chars": 685,
    "preview": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Implements an <see cref=\"IAuthorizationRequirement\"/> which requires"
  },
  {
    "path": "src/GraphQL.Authorization/Requirements/ClaimAuthorizationRequirement.cs",
    "chars": 4008,
    "preview": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Implements an <see cref=\"IAuthorizationRequirement\"/> which requires"
  },
  {
    "path": "src/GraphQL.Authorization/Requirements/IAuthorizationRequirement.cs",
    "chars": 461,
    "preview": "namespace GraphQL.Authorization;\n\n/// <summary>\n/// Represents an authorization requirement.\n/// One of the requirements"
  },
  {
    "path": "src/GraphQL.Authorization.ApiTests/ApiApprovalTests.cs",
    "chars": 1072,
    "preview": "using PublicApiGenerator;\n\nnamespace GraphQL.Authorization.ApiTests;\n\n/// <summary>\n/// See more info about API approval"
  },
  {
    "path": "src/GraphQL.Authorization.ApiTests/GraphQL.Authorization.ApiTests.csproj",
    "chars": 388,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <Import Project=\"../Tests.props\" />\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</"
  },
  {
    "path": "src/GraphQL.Authorization.ApiTests/GraphQL.Authorization.approved.txt",
    "chars": 6079,
    "preview": "namespace GraphQL.Authorization\n{\n    public class AuthenticatedUserRequirement : GraphQL.Authorization.IAuthorizationRe"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/AuthenticatedUserRequirementTests.cs",
    "chars": 905,
    "preview": "namespace GraphQL.Authorization.Tests;\n\npublic class AuthenticatedUserRequirementTests\n{\n    [Fact]\n    public async Tas"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/AuthorizationEvaluatorTests.cs",
    "chars": 3888,
    "preview": "namespace GraphQL.Authorization.Tests;\n\npublic class AuthorizationEvaluatorTests\n{\n    private readonly AuthorizationEva"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/AuthorizationSchemaBuilderTests.cs",
    "chars": 1124,
    "preview": "using GraphQL.Types;\n\nnamespace GraphQL.Authorization.Tests;\n\npublic class AuthorizationSchemaBuilderTests\n{\n    [Fact]\n"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/AuthorizationSettingsTests.cs",
    "chars": 574,
    "preview": "namespace GraphQL.Authorization.Tests;\n\npublic class AuthorizationSettingsTests\n{\n    private readonly AuthorizationSett"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/AuthorizationValidationRuleTests.cs",
    "chars": 13983,
    "preview": "using GraphQL.Types;\nusing GraphQL.Types.Relay.DataObjects;\n\nnamespace GraphQL.Authorization.Tests;\n\npublic class Author"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/ClaimAuthorizationRequirementTests.cs",
    "chars": 2949,
    "preview": "namespace GraphQL.Authorization.Tests;\n\npublic class ClaimAuthorizationRequirementTests\n{\n    [Fact]\n    public async Ta"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/GraphQL.Authorization.Tests.csproj",
    "chars": 694,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <Import Project=\"../Tests.props\" />\n\n  <PropertyGroup Condition=\"'$(SingleTestPlatfo"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/ValidationTestBase.cs",
    "chars": 2726,
    "preview": "using System.Security.Claims;\nusing GraphQL.Execution;\nusing GraphQL.Validation;\nusing GraphQLParser;\n\nnamespace GraphQL"
  },
  {
    "path": "src/GraphQL.Authorization.Tests/ValidationTestConfig.cs",
    "chars": 529,
    "preview": "using System.Security.Claims;\nusing GraphQL.Types;\nusing GraphQL.Validation;\n\nnamespace GraphQL.Authorization.Tests;\n\npu"
  },
  {
    "path": "src/GraphQL.Authorization.sln",
    "chars": 8649,
    "preview": "Microsoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.4.33205."
  },
  {
    "path": "src/Harness/GraphQL.cs",
    "chars": 993,
    "preview": "namespace GraphQL;\n\n/// <summary>\n/// CLR type to map to the 'Query' graph type.\n/// </summary>\npublic class Query\n{\n   "
  },
  {
    "path": "src/Harness/Harness.csproj",
    "chars": 808,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <Description>"
  },
  {
    "path": "src/Harness/Program.cs",
    "chars": 1571,
    "preview": "using GraphQL;\r\nusing GraphQL.Types;\r\nusing Microsoft.Extensions.DependencyInjection.Extensions;\r\n\r\nvar builder = WebApp"
  },
  {
    "path": "src/Harness/Properties/launchSettings.json",
    "chars": 560,
    "preview": "{\n  \"profiles\": {\n    \"Harness [GraphiQL]\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launch"
  },
  {
    "path": "src/Harness/appsettings.Development.json",
    "chars": 176,
    "preview": "{\r\n  \"Logging\": {\r\n    \"IncludeScopes\": false,\r\n    \"LogLevel\": {\r\n      \"Default\": \"Debug\",\r\n      \"System\": \"Informat"
  },
  {
    "path": "src/Harness/appsettings.json",
    "chars": 228,
    "preview": "{\r\n  \"Logging\": {\r\n    \"Debug\": {\r\n      \"LogLevel\": {\r\n        \"Default\": \"Warning\"\r\n      }\r\n    },\r\n    \"Console\": {"
  },
  {
    "path": "src/Tests.props",
    "chars": 1202,
    "preview": "<Project>\n  <Import Project=\"$(MSBuildThisFileDirectory)Tests.local.props\" Condition=\"Exists('$(MSBuildThisFileDirectory"
  },
  {
    "path": "src/xunit.runner.json",
    "chars": 139,
    "preview": "{\n  \"$schema\": \"https://xunit.net/schema/current/xunit.runner.schema.json\",\n  \"diagnosticMessages\": true,\n  \"longRunning"
  }
]

About this extraction

This page contains the full source code of the graphql-dotnet/authorization GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 57 files (113.0 KB), approximately 28.8k tokens, and a symbol index with 128 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!