-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathAuth.cs
More file actions
105 lines (89 loc) · 2.92 KB
/
Copy pathAuth.cs
File metadata and controls
105 lines (89 loc) · 2.92 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.
using Azure.Core;
using Azure.Identity;
namespace Microsoft.TypeChat;
public enum AzureTokenScopes
{
CogServices = 0 // You can assign specific integer values if needed
}
public class AzureTokenProvider : IApiTokenProvider, IDisposable
{
public const int DefaultExpirationBufferMs = 5 * 60 * 1000;
private static readonly AzureTokenProvider s_default;
static AzureTokenProvider()
{
s_default = new AzureTokenProvider(AzureTokenScopes.CogServices);
}
public static AzureTokenProvider Default
{
get { return s_default; }
}
private readonly TokenCredential _credential;
private readonly string[] _scopes;
private readonly int _expirationBufferMs;
private AccessToken _accessToken;
private SemaphoreSlim _lock;
public AzureTokenProvider(AzureTokenScopes scope, int expirationBufferMs = DefaultExpirationBufferMs)
: this(GetScopes(scope), expirationBufferMs)
{
}
public AzureTokenProvider(string[] scopes, int expirationBufferMs = DefaultExpirationBufferMs)
{
ArgumentVerify.ThrowIfNullOrEmpty(scopes, nameof(scopes));
_credential = new DefaultAzureCredential();
_scopes = scopes;
_expirationBufferMs = expirationBufferMs;
_lock = new SemaphoreSlim(1, 1);
}
public async Task<string> GetAccessTokenAsync(CancellationToken cancelToken)
{
if (_accessToken.ExpiresOn <= DateTimeOffset.UtcNow.AddMilliseconds(_expirationBufferMs))
{
return await RefreshTokenAsync(cancelToken).ConfigureAwait(false);
}
return _accessToken.Token;
}
public object GetCredential()
{
return _credential;
}
public async Task<string> RefreshTokenAsync(CancellationToken cancelToken)
{
await _lock.WaitAsync(cancelToken).ConfigureAwait(false);
try
{
_accessToken = await _credential.GetTokenAsync(new TokenRequestContext(_scopes), cancelToken).ConfigureAwait(false);
_accessToken = new AccessToken(_accessToken.Token, _accessToken.ExpiresOn.AddMilliseconds(-_expirationBufferMs));
return _accessToken.Token;
}
finally
{
_lock.Release();
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool fromDispose)
{
if (fromDispose)
{
_lock?.Dispose();
}
_lock = null;
}
private static string[] GetScopes(AzureTokenScopes scope)
{
switch (scope)
{
case AzureTokenScopes.CogServices:
return new string[] {
"https://cognitiveservices.azure.com/.default"
};
default:
throw new ArgumentOutOfRangeException(nameof(scope), "Unsupported Azure token scope.");
}
}
}