public override Func<IHubIncomingInvokerContext, Task<object>> BuildIncoming(Func<IHubIncomingInvokerContext, Task<object>> invoke)
{
return base.BuildIncoming(context =>
{
// Execute the global method invocation authorizer if there is one and short circuit if it denies authorization.
if (_globalInvocationAuthorizer == null || _globalInvocationAuthorizer.AuthorizeHubMethodInvocation(context, appliesToMethod: false))
{
// Get hub attributes implementing IAuthorizeHubMethodInvocation from the cache
// If the attributes do not exist in the cache, retrieve them using reflection and add them to the cache
var classLevelAuthorizers = _classInvocationAuthorizersCache.GetOrAdd(context.Hub.GetType(),
hubType => hubType.GetTypeInfo().GetCustomAttributes().OfType<IAuthorizeHubMethodInvocation>());
// Execute all hub level authorizers and short circuit if ANY deny authorization.
if (classLevelAuthorizers.All(a => a.AuthorizeHubMethodInvocation(context, appliesToMethod: false)))
{
// If the MethodDescriptor is a NullMethodDescriptor, we don't want to cache it since a new one is created
// for each invocation with an invalid method name. #1801
if (context.MethodDescriptor is NullMethodDescriptor)
{
return invoke(context);
}
// Get method attributes implementing IAuthorizeHubMethodInvocation from the cache
// If the attributes do not exist in the cache, retrieve them from the MethodDescriptor and add them to the cache
var methodLevelAuthorizers = _methodInvocationAuthorizersCache.GetOrAdd(context.MethodDescriptor,
methodDescriptor => methodDescriptor.Attributes.OfType<IAuthorizeHubMethodInvocation>());
// Execute all method level authorizers. If ALL provide authorization, continue executing the invocation pipeline.
if (methodLevelAuthorizers.All(a => a.AuthorizeHubMethodInvocation(context, appliesToMethod: true)))
{
return invoke(context);
}
}
}
// Send error back to the client
return TaskAsyncHelper.FromError<object>(
new NotAuthorizedException(String.Format(CultureInfo.CurrentCulture, Resources.Error_CallerNotAuthorizedToInvokeMethodOn,
context.MethodDescriptor.Name,
context.MethodDescriptor.Hub.Name)));
});
}
}