Code Monkey home page Code Monkey logo

Comments (10)

mlynam avatar mlynam commented on July 18, 2024 1

I was able to setup Subscription auth using built in elements alone. If you are interested @jonmill I can give you my method.

from authorization.

mlynam avatar mlynam commented on July 18, 2024 1

Sure.

The main issue I ran into with authorization and graphql-dotnet is the inconsistent handling of the user context. In graphql-dotnet proper, we are told to implement a Dictionary<string,object> and here in authorization we are told to implement an IProvideClaimsPrincipal. After digging through the source I discovered that really it should be the same implementation for both types as the validator here in authorization casts the user context to an IProvideClaimsPrincipal before authorizing. It does work when the GraphQLMiddleware sets up the execution context because that middleware invokes the BuildUserContext method. The GraphQLWebSocketMiddleware does not invoke this method and instead sends a MessageHandlingContext to the executor. Due to this, whatever authenticate pipeline we setup in native AspNetCore is ignored completely by the authorizing validator here in authorization.

I know this preamble was long but bear with me because it explains this next part: I'm not using the authorization repo for the authorization. I dug through the graphql-dotnet repositories and found a namespace tucked away in the server repository: Authorization.AspNetCore. This repository has very similar code to what exists here in the authorization repo except that its authorization validator uses the IHttpContextAccessor to find the actual AspNetCore user context (I believe this makes way more sense than having an arbitrary Dictionary<string,object> provider for user context. This validator works for whichever GraphQL middleware is currently executing the result. The error handling is a little dry in the server repo but it really doesn't matter to me because it properly leverages the well written Microsoft Authorization types.

The final step here is how to actually handle the token during a websocket request. Obviously we cannot pass it through the headers as browsers do not allow header values beyond web socket protocol. In my case, I'm sending the access token as a query param and then using a message event handler in my JWT config to set the token during a websocket request. Here's startup psuedocode that should work for you.

public void ConfigureServices(IServiceCollection services)
{
      services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
          options.Authority = "some authority";
          options.Audience = "some audience";

          options.TokenValidationParameters = new TokenValidationParameters
          {
            NameClaimType = ClaimTypes.NameIdentifier
          };

          options.Events = new JwtBearerEvents
          {
            OnMessageReceived = context =>
            {
              if (context.Request.Query.TryGetValue("access_token", out StringValues queryToken) &&
                  context.Request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
              {
                context.Token = queryToken.Single();
              }

              return Task.CompletedTask;
            }
          };
        });

      // Add schema types...

      services.AddGraphQL()
        .AddGraphQLAuthorization()
        .AddWebSockets();
}

public void Configure(IApplicationBuilder builder)
{
      builder.UseAuthentication();
      builder.UseWebsockets();
      builder.UseGraphQLWebsockets<Schema>();
      builder.UseGraphQL<Schema>();
}

I can probably put together a sample repo a little later on.

from authorization.

jonmill avatar jonmill commented on July 18, 2024

@joemcbride any ideas here? :)

from authorization.

bioharz avatar bioharz commented on July 18, 2024

same issue

from authorization.

jonmill avatar jonmill commented on July 18, 2024

I ended up switching away from the built in provider and rolled my own in order to work with Subscriptions and Queries / Mutations

from authorization.

OpenSpacesAndPlaces avatar OpenSpacesAndPlaces commented on July 18, 2024

It's not directly supported from what I've seen - from previous dicussions on the topic, auth is expected to more/less be your own custom coding.

Ideally you're running this under a WebAPI controller - so JWT should already be negotiated to the context.

For usage you'd do like:

settings.AddPolicy(AuthConstants.ADMIN_POLICY, _ => { _.AddRequirement(new RoleAuthorizationRequirement(UserRoles.Administrator)); });
....
ExecutionResult result = await _executer.ExecuteAsync(_ =>
{
...
_.UserContext = HttpContext.Current
...
}

....
public class RoleAuthorizationRequirement : IAuthorizationRequirement
...
public RoleAuthorizationRequirement(params string[] roles)
....
public Task Authorize(AuthorizationContext ac)
....
HttpContext ctx = (HttpContext)ac.UserContext;

if (ctx == null || ctx.User == null || ctx.User.Identity == null ||String.IsNullOrEmpty(ctx.User.Identity.Name))
 throw;
...
Do lookups with - ctx.User.Identity.Name

from authorization.

OpenSpacesAndPlaces avatar OpenSpacesAndPlaces commented on July 18, 2024

Also keep in mind, "UserContext" can be anything you want.

from authorization.

sungam3r avatar sungam3r commented on July 18, 2024

@jonmill Is this issue still actual for you?

from authorization.

jonmill avatar jonmill commented on July 18, 2024

@sungam3r it would be nice if there was a way that this was built-in, instead of having to roll-your-own auth...but no, I have moved on from this issue and done auth myself

from authorization.

bioharz avatar bioharz commented on July 18, 2024

@mlynam May I ask if you would share the snipped to anyone? Thank you very much @mlynam

from authorization.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.