📄
src/Integrations/Vasttrafik/OAuth2Handler.cs
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
using System; using System.IdentityModel.Tokens.Jwt; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Http.Json; using System.Text; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; namespace MMirror.Integrations.Vasttrafik; internal sealed class OAuth2Handler(IOptions<ClientOptions> options, IMemoryCache memoryCache, HttpClient httpClient) : DelegatingHandler { private readonly string id = options.Value.ClientId; private readonly string secret = options.Value.ClientSecret; protected override async Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken ) { request.Headers.Authorization = await GetAuthorization(); return await base.SendAsync(request, cancellationToken); } private async Task<AuthenticationHeaderValue> GetAuthorization() => (await memoryCache.GetOrCreateAsync("VasttrafikAuthorization", GetToken))!; private async Task<AuthenticationHeaderValue> GetToken(ICacheEntry cacheEntry) { var request = new HttpRequestMessage(HttpMethod.Post, "/token") { Headers = { Authorization = new("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{id}:{secret}"))), }, Content = new FormUrlEncodedContent([new("grant_type", "client_credentials")]), }; var authResponse = await httpClient.SendAsync(request); var token = await authResponse.Content.ReadFromJsonAsync(OAuth2JsonSerializerContext.Default.OAuth2TokenResponse) ?? throw new Exception("Parsed literal null from Vasttrafik token endpoint."); var jwtHandler = new JwtSecurityTokenHandler(); var jwt = jwtHandler.ReadJwtToken(token.AccessToken); cacheEntry.AbsoluteExpiration = jwt.ValidTo; return new("Bearer", token.AccessToken); } } [JsonSerializable(typeof(OAuth2TokenResponse))] internal sealed partial class OAuth2JsonSerializerContext : JsonSerializerContext; internal sealed record OAuth2TokenResponse([property: JsonPropertyName("access_token")] string AccessToken);