Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebAPI2.0 OWIN Token request using JSON

I have created a new WebAPI solution in visual studio and am playing around with the code to try and understand whats going on.

I have a test API thats all up and running with an Authorization controller and another controller that implements all the actual functionality.

The controllers (API) all work by receiving JSON and replying with JSON, with the exception of the /Token request.This has to be:

Content-Type: application/x-www-form-urlencoded

otherwise I just get an error back.

The section of code that creates this endpoint appears to be this:

OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    // In production mode set AllowInsecureHttp = false
    AllowInsecureHttp = false
};

Calling it like this results in a 200 Success response, with a Bearer token:

$("#token_button").click(function ()
{
    var username = $("#token_email").val();
    var password = $("#token_password").val();

    postData("Token", "grant_type=password&username=" + username + "&password=" + password, "application/x-www-form-urlencoded", function (data)
    {
        user = data;
        $("#feedback_display").html(user.access_token);
    }, function ()
    {
        user = null;
    });
});

Calling it like this results in a 400 Response:

$("#token_button").click(function ()
{
    var username = $("#token_email").val();
    var password = $("#token_password").val();

    var data = {
        "grant_type": "password",
        "username": username,
        "password": password
    }

    postData("Token", JSON.stringify(data), "application/json", function (data)
    {
        user = data;
        $("#feedback_display").html(user.access_token);
    }, function ()
    {
        user = null;
    });
});

The response body is:

{"error":"unsupported_grant_type"}

The only difference here is the encoding used to transmit the request. Every where I look all the examples are using form encoding to request this token.

Placing a breakpoint on the code under /api/Account/ExternalLogin, never gets hit.

Is there a reason for this only accepting form encoding? and if not how can I change the controller to accept JSON?

Alternatively have I just done something stupid?

like image 222
Morvael Avatar asked Jun 08 '16 12:06

Morvael


People also ask

What is OWIN authentication in MVC?

A new security design for MVC,Owin Authentication middleware,is recommended for higher security. The security features can be shared by other components which are hosted on OWIN. OWIN provides the underlying set of components to asp.net applications to enable, then to be flexible,portable,and lightweight.


1 Answers

The reason behind the use of application/x-www-form-urlencoded as Content-Type is simple: the OAuth2 specification (RFC 6749) requires this content type for token requests.

Any other content-type will break OAuth2 compliant clients compatibility. I advice you to not change this standard behavior.

Note
Please note that this:

postData("Token", data, "application/json", function (data)
{
    //...
}

works just because you are not sending JSON at all! Even if you added application/json as Content-Type header your request body is serialized as form key-value pairs (the jQuery default object serialization in AJAX calls).

The default implementation of OAuthAuthorizationServerMiddleware (more precisely the internally used OAuthAuthorizationServerHandler) from Microsoft.Owin.Security.OAuth just ignores the Content-Type header and tries to read the request body as a form anyway.

like image 87
Federico Dipuma Avatar answered Sep 21 '22 19:09

Federico Dipuma