0 Comments

When working with the new Identity 2.0 and WebAPI Owin Authentication there is a specific flow you have to follow in order to query an endpoint that need authorization (marked with [Authorize] attribute). Let get going:

First we’ll start with a new ASP.NET project and choose the WebAPI template, make sure that the Authentication is Individual User Account, this will setup the project with all the basic configuration to easily and rapidly use the new Identity provider.

If we look in the Startup.Auth.cs class we can see many of the setup for the Individual User account. What is interesting to us is in this part of the code:

// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    AllowInsecureHttp = true
};

// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
Our application will be using Bearer Token as the auth mechanism…this will be important later on, also notice where the token endpoint is “/Token”.

Right now if we we’re to try and call a secured endpoint(/api/values) we would get a a 401 Unauthorized, because the route is marked with the Authorize Attribute. In order for us to call this endpoint we must be:

  1. A registered user
  2. User must be Authorized (by internal or external providers) In a new project there is no existing user (unless you are hooking up to an existing Database that supports the Identity Model), just for transparency I called the endpoint to register a user :
    POST /api/account/register
    {"email":"mat1@matrichard.com",
    "password": "!a12345A",
    "confirmPassword": "!a12345A"}
    

     

    The password validation settings are configured in the IdentityConfig.cs class and these are the default configs:

    manager.PasswordValidator = new PasswordValidator
    {
        RequiredLength = 6,
        RequireNonLetterOrDigit = true,
        RequireDigit = true,
        RequireLowercase = true,
        RequireUppercase = true,
    };
    

     

    Let’s get back to what is at heart …how to call that /api/values and get a 200 OK instead of 401 Unauthorized. Since I now have a registered user, I only need to Authorize this user, this will be done by making an API call to /Token like so:

    POST /token
    username=mat1%40matrichard.com&password=!a12345A&grant_type=password
    

    Two very important things to note with /token :

    1. The Content-Type MUST be application/x-www-form-urlencoded
    2. A grant_type with the value password MUST be supplied in the body

     

    If everything goes as planned we should receive a 200 OK response with a body that looks very close to that (I removed the access_token for readability purpose) :

    {"access_token":"[A VERY VERY BIG VALUE]",
    "token_type":"bearer",
    "expires_in":1209599,
    "userName":"mat1@matrichard.com",
    ".issued":"Wed, 19 Nov 2014 02:40:33 GMT",
    ".expires":"Wed, 03 Dec 2014 02:40:33 GMT"}
     

    So now based on this response we can build our call to /api/values by simply adding the token value in the authorize header and pre-pending it with the token_type like so :

    Authorization: Bearer [INSERT TOKEN VALUE]
    

     

    It’s that simple.

    Mat
    @matrichard5

0 Comments

In a WebAPI application, by default when you hit an endpoint that does not exists you get a 404 response (with htnl in the body no less…..even if you are doing it from a webapi endpoint), and all of that is done through the framework and the routing mechanism. A quick and easy way to have control over this, is by adding a controller with a route that will be acting as a catch all. For the controller it goes like so:

public class DefaultController : ApiController
{
    public IHttpActionResult Get(string uri)
    {
        // do what is needed
        return this.NotFound();
    }
}

and the route would look like this:

config.Routes.MapHttpRoute(
    name: "ResourceNotFound",
    routeTemplate: "api/{*uri}",
    defaults: new { controller = "Default", uri = RouteParameter.Optional });

by adding this route any GET that is not mapped will default this this controller, what makes it work is the {*uri}, this capture everything that is after the api/, so in your controller you have access to the URI that was requested. This is an easy and quick way if you wanted to create a better response with a message stating what was the requested URI or needed to create some stats based on those unmatched route.

Things to note:

  • DO NOT put this route as a RouteAttribute (in WebAPI 2) if your routes are defined as RouteAttribute, because you’ll get an error:
Multiple controller types were found that match the URL. This can happen if attribute routes on multiple controllers match the requested URL
  • This route should be the LAST route in your route collection and if lucky your only route defined that way.

 

Happy coding

1 Comments

With the introduction of ASP.NET WebAPI 2 came two new attributes, Route and RoutePrefix. By default route resolving is done using the controller name and then appending controller, from there the framework will try and find a matching controller class and load it up and execute the given action or HTTP VERB. So given this ValuesController class (ValuesController is part of the default WebAPI template when starting a new project, as well as a whole lot of scripts and css…… but that’s another debate).

public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/values/5
    public string Get(int id)
    {
        return "value " + 5;
    }
}

when requesting this route:

GET http://localhost:64770/api/values/5

We know that we will get back a response(XML, JSON, or any other format you want to support) with the HTTP Status code of 200 (OK) with the string values 5 in the response body.

Now if I were to add the Route attribute on the GET action:

[Route("api/foo/{id}", Name = "GetFoo")]
public string Get(int id)
{
    return "value " + id;
}

and requesting the previous URL we will now have a 404 (Not Found) response and a message stating that “No HTTP resource was found that matches the request URI”, but by calling

GET http://localhost:64770/api/foo/5

 

We now get a 200 (OK) response with the string values 5 in the response body, just like before. The {id} is used for parameter binding and eventually can be used for route constraints. When adding the route attribute, you can choose to give it a name and an order. If you need (most probably) to add route constraints to your route it can be done by following the route constraints semantic (another blog post).

Don’t forget that for you routes to be properly mapped, you must make sure that in the WebApiConfig.Register method that this line of code:

config.MapHttpAttributeRoutes();

is present otherwise you will get HTTP 404.

So with this attribute we can now easily define a bunch of routes inside a controller, even go for versioning, wihtout having to override classes.

Next up route constraints!

0 Comments

When starting a new ASP.NET project there is  a folder called App_Start and inside this folder you will find a file WebApiConfig. This file should be used for all config for any ApiController. It already contains some element of configuration, but it is missing one very important (IMO): the camelCasing of the properties of a JSON response. When making a call to an ApiController without the camel case settings the JSON response will be like so :

preCamelCase

As you can see from the response (lower box) all the properties name start with a capital letter, which could cause problems when users would want to use your API, or when mapping with a Javascript library. By adding a single line of code in the Register methood of the WebApiConfig.cs file:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
 

Your JSON response will now return what is considered to be valid JSON :

postCamelCase

0 Comments

I did a talk at the Ottawa IT Community on WebAPI, great crowd and lots of interesting questions. So for all of the attendees that wanted the code that was shown here is demo 1, demo 2 and the slides both demos are hosted on Github and remember the code is mostly demo code so get inspired or test the hell out of it Winking smile .

Thanks for having me, I had a great time and hope to come back to speak soon. !!