Reputation: 10509
When using ASP.NET WebAPI 2 OAuthAuthorizationServerProvider one can do custom credential validation within the overridden method of:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
In case an error (Db connection error, for example) occurs during the execution of this method, I would like to return at least 500 Internal Server error to a requester. I don't seem to be able to set custom status code via context.Response.StatusCode = 500;
Is there a way to control the response code from this method?
Upvotes: 1
Views: 3179
Reputation: 2372
Based on Greg P's original answer, with some modifications
Step1: Create a class which will act as your middleware
using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, System.Object>,
System.Threading.Tasks.Task>;
namespace SignOnAPI.Middleware.ResponseMiddleware {
public class ResponseMiddleware
{
AppFunc _next;
ResponseMiddlewareOptions _options;
public ResponseMiddleware(AppFunc nex, ResponseMiddlewareOptions options)
{
_next = next;
}
public async Task Invoke(IDictionary<string, object> environment)
{
var context = new OwinContext(environment);
await _next(environment);
if (context.Response.StatusCode == 400 && context.Response.Headers.ContainsKey("Change_Status_Code"))
{
//read the status code sent in the response
var headerValues = context.Response.Headers.GetValues("Change_Status_Code");
//replace the original status code with the new one
context.Response.StatusCode = Convert.ToInt16(headerValues.FirstOrDefault());
//remove the unnecessary header flag
context.Response.Headers.Remove("Change_Status_Code");
}
}
}
Step2 : Create the extensions class (Can be omitted).
This step is optional, can be modified to accept options that can be passed to the middleware.
public static class ResponseMiddlewareExtensions
{
//method name that will be used in the startup class, add additional parameter to accept middleware options if necessary
public static void UseResponseMiddleware(this IAppBuilder app)
{
app.Use<ResponseMiddleware>();
}
}
Step3: Modify GrantResourceOwnerCredentials
method in your OAuthAuthorizationServerProvider
implementation
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
if (<database connection failed)
{
//first reject the context, to signify that the client is not valid
context.Rejected();
//set the error message
context.SetError("invalid_username_or_password", "Invalid userName or password" );
//add a new key in the header along with the statusCode you'd like to return
context.Response.Headers.Add("Change_Status_Code", new[] { ((int)HttpStatusCode.InternalServerError).ToString() });
return;
}
}
Step4: Use this middleware in the startup class
public void Configuration(IAppBuilder app)
{
app.UseResponseMiddleware();
//configure the authentication server provider
ConfigureOAuth(app);
//rest of your code goes here....
}
Upvotes: 2