Authentication filter in Web API 2 - asp.net-web-api

I created a simple custom authentication filter in Web API 2, which look like this.
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
string authToken = context.Request.Headers.GetValues("CustomAuthHeader").FirstOrDefault();
if (string.IsNullOrEmpty(authToken))
{
context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request);
}
return Task.FromResult(0);
}
public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
return Task.FromResult(0);
}
I have below question on this-
1). AuthenticateAsync is for implementing the core authentication logic but what is the use of ChallengeAsync in real life. If possible please explain with a example.
2). Why its returning Task. Will it create a new thread at back end every time (Wherever apply). If it create a new thread every time, when this thread will be killed?
3). What is the role of Task.FromResult(0)
Thank you!

ChallengeAsync is used to add authentication challenges to the response, if needed. Typically it is used in case of 401 Unauthorized to provide information about authentication required by server.
Methods return task to support asynchronous execution and chaining.
Methods contain no really asynchronous methods that's why they return dummy already completed task to satisfy implemented interface.
I guess this article should help you a lot.

Related

Spring WebClient toFuture() vs. block() - What's the main difference?

My Spring Boot application uses WebClient to make calls to a remote API. I do have some difficulty understanding the difference between the following modes on how to use the WebClient.
Option 1 - using block()
// WebClient
public Boolean updateUser(long id) {
return webClient.post()
.uri(uriBuilder -> uriBuilder.path(USER_PATH).build(id))
.body(Mono.just(payload), User.class)
.exchangeToMono(clientResponse -> Mono.just(clientResponse.statusCode().is2xxSuccessful()))
.block();
}
// Caller
Boolean result = updateUser(5);
Option 2 - using toFuture():
// WebClient
public CompletableFuture<Boolean> updateUser(long id) {
return webClient.post()
.uri(uriBuilder -> uriBuilder.path(USER_PATH).build(id))
.body(Mono.just(payload), User.class)
.exchangeToMono(clientResponse -> Mono.just(clientResponse.statusCode().is2xxSuccessful()))
.toFuture();
}
// Caller
CompletableFuture<Boolean> future = updateUser(5);
Boolean result = future.get();
As far as I understand, using .block() blocks the thread when the WebClient makes its request and waits for a response.
When using toFuture() instead, then the WebClient runs on a different thread, thus it does not block. But is the thread not blocked anyways using the .get() method on the CompletableFuture?
When would I choose one over the other?
In the second option, you allow the caller to decide when to wait, this looks more flexible than the first option.
TL;DR
Mono.toFuture() is not blocking but Mono.toFuture().get() is blocking. block() is technically the same as toFuture().get() and both are blocking.
Mono.toFuture() just transforms Mono into a CompletableFuture by subscribing to it and resolving immediately. But it doesn't mean that you can access result of the corresponding Mono after this. CompletableFuture is still async and you can use methods like thenApply(), thenCompose(), thenCombine(), ... to continue async processing. toFuture().get() is a blocking operation.
CompletableFuture<Double> result = getUserDetail(userId)
.toFuture()
.thenCompose(user -> getCreditRating(user));
where getUserDetail is defined as
Mono<User> getUserDetail(String userId);
Mono.toFuture is useful when you need to combine different async APIs. For example, AWS Java v2 API is async but based on CompletableFuture but we can combine APIs using Mono.toFuture or Mono.fromFuture.

Web Api and where should I contorol Request Header data

In Asp.net Web Api, I want to control, request "access token" key is (which is in request header) valid or not. But I cound't decide where should I implement this kind of control. ActionFilter or controller constructor etc. etc.
How about using a DelegatingHandler? It is part if the Web Api pipeline and executes before Routing and Controller handlers.
A really simple handler for access tokens may look like this. You would implement IsValid as you see fit.
public class ValidateTokenHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var token = request.Headers.Authorization;
if (token == null or !IsValid(token))
{
return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
return await base.SendAsync(request, cancellationToken);
}
}

Setting Result in the context of ChallengeAsync method in an authentication filter

This question is related to the answer I have provided here. OP's comment got me thinking a bit. I suggested using a class implementing IHttpActionResult like this in the ChallengeAsync method of the authentication filter.
public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
CancellationToken cancellationToken)
{
context.Result = new ResultWithChallenge(context.Result);
return Task.FromResult(0);
}
public class ResultWithChallenge : IHttpActionResult
{
private readonly IHttpActionResult next;
public ResultWithChallenge(IHttpActionResult next)
{
this.next = next;
}
public async Task<HttpResponseMessage> ExecuteAsync(
CancellationToken cancellationToken)
{
var response = await next.ExecuteAsync(cancellationToken);
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
response.Headers.WwwAuthenticate.Add(
new AuthenticationHeaderValue("Basic", "realm=localhost"));
}
return response;
}
}
Instead of this, I can simplify the ChallengeAsync like this.
public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
CancellationToken cancellationToken)
{
var result = await context.Result.ExecuteAsync(cancellationToken);
if (result.StatusCode == HttpStatusCode.Unauthorized)
{
result.Headers.WwwAuthenticate.Add(
new AuthenticationHeaderValue("Basic", "realm=localhost"));
}
context.Result = new ResponseMessageResult(result);
}
This saves me from creating a class implementing IHttpActionResult but is this the right way? I get an uneasy feeling that this is somehow bad from a performance standpoint because it feels like I'm converting action result to HttpResponseMessage and back to action result. Any pointers on the need for a separate class here implementing IHttpActionResult like what I suggested will be appreciated as against using the code above.
The intent was to use the first approach rather than the second. For example, see the Basic Authentication sample (also available for MVC), which follows the first approach:
http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/BasicAuthentication/ReadMe.txt
The second approach mostly works. I wouldn't be too concerned about the performance standpoint; either way you're allocating one action result object and one response message object, so I'm not seeing much difference there.
However, there are a couple of reasons I'd recommend the first approach:
The second approach won't work the same way in MVC. Both MVC and Web API have authentication filters, and they basically work the same way. But in MVC, there isn't an equivalent to ResponseMessageResult (the HttpContext is updated as needed, rather than returning a HttpResponseMessage that could be replaced by each caller going up the stack). If you have an MVC implementation of your authentication filter, you'd likely end up doing the first approach there anyway.
It slightly changes the pipeline behavior from what's intended. The code in ChallengeAsync runs earlier than the code in the context.Result that it returns. For example, if the code changed a property on the HttpRequestMessage and that impacted a later filter's ChallengeAsync logic, the behavior could be different than what's intended.
The framework definitely could make it easier to implement the interface; feel free to vote on this work item:
https://aspnetwebstack.codeplex.com/workitem/1456

How to handle session expired exception in Spring MVC-Spring Security app for GWT RPC calls

I have Spring MVC application where security is handled by Spring Security.
UI is built using GWT which gets the data from server using RPC approach.
I need to handle on UI the situation when session is expired:
For example RPC AsyncCallback can get SessionExpiredException type of exception and popup the window with message like "You session is expired, please click the refresh link" or something.
Did someone deal with such problem?
Thanks.
I suppose that for processing of incoming GWT call you use some Spring MVC controller or some servlet. It can have following logic
try{
// decode payload from GWT call
com.google.gwt.user.server.rpc.RPC.decodeRequest(...)
// get spring bean responsible for actual business logic
Object bean = applicationContext.getBean(beanName);
// execute business logic and encode response
return RPC.invokeAndEncodeResponse(bean, ….)
} catch (com.google.gwt.user.server.rpc.UnexpectedException ex) {
// send unexpected exception to client
return RPC.encodeResponseForFailure(..., new MyCustomUnexpectedException(), …) ;
}
Solution for this case
HttpServletRequest request = getRequest() ;
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
return RPC.encodeResponseForFailure(..., new MyCustomSessionExpiredException(), …) ;
} else {
// first code snippet goes here
}
Then catch custom session expired exception in a client side code. If you do not use RPC directly then provide more details about your bridge implementation between GWT and Spring.
You will need also force GWT compiler to include MyCustomSessionExpiredException type to a serialization white list (to prevent case when GWT security policy stops propogation of the exception to client side). Solution: include MyCustomSessionExpiredException type to each method signature of each synchronous interface:
#RemoteServiceRelativePath("productRpcService.rpc")
public interface ProductRpcService extends RemoteService {
List<Product> getAllProducts() throws ApplicationException;
void removeProduct(Product product) throws ApplicationException;
}
MyCustomSessionExpiredException extends ApplicationException
Then show pop-up in client side code:
public class ApplicationUncaughtExceptionHandler implements GWT.UncaughtExceptionHandler {
#Override
public void onUncaughtException(Throwable caught) {
if (caught instanceof MyCustomSessionExpiredException) {
Window.alert("Session expired");
}
}
}
// Inside of EntryPoint.onModuleLoad method
GWT.setUncaughtExceptionHandler(new ApplicationUncaughtExceptionHandler());
I researched a bit and uploaded the solution here http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-expired%253Fstate%253Dclosed.
Use mvn jetty:run-war to see the demo after checking it out and go to rpc-security-sample/index.htm
There are two ways to solve it.
The first is around to pass the delegate proxy for GWT RemoteServlet which throws SessionExpiredException during method invocation. This requires to declare Exception in every RPC service method. Example: http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-expired%253Fstate%253Dclosed
Steps:
Develop new filter which intercepts first
Declare SessionExpiredException in each RPC method service which could inherit RuntimeException for simplicity (no need to follow this in implementers)
Develop parent generic AsyncCallback handler
Use http://code.google.com/p/gspring/ solution to handle all incoming RCP requests.
The second which is much more simplest: return the 401 HTTP error and handle in UI side (GWT native general exception contains the HTTP status number). Example: http://code.google.com/p/gspring/source/browse/#svn%2Ftrunk%2Fsample%2Fsession-expired-401
The second approach is simplest and does not require declaring Exception in service methods contract. However following the first approach can give you some flexibility: it could contain some additional info like last login time (for SessionExpiredException) etc. Also the second approach can introduce new exceptions which are inherited from SecurityException like blacklisted user (for example if user was blacklisted during his session) or for example if user does the same actions very often like a robot (it could be asked for passing the captcha) etc.

webapi batching and delegating handlers

based on my last post I was able to get batching working... until a certain point. In addition to registering the route specific handler I also have 2 delegating handlers
Authenticate the user
logging
the batch handler goes through the delegating handlers authenticating the user and logging the request. when the messagehandlerinvoker starts to send the child/nested requests the following exception is thrown.
System.ArgumentException was unhandled by user code
HResult=-2147024809
Message=The 'DelegatingHandler' list is invalid because the property 'InnerHandler' of 'AuthenticationMessageHandler' is not null.
Parameter name: handlers
Source=System.Net.Http.Formatting
ParamName=handlers
StackTrace:
at System.Net.Http.HttpClientFactory.CreatePipeline(HttpMessageHandler innerHandler, IEnumerable`1 handlers)
at System.Web.Http.HttpServer.Initialize()
at System.Web.Http.HttpServer.<EnsureInitialized>b__3()
at System.Threading.LazyInitializer.EnsureInitializedCore[T](T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory)
at System.Threading.LazyInitializer.EnsureInitialized[T](T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory)
at System.Web.Http.HttpServer.EnsureInitialized()
at System.Web.Http.HttpServer.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpMessageInvoker.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at RoutingRequest.Service.Startup.BatchMessageHandler.<>c__DisplayClassd.<PrcoessRequest>b__b(Task`1 m) in C:\CEI\Clients\Footlocker.com\FL - Vendor Routing Portal\source\RoutingRequest.Service\Startup\BatchMessageHandler.cs:line 45
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
InnerException:
is there a config option I am missing, or do I need to bypass the delegating handlers?
edit
here is my authentication handler.
public class AuthenticationMessageHandler
: DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
SetCurrentUser(request);
return base.SendAsync(request, cancellationToken);
}
private void SetCurrentUser(HttpRequestMessage request)
{
var values = new List<string>().AsEnumerable();
if (request.Headers.TryGetValues("routingrequest-username", out values) == false) return;
var username = values.First();
var user = Membership.GetUser(username, true);
if (user == null)
{
var message = string.Format("membership information for '{0}' could not be found.", username);
throw new HttpRequestException(message);
}
var roles = Roles.GetRolesForUser(username);
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(user.UserName), roles);
}
}
based on Kiran's answer a subclassed httpserver fixes one issue and introduces another. My roles provider is getting a null reference exception. looking into that now.
That blog post correctly identifies the problem, but there is a simpler solution if you are configuring OWIN using a Startup or OwinStartup class:
Change the OWIN configuration call from
UseWebApi(this IAppBuilder builder, HttpConfiguration configuration);
to
UseWebApi(this IAppBuilder builder, HttpServer httpServer);
so that your batch handler and the OWIN pipeline are using the same HttpServer instance.
The root cause of this is that many of the batching articles/examples (eg http://bradwilson.typepad.com/blog/2012/06/batching-handler-for-web-api.html ) create a new HttpServer for batching in addition to the main HttpServer that is handling HTTP requests; and both HttpServers are using the same HttpConfiguration.
When each HttpServer is initialized the first time it receives requests, it creates a pipeline of handlers (in HttpClientFactory.CreatePipeline) by reversing all the configured delegating handlers (eg tracing handlers, or other proxy-type handlers), and terminating the pipeline with the Web API dispatcher.
If you don't have any delegating handlers configured, then this problem won't bite you - you can have 2 HttpServer objects that use the same HttpConfiguration.
But if you have any delegating handlers explicitly or implicitly configured (eg by enabling Web API Tracing), then Web API can't build the 2nd pipeline - the delegating handlers are already linked in the first pipeline - and this exception is thrown on the first request to the 2nd HttpServer.
This exception should absolutely be more clear about what is going on. Better yet, this problem shouldn't even be possible - configuration should be configuration, not individual handlers. The configuration could be a factory for delegating handlers. But I digress...
While the issue is kinda hard to figure out, there's a pretty easy fix:
If you're using OWIN, pass the same HttpServer as you use in the batch handler to the OWIN pipeline via UseWebApi(this IAppBuilder builder, HttpServer httpServer);
If you're using IIS + Web API (no OWIN Startup class), pass GlobalConfiguration.DefaultServer to your batch handler, to avoid creating a new HttpServer
Here's an example OWIN startup class that creates a single HttpServer and passes it to both the batch handler, and Web API. This example uses to OData batch handler:
[assembly: OwinStartup(typeof(My.Web.OwinStartup))]
namespace My.Web
{
/// <summary>
/// OWIN webapp configuration.
/// </summary>
public sealed class OwinStartup
{
/// <summary>
/// Configure all the OWIN modules that participate in each request.
/// </summary>
/// <param name="app">The OWIN appBuilder</param>
public void Configuration(IAppBuilder app)
{
HttpConfiguration webApiConfig = new HttpConfiguration();
webApiConfig.MapHttpAttributeRoutes();
HttpServer webApiServer = new HttpServer(webApiConfig);
// Configure batch handler
var batchHandler = new DefaultODataBatchHandler(webApiServer);
webApiConfig.Routes.MapODataServiceRoute("ODataRoute",
"odata",
BuildEdmModel(),
new DefaultODataPathHandler(),
ODataRoutingConventions.CreateDefault(),
batchHandler);
app.UseWebApi(webApiServer);
}
private EdmModel BuildEdmModel()
{
// ...
}
}
}
I've had this error without batching. I made an HttpClientFactory of my own and it takes in a HandlerFactory, also my own.
It calls the HandlerFactory.Create() method in the constructor and stores the resulting handlers that it made.
These are passed to the System.Net.Http.HttpClientFactory.Create(...) method whenever the factory needs to make a new HttpClient.
But it's then only good for a single call because the handlers themselves are mutated by the .NET code leaving them in a state that means they cannot be reused.
I altered my constructor so that it doesn't create the handlers up front, but each time. It now works.

Resources