I've derived OAuthAuthorizationServerProvider
in order to validate both clients and resource owners.
When I validate resource owners I find their credentials aren't valid, I call context.Rejected()
, and HTTP response comes with HTTP/400 Bad Request status code while I would expect HTTP/401 Unauthorized.
How can I customize OAuthAuthorizationServerProvider
's response HTTP status codes?
This is how we override the OwinMiddleware...first we created our own middleware on top of Owin...I think we had similar issue as you did.
First need to create a constant:
public class Constants
{
public const string OwinChallengeFlag = "X-Challenge";
}
And we override the OwinMiddleware
public class AuthenticationMiddleware : OwinMiddleware
{
public AuthenticationMiddleware(OwinMiddleware next) : base(next) { }
public override async Task Invoke(IOwinContext context)
{
await Next.Invoke(context);
if (context.Response.StatusCode == 400 && context.Response.Headers.ContainsKey(Constants.OwinChallengeFlag))
{
var headerValues = context.Response.Headers.GetValues(Constants.OwinChallengeFlag);
context.Response.StatusCode = Convert.ToInt16(headerValues.FirstOrDefault());
context.Response.Headers.Remove(Constants.OwinChallengeFlag);
}
}
}
In the startup.Auth file, we allowed the overrid of the Invoke Owin Commands
public void ConfigureAuth(IAppBuilder app)
....
app.Use<AuthenticationMiddleware>(); //Allows override of Invoke OWIN commands
....
}
And in the ApplicationOAuthProvider, we modified the GrantResourceOwnerCredentials.
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
using (UserManager<IdentityUser> userManager = _userManagerFactory())
{
IdentityUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
context.Response.Headers.Add(Constants.OwinChallengeFlag, new[] { ((int)HttpStatusCode.Unauthorized).ToString() }); //Little trick to get this to throw 401, refer to AuthenticationMiddleware for more
//return;
}
....