@@ -128,36 +128,70 @@ public async Task<IActionResult> Exchange(OpenIdConnectRequest request)
128128 "The OpenIddict binder for ASP.NET Core MVC is not registered. " +
129129 "Make sure services.AddOpenIddict().AddMvcBinders() is correctly called." ) ;
130130
131- if ( request . IsAuthorizationCodeGrantType ( ) )
131+ if ( request . IsPasswordGrantType ( ) )
132132 {
133- // Retrieve the claims principal stored in the authorization code.
134- var info = await HttpContext . Authentication . GetAuthenticateInfoAsync (
135- OpenIdConnectServerDefaults . AuthenticationScheme ) ;
136-
137- // Retrieve the user profile corresponding to the authorization code.
138- var user = await _userManager . GetUserAsync ( info . Principal ) ;
133+ var user = await _userManager . FindByNameAsync ( request . Username ) ;
139134 if ( user == null )
140135 {
141136 return BadRequest ( new OpenIdConnectResponse
142137 {
143138 Error = OpenIdConnectConstants . Errors . InvalidGrant ,
144- ErrorDescription = "The authorization code is no longer valid ."
139+ ErrorDescription = "The username/password couple is invalid ."
145140 } ) ;
146141 }
147142
148- // Ensure the user is still allowed to sign in.
143+ // Ensure the user is allowed to sign in.
149144 if ( ! await _signInManager . CanSignInAsync ( user ) )
150145 {
151146 return BadRequest ( new OpenIdConnectResponse
152147 {
153148 Error = OpenIdConnectConstants . Errors . InvalidGrant ,
154- ErrorDescription = "The user is no longer allowed to sign in."
149+ ErrorDescription = "The specified user is not allowed to sign in."
150+ } ) ;
151+ }
152+
153+ // Reject the token request if two-factor authentication has been enabled by the user.
154+ if ( _userManager . SupportsUserTwoFactor && await _userManager . GetTwoFactorEnabledAsync ( user ) )
155+ {
156+ return BadRequest ( new OpenIdConnectResponse
157+ {
158+ Error = OpenIdConnectConstants . Errors . InvalidGrant ,
159+ ErrorDescription = "The specified user is not allowed to sign in."
155160 } ) ;
156161 }
157162
158- // Create a new authentication ticket, but reuse the properties stored
159- // in the authorization code, including the scopes originally granted.
160- var ticket = await CreateTicketAsync ( request , user , info . Properties ) ;
163+ // Ensure the user is not already locked out.
164+ if ( _userManager . SupportsUserLockout && await _userManager . IsLockedOutAsync ( user ) )
165+ {
166+ return BadRequest ( new OpenIdConnectResponse
167+ {
168+ Error = OpenIdConnectConstants . Errors . InvalidGrant ,
169+ ErrorDescription = "The username/password couple is invalid."
170+ } ) ;
171+ }
172+
173+ // Ensure the password is valid.
174+ if ( ! await _userManager . CheckPasswordAsync ( user , request . Password ) )
175+ {
176+ if ( _userManager . SupportsUserLockout )
177+ {
178+ await _userManager . AccessFailedAsync ( user ) ;
179+ }
180+
181+ return BadRequest ( new OpenIdConnectResponse
182+ {
183+ Error = OpenIdConnectConstants . Errors . InvalidGrant ,
184+ ErrorDescription = "The username/password couple is invalid."
185+ } ) ;
186+ }
187+
188+ if ( _userManager . SupportsUserLockout )
189+ {
190+ await _userManager . ResetAccessFailedCountAsync ( user ) ;
191+ }
192+
193+ // Create a new authentication ticket.
194+ var ticket = await CreateTicketAsync ( request , user ) ;
161195
162196 return SignIn ( ticket . Principal , ticket . Properties , ticket . AuthenticationScheme ) ;
163197 }
0 commit comments