Problem with authentication (ember-simple-auth) and jwt


#1

Hi everyone, i have one problem with ember-simple-auth with jwt. In the backend a i have a api rest with django, the form login work well, but i found a bug in the process. For example, after login, ember-simple-auth add this item in the localStorage:

{"authenticated":{"authenticator":"authenticator:jwt","token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6Im1hcnRpbnBldmVyaUBnbWFpbC5jb20iLCJ1c2VybmFtZSI6ImFkbWluIiwidXNlcl9pZCI6MSwiZXhwIjoxNTE0MDM4MDc0fQ.uDVXtBkuC3Pn6xmW5Wk5fNvgz1x__ptCM_smZc0KV_c","user":{"id":1,"last_login":"2017-12-22T10:22:48.290117-03:00","is_superuser":true,"username":"admin","first_name":"","last_name":"","email":"martinpeveri@gmail.com","is_staff":true,"is_active":true,"date_joined":"2017-12-22T10:15:58.526730-03:00","position":null,"department":null,"photo":null,"rol":1,"groups":[],"user_permissions":[]}}}

And I repeat it works well, but i close the session and go to set manually in localStorage on the browser this code, authentic automatically. It is a terrible security error. Surely something will be wrong.

This is my code:

My method authenticate:

authenticate() {
            let { user, password } = this.getProperties('user', 'password');

            if(!isPresent(user) || !isPresent(password)) {
                this.set('errorMessage', this.get('i18n').t('auth.login.error'));
            } else {
                this.get('session').authenticate('authenticator:jwt', user, password).catch((reason) => {
                    this.set('errorMessage', reason.responseJSON.non_field_errors);
                });
            }
        }

My adapter:

import DS from 'ember-data';
import ENV from '../config/environment';
import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin';

export default DS.RestAdapter.extend(DataAdapterMixin, {
    namespace: ENV.APP.API_NAMESPACE,
    host: ENV.APP.API_HOST,
    buildURL: function(type, id) {
        var url = this._super(type, id);

        if (url.charAt(url.length -1) !== '/') {
          url += '/';
        }

        return url;
    },
    authorizer: 'authorizer:jwt',
});

My authenticators:

import Ember from 'ember';
import Base from 'ember-simple-auth/authenticators/base';
import ENV from '../config/environment';

const { RSVP: { Promise } } = Ember;

export default Base.extend({
    tokenEndpoint: ENV.APP.API_HOST + '/' + ENV.APP.API_NAMESPACE + '/token-auth/',
    restore(data) {
        return new Promise((resolve, reject) => {
            if (!Ember.isEmpty(data.token)) {
                resolve(data);
            } else {
                reject();
            }
        });
    },
    authenticate(identification, password) {
        const requestOptions = {
            url: this.tokenEndpoint,
            type: 'POST',
            contentType: "application/x-www-form-urlencoded",
            data: {
                username: identification,
                password: password,
            },
        };
        return new Promise((resolve, reject) => {
            Ember.$.ajax(requestOptions).then((response) => {
                //let jwt = response.data.token;
                //let user = response.data.user;
                let jwt = response.token;
                let user = response.user;
                Ember.run(() => {
                    resolve({
                        token: jwt,
                        user: user,
                    });
                });
            }, (error) => {
                Ember.run(() => {
                    reject(error);
                });
            });
        });
    },
    invalidate(data) {
        return Promise.resolve(data);
    }
});

My authorizer:

import Base from 'ember-simple-auth/authorizers/base';
import Ember from 'ember';

export default Base.extend({
    session: Ember.inject.service(),
    authorize(data, block) {
        if (Ember.testing) {
            block('Authorization', 'jwt beyonce');
        }
        const { token } = data
        if (this.get('session.isAuthenticated') && token) {
            block('Authorization', `jwt ${token}`);
        }
    }
});

How can I get around this? A refresh token capable? I’m not sure.

Thanks!!


#2

I found the solution, added verify token url in the backend and in the frontend added this code in the custom authenticator in the method restore:

verifyTokenEndpoint: ENV.APP.API_HOST + '/' + ENV.APP.API_NAMESPACE + '/api-token-verify/',
    restore(data) {
        return new Promise((resolve, reject) => {
            if (!Ember.isEmpty(data.token)) {
                const requestOptions = {
                    url: this.verifyTokenEndpoint,
                    type: 'POST',
                    contentType: "application/x-www-form-urlencoded",
                    data: {
                        token: data.token,
                    },
                };
                let promise = new Promise((resolve, reject) => {
                    Ember.$.ajax(requestOptions).then(() => {
                        resolve();
                    }, () => {
                        reject();
                    });
                });

                return promise.then(() => {
                    resolve(data);
                }).catch(() => {
                    reject();
                })
            } else {
                reject();
            }
        });
    },

Now work well :slight_smile: