Can't get currentUser with Ember simple auth

Hi, i am struggling with getting the currentUser in a session when authenticated. I am trying to get current User with dedicated endpoint /users/me but I don’t receive any query parameters so that I can get fetch it by username. I am using Express.js backend

Here is my current-user service:

import Service from '@ember/service';
import { inject as service } from '@ember/service';
import RSVP from 'rsvp';

export default Service.extend({
    session: service(),
    store: service(),

    load() {
      console.log(this.get('session.isAuthenticated'));
      if (this.get('session.isAuthenticated')) {
        return this.get('store').queryRecord('user', { me: true }).then((user) => {
          console.log('user: ', user );
          this.set('user', user);
        });
      } else {
        return RSVP.resolve();
      }
    }
});

Here is the user.js adapter which I got from the ESA guide:

import ApplicationAdapter from './application';

export default ApplicationAdapter.extend({
    urlForQueryRecord(query) {
        if (query.me) {
          delete query.me;
          return `${this._super(...arguments)}/me`;
        }
    
        return this._super(...arguments);

    }
});

This is the /users/me endpoint:

router.get('/users/me',  asyncHandler(async (req, res, next) => {
    console.log(req.query);
    console.log(req.body);
}));

I think I missunderstood something. Thank you for any help :slight_smile:

Can you show response from server (development tools in browser)?

Thank you for your message.

I did a workaround where I send the users id in the /token route as the secret token

res.status(200).send(`{ "access_token": "${docs[0]._id}"}`);

It it is not like the currentUser I believe but i finally receive the id so I can query by user-id.

To your question, the response are 2 empty objects. It reaches the endpoint but does not have any query parameters to work with

If I’m understanding this correctly I’d think you’d want your Ember app to make a request to /users/me (sounds like that part is working fine) and it should send the token as part of the headers in that request (should already be happening if your authentication is set up correctly), so in your backend you should use the auth token to determine the correct user and return it from the endpoint.

The route that’s sends the token is /token and I thought you need to have a additional route /users/me to receive the currentUser, that what atleast I got from the ESA-Guide. Now, I have the /token route that sends the user-id.

router.post('/token', asyncHandler(async (req, res, next) => {
    if (req.body.grant_type === 'password') {
        try {
            const { username, password } = req.body;
            await User.find({ email: username }, async (err, docs) => {
                if (docs.length !== 0) {
                    if (docs[0].password === password) {
                        res.status(200).send(`{ "access_token": "${docs[0]._id}"}`);
                        next();
                    } else {
                        bcrypt.compare(password, docs[0].password, (error, val) => {
                            if (error) {
                                next(error);
                            }
                            if (val) {
                                res.status(200).send(`{ "access_token": "${docs[0]._id}" }`);
                                next();
                            } else {
                                res.status(400).send('{"error": "invalid_grant"}');
                                next();
                            }
                        });
                    }
                } else {
                    res.status(400).send('{"error": "invalid_grant"}');
                    next();
                }
            });
        } catch (error) {
            next(error);
        }
    } else {
        res.status(400).send('{ "error": "unsupported_grant_type" }');
    }
}));

Could it be that this was how it suppose to be in the first place ?

So you’re just returning the user id as the authentication token? I want to preface this by saying I’m not an auth expert by any means but I’m fairly certain that would be a huge security risk. A token should be something that is arbitrary and hard to guess, and revokable. Each session should have a unique token. Let’s imagine that someone logged in using this authentication scheme and used their own user id as their token for every request. That means that every time they authenticated they would get the same token (because it’s their user id), and furthermore anyone who know their user id could submit authorized requests to the API without ever having established a session.

This is probably a bad analogy but imagine you had a coat check at a high-end restaurant (lots of expensive coats!). You give someone your coat (data) and they give you a ticket or tag or something with a number on it (token). That number is then associated with your coat. So to get your coat you have to have that number. Now imagine the same scenario but instead of a number the coat check just uses your last name. To get your coat back all someone, anyone, would need is your name. Probably a lot easier to get than your coat check tag.

Again I’m no expert here but I’ve worked with multiple authentication systems and ember simple auth, and I’m fairly certain the way this should work is like this:

  1. user (via client app) sends authentication request with username/password
  2. assuming credentials are correct, server creates a session and token, and sends token back to client in whatever response format is required by the auth spec you are implementing (OAuth, etc)
  3. Client receives token and stores it in session service, and attaches it to every outgoing API request to authorize said requests
  4. Client makes a request to GET /users/me (with token in auth header of the request)
  5. Server takes token, looks up session information (which i believe should include user id) and returns the correct user record
  6. User sees their name/email/etc and is comforted. They remembered their password, and the server remembered them. Much rejoicing.

Oh one other way I think you could return the user id is encoded as part of a json web token (JWT). So instead of returning just an access token you return extra data along with it. I think that means you’d need a jwt decoder on the front-end but it’s been a while and I kinda forget how all that part worked. I personally would recommend using the current oauth spec as a starting point, and there are probably server libraries for any framework/language that implement it.

I use MongoDB as the database which means it receives an hexstring of the objectid which is unique. I could also additionally hash it ? So that the userId that is responsed is a hashed objectid

I don’t think that would mitigate the security risks at all, I think your token should be revokable (and therefore temporary) and not directly related to anything other than a session

1 Like

Thank you for your advice, I will remove that. I will try to do the jwt way. I basically just need some information of the authenticated user so I can fetch data by the user.

try to use ember service