I need to consume a login endpoint, This endpoint expects form-data-urlencoded formatted data.
I have tried all I can send to data containing the username and password received from the view to the service. all efforts return an error 400. What are my doing wrong?
below is the endpoint to login and create a ticket in the app.
[AllowAnonymous, HttpPost]
public async Task<IActionResult> Token([ModelBinder(BinderType = typeof(OpenIddictMvcBinder))] OpenIdConnectRequest model)
{
try
{
if (model.IsPasswordGrantType())
{
var applicationUser = await _userManager.FindByNameAsync(model.Username);
if (applicationUser is null)
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "Login or password is incorrect."
});
}
// Ensure the user is allowed to sign in.
//if (!await _signInManager.CanSignInAsync(applicationUser) || applicationUser.IsDeleted)
if (!await _signInManager.CanSignInAsync(applicationUser))
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.AccessDenied,
ErrorDescription = "You are not allowed to sign in."
});
}
// Reject the token request if two-factor authentication has been enabled by the user.
if (_userManager.SupportsUserTwoFactor && await _userManager.GetTwoFactorEnabledAsync(applicationUser))
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.AccessDenied,
ErrorDescription = "You are not allowed to sign in."
});
}
// Ensure the user is not already locked out.
if (_userManager.SupportsUserLockout && await _userManager.IsLockedOutAsync(applicationUser))
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.AccessDenied,
ErrorDescription = "Your profile is temporary locked."
});
}
// Ensure the password is valid.
if (!await _userManager.CheckPasswordAsync(applicationUser, model.Password))
{
if (_userManager.SupportsUserLockout)
{
await _userManager.AccessFailedAsync(applicationUser);
}
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "Login or password is incorrect."
});
}
if (_userManager.SupportsUserLockout)
{
await _userManager.ResetAccessFailedCountAsync(applicationUser);
}
applicationUser.LastLoginDate = Clock.Now;
await _userManager.UpdateAsync(applicationUser);
var ticket = await CreateTicketAsync(model, applicationUser);
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}
// Create a new authentication ticket.
//var ticket = await CreateTicketAsync(model, applicationUser, isAdUser: isAdUser);
//return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
else if (model.IsRefreshTokenGrantType())
{
// Retrieve the claims principal stored in the refresh token.
var info = await HttpContext.AuthenticateAsync(
OpenIddictServerDefaults.AuthenticationScheme);
// Retrieve the user profile corresponding to the refresh token.
// Note: if you want to automatically invalidate the refresh token
// when the user password/roles change, use the following line instead:
// var user = _signInManager.ValidateSecurityStampAsync(info.Principal);
var user = await _userManager.GetUserAsync(info.Principal);
if (user == null)
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The refresh token is no longer valid."
});
}
// Ensure the user is still allowed to sign in.
if (!await _signInManager.CanSignInAsync(user))
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The user is no longer allowed to sign in."
});
}
// Create a new authentication ticket, but reuse the properties stored
// in the refresh token, including the scopes originally granted.
var ticket = await CreateTicketAsync(model, user, info.Properties);
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
ErrorDescription = "The specified grant type is not supported."
});
}
catch (Exception ex)
{
return HandleError(ex);
}
}
I then have my mvc web app project in the same solution as the service, see the login action below
[HttpPost]
public async Task<IActionResult> Login(LoginVM model)
{
try
{
var url = Const.BaseUrl + "/Authentication/Token";
//The first thing I tried
var nvc = new Dictionary<string, string>();
nvc.Add("Content-Type", "application/x-www-form-urlencoded");
nvc.Add("Username", model.Username);
nvc.Add("Password", model.Password);
var req = new HttpRequestMessage(HttpMethod.Post, url) { Content = new FormUrlEncodedContent(nvc) };
var res = await client.SendAsync(req);
//this returned an error 400
//second thing i tried
MyClient.Headers[HttpRequestHeader.Accept] = "application/json";
MyClient.Headers[HttpRequestHeader.ContentType] = "application/json";
string allData = JsonConvert.SerializeObject(mod);
var responseData = MyClient.UploadString(url, "POST", allData);
//Same error 400
return View();
}
catch (Exception ex)
{
throw;
}
}
Please how can I post username and password received from the view to the webservice endpoint above
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…