paulvanbladel / aurelia-auth

:key: Authentication plugin for aurelia
200 stars 74 forks source link

Query: Unsupported grant type error #104

Closed richardbartley closed 8 years ago

richardbartley commented 8 years ago

NEWBIE question.

Trying to use the latest skeleton app and aurelia-auth and am stuck trying to authenticate against a web api project I have.

Following the login.js script,


login() {

        //var creds = "grant_type=password&email=" + this.email + "&password=" + this.password;
        var creds = "grant_type=password&username=" + this.email + "&password=" + this.password;

        return this.auth.login(creds)
            .then(response=>{
                console.log("success logged " + response);
            })
            .catch(err=>{
                err.json().then(function(e){
                    console.log("login failure : " + e.message);    
                });
            });
    };

the request to my URL is being made but it does not appear to be sending the grant type, username or password.

My response from Fiddler

HTTP/1.1 400 Bad Request
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 34
Content-Type: application/json;charset=UTF-8
Expires: -1
Server: Microsoft-IIS/10.0
X-SourceFiles: =?UTF-8?B?QzpcU2FuZGJveFxTb3VyY2VcYWR2YW50YWdlZG90bmV0XEFkdmFudGFnZS5XZWJBcGlcVG9rZW4=?=
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Date: Tue, 15 Mar 2016 16:31:43 GMT

{"error":"unsupported_grant_type"}

My authConfig.js looks like this;

var configForDevelopment = {

    httpInterceptor: true,
    loginOnSignup: true,
    baseUrl: '/',
    loginRedirect: '/#customer',
    logoutRedirect: '/',
    signupRedirect: '/login',
    loginUrl: 'https://localhost:44301/Token',
    signupUrl: '/auth/signup',
    profileUrl: '/auth/me',
    loginRoute: '/login',
    signupRoute: '/signup',
    tokenRoot: false,
    tokenName: 'token',
    tokenPrefix: 'aurelia',
    responseTokenProp: 'access_token',
    unlinkUrl: '/auth/unlink/',
    unlinkMethod: 'get',
    authHeader: 'Authorization',
    authToken: 'Bearer',
    withCredentials: true,
    platform: 'browser',
    storage: 'localStorage',
    providers: {

        identSrv : {
            name: 'identSrv',
            url: '/Token',
            authorizationEndpoint: 'https://localhost:44301', //if this ends with slash --> game over
            redirectUri: window.location.origin || window.location.protocol + '//' + window.location.host,
            scope: ['profile', 'openid'],

            responseType :'code',

            scopePrefix: '',
            scopeDelimiter: ' ',
            requiredUrlParams: ['scope', 'nonce'],
            optionalUrlParams: ['display', 'state'],
            display: 'popup',
            type: '2.0',
            clientId: 'jsclient',

            popupOptions: { width: 452, height: 633 }
        },

        google: {
            //responseType :'code',
            clientId: '239531826023-ibk10mb9p7ull54j55a61og5lvnjrff6.apps.googleusercontent.com',
            state: function(){
                var val = ((Date.now() + Math.random()) * Math.random()).toString().replace(".", "");
                return encodeURIComponent(val);
            }
        } 
        ,
        linkedin:{
            clientId:'778mif8zyqbei7'
        },
        facebook:{
            clientId:'1452782111708498'
        }
    }
};

Any help or pointers appreciated.

Thanks, Richard.

RWOverdijk commented 8 years ago

@richardbartley Use an object in stead of a string.

paulvanbladel commented 8 years ago

Please take a look at https://github.com/paulvanbladel/aurelia-identityserver-aspnetcore

richardbartley commented 8 years ago

Object seemed to make no difference.

Raw view of what ends up getting sent is;

OPTIONS https://localhost:44301/Token HTTP/1.1
Host: localhost:44301
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:49849
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
Access-Control-Request-Headers: accept, authorization, content-type
Accept: */*
Referer: http://localhost:49849/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en;q=0.8,en-US;q=0.6

I can authenticate the old classic way with a simple ajax call.

var loginData = {
            grant_type: 'password',
            username: self.loginEmail(),
            password: self.loginPassword()
        };

        $.ajax({
            type: 'POST',
            url: baseUrl + '/Token',
            data: loginData
        }).done(function (data) {
            self.user(data.userName);
            // Cache the access token in session storage.
            sessionStorage.setItem(tokenKey, data.access_token);
        }).fail(showError);

I can see what the fetch method should be doing in authService.js...just for me doesn't want to play. Clearly I must be doing something wrong here.

return this.http.fetch(loginUrl, {
              method: 'post',
              headers: typeof content === 'string' ? { 'Content-Type': 'application/x-www-form-urlencoded' } : {},
              body: typeof content === 'string' ? content : json(content)
            }).then(authUtils.status).then(function (response) {
              _this2.auth.setToken(response);
              return response;
            });
RWOverdijk commented 8 years ago

@richardbartley Perhaps your problem is with the types the server accepts? I'm pretty sure that using an object works (over at our fork anyway, because that's how we use it, too).

The data you pasted doesn't include the payload it's sending to the server, could you try logging that for us?

richardbartley commented 8 years ago

CORS related issue maybe? Fetch API cannot load https://localhost:44301/Token. Response for preflight has invalid HTTP status code 400

richardbartley commented 8 years ago

Rejecting the preflight OPTIONS request.....

richardbartley commented 8 years ago

For anyone else struggling with CORS and Web Api when using fetch, eventually I found the problem was that the preflight OPTIONS request was being rejected on the server. Doing a $.ajax call always worked as no pre-flight was made (in Chrome at least). Just fetch caused the issue.

The way to resolve this was ultimately solved here [http://stackoverflow.com/questions/25794439/webapi-2-with-owin-middleware-and-token-based-authentication-options-request-re] by overriding the MatchEndPoint method in the OAuthAuthorizationServerProvider derived class.

public override Task MatchEndpoint(OAuthMatchEndpointContext context)
        {
            if (context.OwinContext.Request.Method == "OPTIONS" && context.IsTokenEndpoint)
            {
                context.OwinContext.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST" });
                context.OwinContext.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "accept", "authorization", "content-type" });
                context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
                context.OwinContext.Response.StatusCode = 200;
                context.RequestCompleted();

                return Task.FromResult<object>(null);
            }

            return base.MatchEndpoint(context);
        }
paulvanbladel commented 8 years ago

@richardbartley thanks a lot for the update Richard. Take care. paul.

ahedreville commented 6 years ago

Do not want to work for me.. anyway I solved from the reply https://github.com/SpoonX/aurelia-authentication/issues/234

I need to pass more parameters for my server... and it works

this.authService.login({ username: 'jdoe@foo.com', password: 'mysecret', grant_type: 'password' }, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}});

ahedreville commented 6 years ago

A better option is to add the following to your config

defaultHeadersForTokenRequests: // Default headers for login and token-update endpoint {'Content-Type': 'application/x-www-form-urlencoded'},

It works too