简体   繁体   中英

How to get Access Token from ASP.Net Web API 2 via AngularJS $http?

I try like this:

$http({ method: 'POST', url: '/token', data: { username: $scope.username, password: $scope.password, grant_type: 'password' } }).success(function (data, status, headers, config) {
    $scope.output = data;
}).error(function (data, status, headers, config) {
    $scope.output = data;
});

then tried changing the grant_type to a param:

$http({ method: 'POST', url: '/token', data: { username: $scope.username, password: $scope.password }, params: { grant_type: 'password' } }).success(function (data, status, headers, config) {
    $scope.output = data;
}).error(function (data, status, headers, config) {
    $scope.output = data;
});

Still get the dreaded: {"error":"unsupported_grant_type"}

So I do what no AngularJS developer should ever do, resorted to jQuery:

var data = $('#regForm').serialize() + "&grant_type=password";
$.post('/token', data).always(showResponse);

function showResponse(object) {
    $scope.output = JSON.stringify(object, null, 4);
    $scope.$apply();
};

Which works like a champ... so my question is: how do we replicate the jQuery $.post() call above using AngularJS $http() so we can grab an access token from the OWIN middleware based /token endpoint in ASP.Net Web API 2?

Do this:

$http({
        url: '/token',
        method: 'POST',
        data: "userName=" + $scope.username + "&password=" + $scope.password + 
              "&grant_type=password"
})

I think, adding the header {headers: { 'Content-Type': 'application/x-www-form-urlencoded' } to your post request would do the trick. It should be something like this:

$http.post(loginAPIUrl, data,
    {headers: { 'Content-Type': 'application/x-www-form-urlencoded' }})

You are getting that error because the default implementation of the OWIN OAuth provider is expecting the post to the "/Token" service to be form encoded and not json encoded. There is a more detailed answer here How do you set katana-project to allow token requests in json format?

But you can still use AngularJs you just have to change the way the $http post is made. You can try the answer here if you don't mind using jquery to change your params How can I post data as form data instead of a request payload? Hope that helps.

You can always watch for the requests being made using the developer console in your browser and see the difference in the request.

But by looking at your jquery code &grant_type=password is being passed in the body not the querystring so the $http call should be

$http({ method: 'POST', url: '/token', data: { username: $scope.username, password: $scope.password ,grant_type:password} }).success(function (data, status, headers, config) {

Similar to achinth, but you can still use the $http.post method (+ data is escaped)

$http.post(loginUrl, "userName=" + encodeURIComponent(email) +
                     "&password=" + encodeURIComponent(password) +
                     "&grant_type=password"
).success(function (data) {
//...

1) Note the URL: "localhost:55828/token" (not "localhost:55828/API/token")

2) Note the request data. Its not in json format, its just plain data without double quotes. "userName=xxx@gmail.com&password=Test123$&grant_type=password"

3) Note the content type. Content-Type: 'application/x-www-form-urlencoded' (not Content-Type: 'application/json')

4) When you use javascript to make post request, you may use following:

$http.post("localhost:55828/token", 
    "userName=" + encodeURIComponent(email) +
        "&password=" + encodeURIComponent(password) +
        "&grant_type=password",
    {headers: { 'Content-Type': 'application/x-www-form-urlencoded' }}
).success(function (data) {//...

See screenshots below from Postman:

Postman Request

Postman Request Header

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM