Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return data record from authentication #50

Closed
Baukereg opened this issue Apr 28, 2015 · 8 comments
Closed

Return data record from authentication #50

Baukereg opened this issue Apr 28, 2015 · 8 comments

Comments

@Baukereg
Copy link

I would like to return a data record from the authenticate request. Something like this:

{
   "token":"eyJhbGciOiJIUzI1NiIsIskdj........",
   "account":{
      "id":"account_1",
      "username":"Demo",
      "role":"CLIENT",
      "personKey":"client_1"
   }
}

Account should be deserialized to an account model record.

Is there any way to accomplish this in the current version of simple auth token?

@injaon
Copy link

injaon commented Apr 29, 2015

I have to deal with the same issue today. This is how I resolved it.

First, I modify my backend server (django) to return the user id with the token. So, with a succesfull authentication it returns something like this:

{
   "token": "eyJhbGciOiJIUzI1NiIsIskdj........",
   "empleado_id": 1234
}

Then, I created a custom session. When it receives the token it makes a secord request for the user data. This is the code:

/* app/initializers/crystal-session.js */

import Em from "ember";
import DS from "ember-data";
import Session from "simple-auth/session";

var CrystalSession = Session.extend({
    user: function() {
        var accountId = this.get('empleado_id');
        if (!Em.isEmpty(accountId)) {
            return DS.PromiseObject.create({
                promise: this.container.lookup('store:main').find('empleado', accountId)
            });
        }
        return null;
    }.property('empleado_id')
});

export default {
    name: 'crystal-session',
    before: "simple-auth",
    initialize: function (container, application) {
        application.register('session:crystal', CrystalSession);
    }
};

Please notice that my user is called empleado

Finally, let simple-auth know about this session. Edit your config/environment.js file with:

ENV['simple-auth'] = {
    session: 'session:crystal',
    /* other stuff here */   
}

@aibarra11
Copy link

Hello Injaon, Can you please show your controller code, particular the authenticate action that's triggered when submitting the username/password. I followed your example, but the user function isn't being triggered, so I'm wondering if you're using a regular ajax call or this.get('session').authenticate(authenticator, credentials) method in this package.

@thermokarst
Copy link

@aibarra11: I had implemented something based on @injaon's response, however I just realized that for what I am trying to do, this was probably overkill. I just reimplemented to something along these lines (see below). I completely removed the custom session initializer, and did the following in my login controller:

// app/pods/login/controller.js
import Ember from 'ember';
import parseBase64 from '../../utils/parse-base64';

export default Ember.Controller.extend({
  actions: {
    authenticate: function() {
      let credentials = this.getProperties('identification', 'password');
      let session = this.get('session');
      let authenticator = 'simple-auth-authenticator:token';

      session.authenticate(authenticator, credentials).then(() => {
        // parseBase64 just converts the base64 encoded string to a javascript object
        let t = parseBase64(session.get('secure.token'));
        // 'sub' is the user's id, as per the JWT draft specification
        this.store.find('user', t['sub']).then((user) => {
          // we can store the current user in the ember-simple-auth session
          session.set('currentUser', user);
        });
      }, (error)=> {
        // handle errors appropriately
      });
    }
  }
});

In my template I have access to the following:

{{session.currentUser.name}}

And my session in local storage looks like this:

{
  "secure": {
    "authenticator": "simple-auth-authenticator:token",
    "token": "TOKEN_DATA"
  },
  "currentUser": {
    "email": "testA",
    "name": "Test Admin User",
    "role": "A",
    "createdAt": "1901-01-01T00:00:00.000Z",
    "updatedAt": "1901-01-01T00:00:00.000Z"
  }
}

Not sure if that adheres to the usual best-practices or not, but it seems to work just fine for me. Any comments or suggestions are certainly welcome.

EDITED 6:40p AKDT: fixed double declaration of variable user

@aibarra11
Copy link

@thermokarst that works for me! hahaha, yeah.. I'm pretty sure i'm not following a bunch of best practices too, but at the rate the ember core changes and the rate i'm able to learn this, i'm happy no matter how i get it working =)

@Baukereg
Copy link
Author

@thermokarst I'm having trouble importing parseBase64 (cannot find import), nor can I find any additional info about it. Is it default Ember or an additional library?

@thermokarst
Copy link

@Baukereg: parseBase64 is a user-defined function (the import statement at the top: import parseBase64 from '../../utils/parse-base64';, utils is for user-defined functions). Sorry, I guess I didn't make it clear in my comments in the code snippet above, but parseBase64 is a function that I dropped into utils. I pulled that from ember-cli-simple-auth-token, you can find it here: https://github.com/thermokarst/hymenobacterdotinfo/blob/master/app/utils/parse-base64.js.

It's worth noting, when ember-simple-auth 1.0 came out I dropped ember-cli-simple-auth-token, and moved to a session-account service setup (https://github.com/thermokarst/hymenobacterdotinfo/blob/master/app/services/session-account.js).

@aalimovs
Copy link

aalimovs commented Mar 3, 2016

Another simple solution inspired by @thermokarst's session-account service, is to have an observer in the in the application's controller:

// app/pods/application/controller.js
import Ember from 'ember';

export default Ember.Controller.extend({
    session: Ember.inject.service('session'),

    setSessionClaims: Ember.observer('session.data.authenticated.token', function() {
        if(this.get('session.data.authenticated.token')) {
            try {
                let claims = JSON.parse(atob(this.get('session.data.authenticated.token').split('.')[1]));
            } catch (error) {
                return alert('Failed to JSON.parse(claims)');
            }
            this.set('session.data.authenticated.claims', claims);
        }
    }).on('init'),
});

or instead of the long session.data.authenticated.claims you could just set session.currentUser (thanks @thermokarst)

@thermokarst
Copy link

@aalimovs: thanks for posting this, I really like the idea of using an observer on the application's controller. Seems like for simple use cases this is simpler than setting up a service. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants