I am using Web API and have setup a simple authentication and authorization mechanism where the caller passes a token that I have issued to them in the query string. So they submit a request like:
https://mysite.com/api/Ping?token=[issued-token]
I have an ApiAuthorizeAttribute like this:
public class ApiAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
public ApiPermission Permission { get; set; }
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
switch (Permission)
{
case ApiPermission.None:
return;
case ApiPermission.Write:
case ApiPermission.Read:
string query = actionContext.Request.RequestUri.Query;
var nvc = System.Web.HttpUtility.ParseQueryString(query);
string token = nvc["token"];
// (my code to map the token to an Authorization for the request)
ApiAuthorization auth = ApiToken.GetAuthorization(token);
if (auth != null && auth.HasPermission(Permission))
return;
HandleUnauthorizedRequest(actionContext);
return;
default:
throw new ArgumentException("Unexpected Permission");
}
}
}
Then I can decorate my APIs like this. Note: this is just an example, a real call would read data from their account (an account identifier is encrypted within their token) and return it.
/// <summary>
/// Ping service that requires a Token with Read permission
/// Returns "Success!"
/// </summary>
[ApiAuthorize(Permission = ApiPermission.Read)]
[HttpGet]
public string Ping()
{
return "Success!";
}
As you might note, I could not access the QueryString anywhere from HttpActionContext parameter and had to build it myself. It seems like they explicitly removed QueryString from this Request object. I don’t want to add “token” it to each and every API method in order to get it in the Route Data.
So my questions are:
BTW, I realize there are other (probably better) options for authorization such as Basic Authentication and OAuth, and I do not want to debate that topic here.
While Adam Tal's answer is perfectly valid, in the Web API new world order you really do not want to use anything from the System.Web
namespace; in fact you don't even want to reference it. Alas you can get to the querystring from the GetQueryNameValuePairs() extension method. That will let you cut System.Web boat anchor loose and still get to what you need.
using System.Net.Http;
var queryString = actionContext.Request
.GetQueryNameValuePairs()
.ToDictionary(x => x.Key, x => x.Value);
NameValueCollection queryString = actionContext.Request.RequestUri.ParseQueryString();
It works for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With