This repository was archived by the owner on Aug 29, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathAuthenticationServiceFactory.cs
More file actions
152 lines (136 loc) · 8.15 KB
/
Copy pathAuthenticationServiceFactory.cs
File metadata and controls
152 lines (136 loc) · 8.15 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using Azure.Core;
using Azure.Identity;
using Microsoft.Graph.Cli.Core.Configuration;
using Microsoft.Graph.Cli.Core.IO;
using Microsoft.Graph.Cli.Core.Utils;
using System;
using System.Threading;
using System.Threading.Tasks;
#if OS_WINDOWS
using System.Diagnostics;
using Azure.Identity.Broker;
using Microsoft.Graph.Cli.Core.utils;
#endif
namespace Microsoft.Graph.Cli.Core.Authentication;
/// <summary>
/// Creates authentication services based on a strategy.
/// </summary>
public class AuthenticationServiceFactory
{
private readonly IPathUtility pathUtility;
private readonly IAuthenticationCacheManager authenticationCacheManager;
private readonly AuthenticationOptions? authenticationOptions;
/// <summary>
/// Creates a new authentication service factory instance
/// </summary>
/// <param name="pathUtility">Path utility</param>
/// <param name="authenticationCacheManager">Cache manager.</param>
/// <param name="authenticationOptions">Authentication options.</param>
public AuthenticationServiceFactory(IPathUtility pathUtility, IAuthenticationCacheManager authenticationCacheManager, AuthenticationOptions? authenticationOptions)
{
this.pathUtility = pathUtility;
this.authenticationOptions = authenticationOptions;
this.authenticationCacheManager = authenticationCacheManager;
}
/// <summary>
/// Returns a login service that satisfies the provided authentication strategy.
/// </summary>
/// <param name="strategy">Authentication strategy.</param>
/// <param name="tenantId">Tenant Id</param>
/// <param name="clientId">Client Id</param>
/// <param name="certificateName">Certificate name</param>
/// <param name="certificateThumbPrint">Certificate thumb-print</param>
/// <param name="environment">The national cloud environment. Either 'Global', 'US_GOV', 'US_GOV_DOD' or 'China'</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Returns a login service instance.</returns>
/// <exception cref="InvalidOperationException">When an unsupported authentication strategy is provided.</exception>
public virtual async Task<LoginServiceBase> GetAuthenticationServiceAsync(AuthenticationStrategy strategy, string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint, CloudEnvironment environment, CancellationToken cancellationToken = default)
{
var credential = await GetTokenCredentialAsync(strategy, tenantId, clientId, certificateName, certificateThumbPrint, environment, cancellationToken);
if (strategy == AuthenticationStrategy.DeviceCode && credential is DeviceCodeCredential deviceCred)
{
return new InteractiveLoginService<DeviceCodeCredential>(deviceCred, pathUtility);
}
else if (strategy == AuthenticationStrategy.InteractiveBrowser && credential is InteractiveBrowserCredential browserCred)
{
return new InteractiveLoginService<InteractiveBrowserCredential>(browserCred, pathUtility);
}
else if (strategy == AuthenticationStrategy.ClientCertificate && credential is ClientCertificateCredential)
{
return new AppOnlyLoginService<ClientCertificateCredential>(pathUtility);
}
else if (strategy == AuthenticationStrategy.ManagedIdentity && credential is ManagedIdentityCredential)
{
return new AppOnlyLoginService<ManagedIdentityCredential>(pathUtility);
}
else if (strategy == AuthenticationStrategy.Environment && credential is EnvironmentCredential)
{
return new AppOnlyLoginService<EnvironmentCredential>(pathUtility);
}
else
{
throw new InvalidOperationException($"The authentication strategy {strategy} is not supported");
}
}
/// <summary>
/// Returns a credential object instance that satisfies the provided authentication strategy
/// </summary>
/// <param name="strategy">Authentication strategy.</param>
/// <param name="tenantId">Tenant Id</param>
/// <param name="clientId">Client Id</param>
/// <param name="certificateName">Certificate name</param>
/// <param name="certificateThumbPrint">Certificate thumb-print</param>
/// <param name="environment">The cloud environment. <see cref="CloudEnvironment"/></param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A token credential instance.</returns>
/// <exception cref="InvalidOperationException">When an unsupported authentication strategy is provided.</exception>
/// <exception cref="ArgumentNullException">When a null url is provided for the authority host.</exception>
public virtual async Task<TokenCredential> GetTokenCredentialAsync(AuthenticationStrategy strategy, string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint, CloudEnvironment environment, CancellationToken cancellationToken = default)
{
var authorityHost = environment.Authority();
return strategy switch
{
AuthenticationStrategy.DeviceCode => await GetDeviceCodeCredentialAsync(tenantId, clientId, authorityHost, cancellationToken),
AuthenticationStrategy.InteractiveBrowser => await GetInteractiveBrowserCredentialAsync(tenantId, clientId, authorityHost, cancellationToken),
AuthenticationStrategy.ClientCertificate => GetClientCertificateCredential(tenantId, clientId, certificateName, certificateThumbPrint, authorityHost),
AuthenticationStrategy.Environment => new EnvironmentCredential(tenantId, clientId, new TokenCredentialOptions { AuthorityHost = authorityHost }),
AuthenticationStrategy.ManagedIdentity => new ManagedIdentityCredential(clientId, new TokenCredentialOptions { AuthorityHost = authorityHost }),
_ => throw new InvalidOperationException($"The authentication strategy {strategy} is not supported"),
};
}
private async Task<DeviceCodeCredential> GetDeviceCodeCredentialAsync(string? tenantId, string? clientId, Uri authorityHost, CancellationToken cancellationToken = default)
{
DeviceCodeCredentialOptions credOptions = new()
{
ClientId = clientId ?? Constants.DefaultAppId,
TenantId = tenantId ?? Constants.DefaultTenant,
DisableAutomaticAuthentication = true,
AuthorityHost = authorityHost
};
TokenCachePersistenceOptions tokenCacheOptions = new() { Name = Constants.TokenCacheName };
credOptions.TokenCachePersistenceOptions = tokenCacheOptions;
credOptions.AuthenticationRecord = await authenticationCacheManager.ReadAuthenticationRecordAsync(cancellationToken);
return new DeviceCodeCredential(credOptions);
}
private async Task<InteractiveBrowserCredential> GetInteractiveBrowserCredentialAsync(string? tenantId, string? clientId, Uri authorityHost, CancellationToken cancellationToken = default)
{
#if OS_WINDOWS
Debug.Assert(OperatingSystem.IsWindows());
InteractiveBrowserCredentialBrokerOptions credOptions = new(WindowUtils.GetConsoleOrTerminalWindow());
#else
InteractiveBrowserCredentialOptions credOptions = new();
#endif
credOptions.ClientId = clientId ?? Constants.DefaultAppId;
credOptions.TenantId = tenantId ?? Constants.DefaultTenant;
credOptions.DisableAutomaticAuthentication = true;
credOptions.AuthorityHost = authorityHost;
TokenCachePersistenceOptions tokenCacheOptions = new() { Name = Constants.TokenCacheName };
credOptions.TokenCachePersistenceOptions = tokenCacheOptions;
credOptions.AuthenticationRecord = await authenticationCacheManager.ReadAuthenticationRecordAsync(cancellationToken);
return new InteractiveBrowserCredential(credOptions);
}
private ClientCertificateCredential GetClientCertificateCredential(string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint, Uri authorityHost)
{
return ClientCertificateCredentialFactory.GetClientCertificateCredential(tenantId ?? Constants.DefaultTenant, clientId ?? Constants.DefaultAppId, certificateName, certificateThumbPrint, authorityHost);
}
}