Reputation: 28
EDIT: I changed my approach. Now I am using MessageHandlers. Thanks to Raciel, who pointed the direction where to dig.
These links where very useful for me: MessageHandlers overview Using own Principal classes
I have a WebApi project and need to provide custom authorization to it. Special Token object is added to each request from the frontend. Something like that:
SendApiRequest: function (controller, action, data, successCallback, failureCallback) {
var url = ROUTER.GetApiUrl(controller, action);
data.Token = TOKEN;
jQuery.ajax({
type: 'POST',
dataType: 'json',
url: url,
data: data,
success: function (result) {
if (typeof successCallback == 'function') {
successCallback(result);
}
},
error: function (result) {
if (typeof failureCallback == 'function') {
failureCallback(result);
}
}
});}
I have an AuthorizationAttribute and I somehow need to serialize Token object from the request. But cannot find any automatic way to do that.
public class CustomAuthorizationAttribute : AuthorizeAttribute
{
public override void OnAuthorization(HttpActionContext context)
{
UserToken token = null;
//HOW TO SERIALIZE token object from context?
}
}
UserToken class looks like that:
public class UserToken
{
public Int64 TokenID;
public int UserID;
public string TokenValue;
public string IP;
public string Hash;
public DateTime CreatedOn;
public DateTime ActionOn;
}
So the question is: how to serialize custom Object from HttpActionContext?
Thank you.
Upvotes: 0
Views: 2657
Reputation: 2156
This is what I have done when I'm dealing with cases similar to yours.
Instead of creating your own Authorize attribute, you can create a MessageHandler which checks for the token and validates it on every request. This message handler is the responsible for populating the Principal in the current thread, so the Authorize attribute can work as expected allowing authorized clients to access the controller/action in question.
This is how my Authorization message handler looks like:
public class AuthMessageHandler : DelegatingHandler
{
protected ITokenProvider TokenProvider { get; private set; }
protected IPrincipalProvider PrincipalProvider { get; private set; }
public AuthMessageHandler(ITokenProvider tokenProvider, IPrincipalProvider principalProvider)
{
TokenProvider = tokenProvider;
PrincipalProvider = principalProvider;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Identity identity = null;
string token = ExtractToken(request);
if (token != null && TokenProvider.Verify(token, out identity))
{
request.Properties.Add(Constants.IdentityKey, identity);
var principal = PrincipalProvider.CreatePrincipal(identity);
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
}
return base.SendAsync(request, cancellationToken);
}
private string ExtractToken(HttpRequestMessage request)
{
IEnumerable<string> tokenValues = null;
if (request.Headers.TryGetValues(Constants.TokenHeaderKey, out tokenValues))
return tokenValues.First();
return null;
}
}
Please note:
Please let me know if you have any questions. This is actually simpler that it looks.
Upvotes: 2