-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTokenAuthenticationProvider.cs
99 lines (81 loc) · 3.57 KB
/
TokenAuthenticationProvider.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
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
using Microsoft.Graph;
using System.Net.Http.Headers;
using System.Text.Json;
namespace TeacherAI;
public class TokenAuthenticationProvider : IAuthenticationProvider
{
public static string AuthRedirectUrl =>
$"https://login.microsoftonline.com/{_tenantId}/oauth2/v2.0/authorize?client_id={_clientId}&prompt=consent&redirect_uri={Uri.EscapeDataString(_redirectUri)}&response_type=code" +
$"&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read%20https%3A%2F%2Fgraph.microsoft.com%2Ffiles.readwrite.all";
private static string _accessToken;
private static DateTime _expirationTime;
private static string _tenantId;
private static string _clientId;
private static string _clientSecret;
private static string _redirectUri;
private static string _refreshToken;
private static readonly SemaphoreSlim _semaphore = new(1);
public static void Configure(string tenantId, string clientId, string clientSecret, string refreshToken)
{
_tenantId = tenantId;
_clientId = clientId;
_clientSecret = clientSecret;
_redirectUri = $"https://{Organisation.Instance.AppWebsite}/auth/authorise-service-account/done";
_refreshToken = refreshToken;
}
public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
ArgumentNullException.ThrowIfNull(request);
await _semaphore.WaitAsync();
try
{
if (DateTime.UtcNow.AddMinutes(5) >= _expirationTime) await GetNewAccessTokenAsync();
}
finally
{
_semaphore.Release();
}
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken);
}
private static async Task GetNewAccessTokenAsync()
{
using var client = new HttpClient();
var postData = new List<KeyValuePair<string, string>>()
{
new("client_id", _clientId),
new("scope", "Files.ReadWrite.All offline_access"),
new("refresh_token", _refreshToken),
new("grant_type", "refresh_token"),
new("client_secret", _clientSecret),
new("redirect_uri", _redirectUri)
};
using var content = new FormUrlEncodedContent(postData);
var response = await client.PostAsync($"https://login.microsoftonline.com/{_tenantId}/oauth2/v2.0/token", content);
using var dataStream = await response.Content.ReadAsStreamAsync();
using var reader = new StreamReader(dataStream);
var responseFromServer = await reader.ReadToEndAsync();
var jsonDoc = JsonDocument.Parse(responseFromServer);
_accessToken = jsonDoc.RootElement.GetProperty("access_token").GetString();
_expirationTime = DateTime.UtcNow.AddSeconds(jsonDoc.RootElement.GetProperty("expires_in").GetInt32());
}
public static async Task<string> GetRefreshTokenAsync(string code)
{
using var client = new HttpClient();
var postData = new List<KeyValuePair<string, string>>()
{
new("client_id", _clientId),
new("scope", "Files.ReadWrite.All offline_access"),
new("code", code),
new("grant_type", "authorization_code"),
new("client_secret", _clientSecret),
new("redirect_uri", _redirectUri)
};
using var content = new FormUrlEncodedContent(postData);
var response = await client.PostAsync($"https://login.microsoftonline.com/{_tenantId}/oauth2/v2.0/token", content);
using var dataStream = await response.Content.ReadAsStreamAsync();
using var reader = new StreamReader(dataStream);
var responseFromServer = await reader.ReadToEndAsync();
var jsonDoc = JsonDocument.Parse(responseFromServer);
return jsonDoc.RootElement.GetProperty("refresh_token").GetString();
}
}