Beispiel #1
0
        public async Task <IActionResult> Negotiate(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "messaging/negotiate")] HttpRequest req,
            IBinder binder)
        {
            string userId = req.Headers["X-User-Id"];

            if (!Guid.TryParse(userId, out Guid userIdGuid))
            {
                _logger.LogError($"User call to /negotiate did not include a valid GUID in the header. We found '{userId}' in the X-User-Id header.");
                return(new BadRequestResult());
            }

            // Force override of the SignalR user ID.
            // Normally this method would be decorated with a [SignalRConnectionInfo] attribute, which would be
            // where we could set the UserId attribute by using function dot-binding, i.e. UserId = "{headers.x-user-id}".
            // Unfortunately, the only headers visible to the function seem to be the Azure Auth-based claims headers,
            // and we're sending up a custom user ID.
            // So instead, we short-circuit the normal binding process, forcibly create our own binding attribute by hand,
            // at a point in time where we have access to our user ID, and then tell the binder to use that instead.
            SignalRConnectionInfoAttribute attribute = new SignalRConnectionInfoAttribute
            {
                HubName = Constants.ChatHubName,
                UserId  = userIdGuid.ToIdString(),
            };
            SignalRConnectionInfo info = await binder.BindAsync <SignalRConnectionInfo>(attribute);

            return(new OkObjectResult(info));
        }
        public SignalRConnectionInfo GetClientConnectionInfo(SignalRConnectionInfoAttribute attribute)
        {
            IEnumerable <Claim> claims1 = attribute.GetClaims();
            string hubName = attribute.HubName;
            IEnumerable <Claim> claims2 = claims1;

            return(GetClientConnectionInfo(hubName, claims2));
        }
        public static IEnumerable <Claim> GetClaims(this SignalRConnectionInfoAttribute attribute)
        {
            List <Claim> claimList = new List <Claim>();

            if (!string.IsNullOrEmpty(attribute.UserId))
            {
                claimList.Add(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", attribute.UserId));
            }
            return((IEnumerable <Claim>)claimList);
        }
        public void GetClaims_WithUserId_ReturnsUserIdInClaims()
        {
            var attr = new SignalRConnectionInfoAttribute
            {
                UserId = "foo"
            };

            var claims = attr.GetClaims();

            Assert.Contains(claims, c => c.Type == ClaimTypes.NameIdentifier && c.Value == "foo");
        }
        public void GetClaims_WithNoUserId_ReturnsEmptyClaims()
        {
            var attr = new SignalRConnectionInfoAttribute
            {
                UserId = null
            };

            var claims = attr.GetClaims();

            Assert.Empty(claims);
        }
Beispiel #6
0
        public static async Task <SignalRConnectionInfo> Negotiate(
            [HttpTrigger(AuthorizationLevel.Anonymous)]
            HttpRequest req, IBinder binder)
        {
            var userId = req.Query["oid"];

            if (string.IsNullOrEmpty(userId))
            {
                return(null);
            }

            var attribute = new SignalRConnectionInfoAttribute
            {
                HubName = "chat",
                UserId  = userId
            };

            return(await binder.BindAsync <SignalRConnectionInfo>(attribute).ConfigureAwait(false));
        }
Beispiel #7
0
        public static async Task <SignalRConnectionInfo> GetSignalRInfo2(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", "get")] HttpRequest req,
            IBinder binder, ILogger log)
        {
            string hub    = "billtedRoom";
            string userId = req.Query["user"];

            SignalRConnectionInfoAttribute attribute = new SignalRConnectionInfoAttribute
            {
                HubName = hub,
                UserId  = userId
            };

            // This style is an example of imperative attribute binding; the mechanism for declarative binding described below does not work
            // UserId = "{headers.x-my-custom-header}" https://docs.microsoft.com/en-us/azure/azure-signalr/signalr-concept-serverless-development-config
            SignalRConnectionInfo connection = await binder.BindAsync <SignalRConnectionInfo>(attribute);

            return(connection);
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
            IBinder binder)
        // [SignalRConnectionInfo(HubName = Constants.SignalRTasksHubName, ConnectionStringSetting = Constants.SignalRConnectionStringSetting)] SignalRConnectionInfo connectionInfo)
        {
            SignalRConnectionInfoAttribute attribute = new SignalRConnectionInfoAttribute
            {
                HubName = Constants.SignalRTasksHubName,
                ConnectionStringSetting = Constants.SignalRConnectionStringSetting,
                // Use random user id for anonymous usage
                UserId = $"userid:{Guid.NewGuid().ToString()}"
                         // UserId = "myUserId"
            };


            // This style is an example of imperative attribute binding; the mechanism for declarative binding described below does not work
            // UserId = "{headers.x-my-custom-header}" https://docs.microsoft.com/en-us/azure/azure-signalr/signalr-concept-serverless-development-config
            SignalRConnectionInfo connectionInfo = await binder.BindAsync <SignalRConnectionInfo>(attribute);

            return(new OkObjectResult(connectionInfo));
        }
Beispiel #9
0
        public static async Task <SignalRConnectionInfo> GetSignalRInfo(
            [HttpTrigger(AuthorizationLevel.Function, "post")] string request,
            Binder binder,
            ILogger log)
        {
            log.LogInformation($"GetSignalRConnection: Received request: {request}.");

            // We need to extract the Entity Id from the context. The entity id is going to be used as the SignalR user id associated with the caller's connection.
            var context = JsonConvert.DeserializeObject <FunctionExecutionContext <object> >(request);

            log.LogInformation($"Creating PubSub subscription for user {context.CallerEntityProfile.Entity.Id}.");

            // In Azure Functions, the SignalR connection is normally created through an input binding attribute. Here, because we need to specify the user id dynamically,
            // we're going to manually create the attribute and then use it to mint connection info.
            // The connection string to use is pulled from the AzureSignalRConnectionString setting by default.
            var signalRConnectionAttribute = new SignalRConnectionInfoAttribute()
            {
                HubName = "PubSub", UserId = context.CallerEntityProfile.Entity.Id
            };

            return(await binder.BindAsync <SignalRConnectionInfo>(signalRConnectionAttribute));
        }