websanova / vue-auth

A simple light-weight authentication library for Vue.js
MIT License
2.36k stars 380 forks source link

token doesn't persist, suggested behavior vs Oauth 2.0 RFC spec? #688

Closed thebleucheese closed 2 years ago

thebleucheese commented 2 years ago

I'm using a FastAPI backend, and I'm following the v3 demo. access_token returns fine from my login URL

{"access_token":"eyJhbGciOiJIUzI1N...","token_type":"bearer"}

but doesn't persist anywhere and Authorization Header Bearer token isn't set in the request when fetching data from /auth/user. the /auth/user fetchUser() call returns a 401

I found something similar to this in these two issues: https://github.com/websanova/vue-auth/issues/640 https://github.com/websanova/vue-auth/issues/628

I think the suggestion there is to add the Authorization as a Header variable from the server response? Maybe I'm misunderstanding... I'd prefer not to do that as it's not in the Oauth2.0 spec:

Oauth 2.0 RFC https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.4

     HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
     Cache-Control: no-store
     Pragma: no-cache

     {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600,
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
       "example_parameter":"example_value"
     }

My auth setup is as follows:

export default (app) => {
    app.use(createAuth({
        plugins: {
            http: app.axios,
            router: app.router,
        },
        drivers: {
            http: driverHttpAxios,
            auth: driverAuthBearer,
            router: driverRouterVueRouter
        },
        options: {
            tokenDefaultKey: 'access_token',
            //stores: ['storage', 'cookie'],
            stores: ['storage'],
            notFoundRedirect: {name: 'user-account'},
            fetchData: {
                url: '/auth/user',
                method: 'GET',
                enabled: true
            }
        }
    }));
}

and login method in useAuthComp.js is as follows:

 function login(username, password, staySignedIn) {
        return new Promise((resolve, reject) => {
            auth.login(
            {
                url: 'auth/token',
                headers: {
                  "Content-Type": "application/x-www-form-urlencoded",
                },
                staySignedIn: true,
                data: new URLSearchParams({username: username, password: password}).toString(), 
                success: function() {
                  console.log("Login success.");
                },
                error: function() {
                  console.log("Login failure.");
                },
                remember: false,
                fetchUser: true,
                redirect: '/',
              }

            )
            .then((res) => {
                console.log("RES: ", res)

                resolve(res);
            }, reject);
        });
    };

Do I need to manually pull the access_token out? Is something weird happening because I'm using 127.0.0.1 or localhost and two separate ports? (vite is hosting at 3000 and FastAPI at 8000) Any nudge in the right direction would help. Thanks!

websanova commented 2 years ago

I believe you should just need a custom driver:

https://github.com/websanova/vue-auth/tree/master/src/drivers/auth

The one you currently have set is "bearer" which will look for the token in the "authorization" header:

https://github.com/websanova/vue-auth/blob/master/src/drivers/auth/bearer.js

So basically you just need to make a custom version of one of those drivers to match what you have.

thebleucheese commented 2 years ago

I believe you should just need a custom driver:

https://github.com/websanova/vue-auth/tree/master/src/drivers/auth

The one you currently have set is "bearer" which will look for the token in the "authorization" header:

https://github.com/websanova/vue-auth/blob/master/src/drivers/auth/bearer.js

So basically you just need to make a custom version of one of those drivers to match what you have.

Ah ok, thanks! This is really easy now that I understand what the driver's doing. I got thrown off by the tokenDefaultKey param I was seeing in the options. I read through the code and realized tokenDefaultKey is for the stored key rather than the key to parse out of the token response body using an Oauth2 password bearer flow.

Here's a really quick and dirty driver that works (so far) with FastAPI's default password bearer implementation.


export default {

    request: function (req, token) {
        this.drivers.http.setHeaders.call(this, req, {
            Authorization: 'Bearer ' + token
        });
    },

    response: function (res) {
        const httpData = this.drivers.http.httpData(res)

        let token
        if(httpData.hasOwnProperty('access_token'))
            token = httpData['access_token']

        if (token) {
            return token.trim();
        }
    }
};