@@ -33,8 +33,7 @@ public class UsernamePasswordCredential : TokenCredential
3333 /// Protected constructor for mocking
3434 /// </summary>
3535 protected UsernamePasswordCredential ( )
36- {
37- }
36+ { }
3837
3938 /// <summary>
4039 /// 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()
4645 /// <param name="clientId">The client (application) ID of an App Registration in the tenant.</param>
4746 public UsernamePasswordCredential ( string username , string password , string tenantId , string clientId )
4847 : this ( username , password , tenantId , clientId , ( TokenCredentialOptions ) null )
49- {
50- }
48+ { }
5149
5250 /// <summary>
5351 /// 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
6058 /// <param name="options">The client options for the newly created UsernamePasswordCredential</param>
6159 public UsernamePasswordCredential ( string username , string password , string tenantId , string clientId , TokenCredentialOptions options )
6260 : this ( username , password , tenantId , clientId , options , null , null )
63- {
64- }
61+ { }
6562
6663 /// <summary>
6764 /// 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
7471 /// <param name="options">The client options for the newly created UsernamePasswordCredential</param>
7572 public UsernamePasswordCredential ( string username , string password , string tenantId , string clientId , UsernamePasswordCredentialOptions options )
7673 : 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 )
8184 {
8285 Argument . AssertNotNull ( username , nameof ( username ) ) ;
8386 Argument . AssertNotNull ( password , nameof ( password ) ) ;
@@ -126,7 +129,8 @@ public virtual async Task<AuthenticationRecord> AuthenticateAsync(CancellationTo
126129 /// <returns>The <see cref="AuthenticationRecord"/> of the authenticated account.</returns>
127130 public virtual AuthenticationRecord Authenticate ( TokenRequestContext requestContext , CancellationToken cancellationToken = default )
128131 {
129- return AuthenticateImplAsync ( false , requestContext , cancellationToken ) . EnsureCompleted ( ) ;
132+ AuthenticateImplAsync ( false , requestContext , cancellationToken ) . EnsureCompleted ( ) ;
133+ return _record ;
130134 }
131135
132136 /// <summary>
@@ -137,7 +141,8 @@ public virtual AuthenticationRecord Authenticate(TokenRequestContext requestCont
137141 /// <returns>The <see cref="AuthenticationRecord"/> of the authenticated account.</returns>
138142 public virtual async Task < AuthenticationRecord > AuthenticateAsync ( TokenRequestContext requestContext , CancellationToken cancellationToken = default )
139143 {
140- return await AuthenticateImplAsync ( true , requestContext , cancellationToken ) . ConfigureAwait ( false ) ;
144+ await AuthenticateImplAsync ( true , requestContext , cancellationToken ) . ConfigureAwait ( false ) ;
145+ return _record ;
141146 }
142147
143148 /// <summary>
@@ -166,15 +171,19 @@ public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext r
166171 return await GetTokenImplAsync ( true , requestContext , cancellationToken ) . ConfigureAwait ( false ) ;
167172 }
168173
169- private async Task < AuthenticationRecord > AuthenticateImplAsync ( bool async , TokenRequestContext requestContext , CancellationToken cancellationToken )
174+ private async Task < AuthenticationResult > AuthenticateImplAsync ( bool async , TokenRequestContext requestContext , CancellationToken cancellationToken )
170175 {
171176 using CredentialDiagnosticScope scope = _pipeline . StartGetTokenScope ( $ "{ nameof ( UsernamePasswordCredential ) } .{ nameof ( Authenticate ) } ", requestContext ) ;
172-
173177 try
174178 {
175- scope . Succeeded ( await GetTokenImplAsync ( async , requestContext , cancellationToken ) . ConfigureAwait ( false ) ) ;
179+ var tenantId = TenantIdResolver . Resolve ( _tenantId , requestContext , _allowMultiTenantAuthentication ) ;
176180
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 ;
178187 }
179188 catch ( Exception e )
180189 {
@@ -185,17 +194,25 @@ private async Task<AuthenticationRecord> AuthenticateImplAsync(bool async, Token
185194 private async Task < AccessToken > GetTokenImplAsync ( bool async , TokenRequestContext requestContext , CancellationToken cancellationToken )
186195 {
187196 using CredentialDiagnosticScope scope = _pipeline . StartGetTokenScope ( "UsernamePasswordCredential.GetToken" , requestContext ) ;
188-
189197 try
190198 {
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 ) ;
199216 return scope . Succeeded ( new AccessToken ( result . AccessToken , result . ExpiresOn ) ) ;
200217 }
201218 catch ( Exception e )
0 commit comments