graphql-platform icon indicating copy to clipboard operation
graphql-platform copied to clipboard

Discrepancy between HotChocolate and AspNetCore Authorization

Open TomaszCypser opened this issue 2 years ago • 1 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Product

Hot Chocolate

Describe the bug

I believe that I have found a behavior discrepancy between HotChocolate and AspNetCore Authorization, when using it with AWS Lambda and API Gateway with a Lambda authorizer.

After passing the Lambda Authorizer, in case if an invalid/expired or no token is provided, the HttpContext.User has a different structure than when running the service locally or without lambda authorizer. This structure is as follows:

{
    "Claims": [
        {
            "Issuer": "LOCAL AUTHORITY",
            "OriginalIssuer": "LOCAL AUTHORITY",
            "Properties": {},
            "Subject": {
                "AuthenticationType": "AuthorizerIdentity",
                "IsAuthenticated": true,
                "Actor": null,
                "BootstrapContext": null,
                "Claims": [
                    null
                ],
                "Label": null,
                "Name": null,
                "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
                "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
            },
            "Type": "integrationLatency",
            "Value": "42",
            "ValueType": "http://www.w3.org/2001/XMLSchema#string"
        }
    ],
    "Identities": [
        {
            "AuthenticationType": "AuthorizerIdentity",
            "IsAuthenticated": true,
            "Actor": null,
            "BootstrapContext": null,
            "Claims": [
                {
                    "Issuer": "LOCAL AUTHORITY",
                    "OriginalIssuer": "LOCAL AUTHORITY",
                    "Properties": {},
                    "Subject": null,
                    "Type": "integrationLatency",
                    "Value": "42",
                    "ValueType": "http://www.w3.org/2001/XMLSchema#string"
                }
            ],
            "Label": null,
            "Name": null,
            "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
            "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
        }
    ],
    "Identity": {
        "Name": null,
        "AuthenticationType": "AuthorizerIdentity",
        "IsAuthenticated": true
    }
}

This structure that is present locally or without lambda authorizer:

{
    "Claims": [],
    "Identities": [
        {
            "AuthenticationType": null,
            "IsAuthenticated": false,
            "Actor": null,
            "BootstrapContext": null,
            "Claims": [],
            "Label": null,
            "Name": null,
            "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
            "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
        }
    ],
    "Identity": {
        "Name": null,
        "AuthenticationType": null,
        "IsAuthenticated": false
    }
}

The discrepancy between HotChocolate and AspNetCore Authorization is that a particular claim passes the authorization in HotChocolate, while the AspNetCore Authorization handler fails it.

As a workaround, I have implemented my own DefaultHttpRequestInterceptor that checks whether the HttpContext.User has the above structure and, if so, overwrites it with the one that is present by default locally or when the lambda authorizer is not present.

Could you please tell me if I am misunderstanding what is happening or perhaps misconfigured something? Here is a minimal example of how the service is setup click

Steps to reproduce

  1. Create an AWS Lambda with that uses HotChocolate with @authorize directive and API Gateway with a Lambda authorizer.
  2. Call query that uses @authorize directive with invalid token

Expected result:

Service responds with message like

{
  "errors": [
    {
      "message": "The current user is not authorized to access this resource.",
      "extensions": {
        "code": "AUTH_NOT_AUTHORIZED"
      }
    }
  ]
}

Actual result:

Service responds as if the query would not require authorization.

Relevant log output

No response

Additional Context?

No response

Version

13.0.5

TomaszCypser avatar Apr 06 '23 20:04 TomaszCypser

Actually, we will internally just call the ASP.NET core authorization. But we do not authenticate the schemes. Thats the thing you have to do in the request interceptor. context.AuthenticateAsync("scheme")

michaelstaib avatar May 14 '23 07:05 michaelstaib