-
Notifications
You must be signed in to change notification settings - Fork 383
Expand file tree
/
Copy pathAzureSignalR.cs
More file actions
105 lines (88 loc) · 4.02 KB
/
AzureSignalR.cs
File metadata and controls
105 lines (88 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace RealtimeSignIn
{
class AzureSignalR
{
class PayloadMessage
{
public string Target { get; set; }
public object[] Arguments { get; set; }
}
private readonly string endpoint;
private readonly string accessKey;
private readonly HttpClient httpClient = new HttpClient();
private readonly JwtSecurityTokenHandler jwtTokenHandler = new JwtSecurityTokenHandler();
private static void ParseConnectionString(string connectionString, out string endpoint, out string accessKey)
{
var dict = connectionString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Split(new[] { '=' }, 2)).ToDictionary(p => p[0].Trim().ToLower(), p => p[1].Trim());
if (!dict.TryGetValue("endpoint", out endpoint)) throw new ArgumentException("Invalid connection string, missing endpoint.");
if (!dict.TryGetValue("accesskey", out accessKey)) throw new ArgumentException("Invalid connection string, missing access key.");
}
private string GenerateJwtBearer(string issuer, string audience, ClaimsIdentity subject, DateTime? expires, string signingKey)
{
SigningCredentials credentials = null;
if (!string.IsNullOrEmpty(signingKey))
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(signingKey));
credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
}
var token = jwtTokenHandler.CreateJwtSecurityToken(
issuer: issuer,
audience: audience,
subject: subject,
expires: expires,
signingCredentials: credentials);
return jwtTokenHandler.WriteToken(token);
}
private Task<HttpResponseMessage> PostJsonAsync(string url, object body, string bearer)
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(url)
};
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", bearer);
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.AcceptCharset.Clear();
request.Headers.AcceptCharset.Add(new StringWithQualityHeaderValue("UTF-8"));
var content = JsonConvert.SerializeObject(body);
request.Content = new StringContent(content, Encoding.UTF8, "application/json");
return httpClient.SendAsync(request);
}
public AzureSignalR(string connectionString)
{
ParseConnectionString(connectionString, out endpoint, out accessKey);
}
public async Task SendAsync(string hubName, string methodName, params object[] args)
{
var payload = new PayloadMessage()
{
Target = methodName,
Arguments = args
};
var url = $"{endpoint}/api/v1/hubs/{hubName}";
var bearer = GenerateJwtBearer(null, url, null, DateTime.UtcNow.AddMinutes(30), accessKey);
await PostJsonAsync(url, payload, bearer);
}
public string GetClientHubUrl(string hubName)
{
return $"{endpoint}/client/?hub={hubName}";
}
public string GenerateAccessToken(string hubName)
{
return GenerateJwtBearer(null, GetClientHubUrl(hubName), null, DateTime.UtcNow.AddMinutes(30), accessKey);
}
}
}