@@ -33,8 +33,7 @@ public class UsernamePasswordCredential : TokenCredential
33
33
/// Protected constructor for mocking
34
34
/// </summary>
35
35
protected UsernamePasswordCredential ( )
36
- {
37
- }
36
+ { }
38
37
39
38
/// <summary>
40
39
/// Creates an instance of the <see cref="UsernamePasswordCredential"/> with the details needed to authenticate against Azure Active Directory with a simple username
@@ -46,8 +45,7 @@ protected UsernamePasswordCredential()
46
45
/// <param name="clientId">The client (application) ID of an App Registration in the tenant.</param>
47
46
public UsernamePasswordCredential ( string username , string password , string tenantId , string clientId )
48
47
: this ( username , password , tenantId , clientId , ( TokenCredentialOptions ) null )
49
- {
50
- }
48
+ { }
51
49
52
50
/// <summary>
53
51
/// Creates an instance of the <see cref="UsernamePasswordCredential"/> with the details needed to authenticate against Azure Active Directory with a simple username
@@ -60,8 +58,7 @@ public UsernamePasswordCredential(string username, string password, string tenan
60
58
/// <param name="options">The client options for the newly created UsernamePasswordCredential</param>
61
59
public UsernamePasswordCredential ( string username , string password , string tenantId , string clientId , TokenCredentialOptions options )
62
60
: this ( username , password , tenantId , clientId , options , null , null )
63
- {
64
- }
61
+ { }
65
62
66
63
/// <summary>
67
64
/// Creates an instance of the <see cref="UsernamePasswordCredential"/> with the details needed to authenticate against Azure Active Directory with a simple username
@@ -74,10 +71,16 @@ public UsernamePasswordCredential(string username, string password, string tenan
74
71
/// <param name="options">The client options for the newly created UsernamePasswordCredential</param>
75
72
public UsernamePasswordCredential ( string username , string password , string tenantId , string clientId , UsernamePasswordCredentialOptions options )
76
73
: this ( username , password , tenantId , clientId , options , null , null )
77
- {
78
- }
79
-
80
- internal UsernamePasswordCredential ( string username , string password , string tenantId , string clientId , TokenCredentialOptions options , CredentialPipeline pipeline , MsalPublicClient client )
74
+ { }
75
+
76
+ internal UsernamePasswordCredential (
77
+ string username ,
78
+ string password ,
79
+ string tenantId ,
80
+ string clientId ,
81
+ TokenCredentialOptions options ,
82
+ CredentialPipeline pipeline ,
83
+ MsalPublicClient client )
81
84
{
82
85
Argument . AssertNotNull ( username , nameof ( username ) ) ;
83
86
Argument . AssertNotNull ( password , nameof ( password ) ) ;
@@ -126,7 +129,8 @@ public virtual async Task<AuthenticationRecord> AuthenticateAsync(CancellationTo
126
129
/// <returns>The <see cref="AuthenticationRecord"/> of the authenticated account.</returns>
127
130
public virtual AuthenticationRecord Authenticate ( TokenRequestContext requestContext , CancellationToken cancellationToken = default )
128
131
{
129
- return AuthenticateImplAsync ( false , requestContext , cancellationToken ) . EnsureCompleted ( ) ;
132
+ AuthenticateImplAsync ( false , requestContext , cancellationToken ) . EnsureCompleted ( ) ;
133
+ return _record ;
130
134
}
131
135
132
136
/// <summary>
@@ -137,7 +141,8 @@ public virtual AuthenticationRecord Authenticate(TokenRequestContext requestCont
137
141
/// <returns>The <see cref="AuthenticationRecord"/> of the authenticated account.</returns>
138
142
public virtual async Task < AuthenticationRecord > AuthenticateAsync ( TokenRequestContext requestContext , CancellationToken cancellationToken = default )
139
143
{
140
- return await AuthenticateImplAsync ( true , requestContext , cancellationToken ) . ConfigureAwait ( false ) ;
144
+ await AuthenticateImplAsync ( true , requestContext , cancellationToken ) . ConfigureAwait ( false ) ;
145
+ return _record ;
141
146
}
142
147
143
148
/// <summary>
@@ -166,15 +171,19 @@ public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext r
166
171
return await GetTokenImplAsync ( true , requestContext , cancellationToken ) . ConfigureAwait ( false ) ;
167
172
}
168
173
169
- private async Task < AuthenticationRecord > AuthenticateImplAsync ( bool async , TokenRequestContext requestContext , CancellationToken cancellationToken )
174
+ private async Task < AuthenticationResult > AuthenticateImplAsync ( bool async , TokenRequestContext requestContext , CancellationToken cancellationToken )
170
175
{
171
176
using CredentialDiagnosticScope scope = _pipeline . StartGetTokenScope ( $ "{ nameof ( UsernamePasswordCredential ) } .{ nameof ( Authenticate ) } ", requestContext ) ;
172
-
173
177
try
174
178
{
175
- scope . Succeeded ( await GetTokenImplAsync ( async , requestContext , cancellationToken ) . ConfigureAwait ( false ) ) ;
179
+ var tenantId = TenantIdResolver . Resolve ( _tenantId , requestContext , _allowMultiTenantAuthentication ) ;
176
180
177
- return _record;
181
+ AuthenticationResult result = await Client
182
+ . AcquireTokenByUsernamePasswordAsync ( requestContext . Scopes , requestContext . Claims , _username , _password , tenantId , async, cancellationToken )
183
+ . ConfigureAwait ( false ) ;
184
+
185
+ _record = new AuthenticationRecord ( result , _clientId ) ;
186
+ return result ;
178
187
}
179
188
catch ( Exception e )
180
189
{
@@ -185,17 +194,25 @@ private async Task<AuthenticationRecord> AuthenticateImplAsync(bool async, Token
185
194
private async Task < AccessToken > GetTokenImplAsync ( bool async , TokenRequestContext requestContext , CancellationToken cancellationToken )
186
195
{
187
196
using CredentialDiagnosticScope scope = _pipeline . StartGetTokenScope ( "UsernamePasswordCredential.GetToken" , requestContext ) ;
188
-
189
197
try
190
198
{
191
- var tenantId = TenantIdResolver . Resolve ( _tenantId , requestContext , _allowMultiTenantAuthentication ) ;
192
-
193
- AuthenticationResult result = await Client
194
- . AcquireTokenByUsernamePasswordAsync ( requestContext . Scopes , requestContext . Claims , _username , _password , tenantId , async, cancellationToken )
195
- . ConfigureAwait ( false ) ;
196
-
197
- _record = new AuthenticationRecord ( result , _clientId ) ;
198
-
199
+ AuthenticationResult result ;
200
+ if ( _record != null )
201
+ {
202
+ var tenantId = TenantIdResolver . Resolve ( _tenantId , requestContext , _allowMultiTenantAuthentication ) ;
203
+ try
204
+ {
205
+ result = await Client . AcquireTokenSilentAsync ( requestContext . Scopes , requestContext . Claims , _record , tenantId , async, cancellationToken )
206
+ . ConfigureAwait ( false ) ;
207
+ return scope . Succeeded ( new AccessToken ( result . AccessToken , result . ExpiresOn ) ) ;
208
+ }
209
+ catch ( MsalUiRequiredException msalEx )
210
+ {
211
+ AzureIdentityEventSource . Singleton . UsernamePasswordCredentialAcquireTokenSilentFailed ( msalEx ) ;
212
+ // fall through so that AuthenticateImplAsync is called.
213
+ }
214
+ }
215
+ result = await AuthenticateImplAsync ( async , requestContext , cancellationToken ) . ConfigureAwait ( false ) ;
199
216
return scope . Succeeded ( new AccessToken ( result . AccessToken , result . ExpiresOn ) ) ;
200
217
}
201
218
catch ( Exception e )
0 commit comments