Loopback: will consider use jwt to replace uid2 generate access token?

Created on 20 Dec 2015  Â·  27Comments  Â·  Source: strongloop/loopback

Json Web Tokens seems better than normal 64 length uid2 string.

Why not change to jwt?
https://tools.ietf.org/html/rfc7519

discussion stale

Most helpful comment

We can implement manualy by some scripts. This is my code:

server.js

Disable bearerTokenBase64Encoded by adding this before booting:

app.use(loopback.token({
  model: app.models.accessToken,
  currentUserLiteral: 'me',
  bearerTokenBase64Encoded: false // here
}));

boot

Create a js file (ex: jwt.js) in boot directory and place this code:

'use strict';
const jwt = require('jsonwebtoken');
const secretKey = process.env.JWT_SECRET_KEY || null;

module.exports = function(app) {
  const User = app.models.User;
  const AccessToken = app.models.AccessToken;

  User.prototype.createAccessToken = function(ttl, cb) {
    const userSettings = this.constructor.settings;
    const expiresIn = Math.min(ttl || userSettings.ttl, userSettings.maxTTL);
    const accessToken = jwt.sign({id: this.id}, secretKey, {expiresIn});
    return cb ? cb(null, Object.assign(this, {accessToken})) : {id: accessToken};
  };

  User.logout = function(tokenId, fn) {
    // You may want to implement JWT blacklist here

    fn();
  };

  AccessToken.resolve = function(id, cb) {
    if (id) {
      try {
        const data = jwt.verify(id, secretKey);
        cb(null, {userId: data.id});
      } catch (err) {
        // Should override the error to 401
        cb(err);
      }
    } else {
      cb();
    }
  };
};

Remember to install jsonwebtoken package.

All 27 comments

+1

+1

+1
On 19 Jun 2016 20:17, "Dilshan Rajapakse" [email protected] wrote:

+1

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/strongloop/loopback/issues/1905#issuecomment-227001145,
or mute the thread
https://github.com/notifications/unsubscribe/AHvuCM9hEQ5fsVMi57TeK9NWr-DR3p_uks5qNVZ-gaJpZM4G42WI
.

+1

I agree, at least this should be possible to integrate as a configuration flag or plugin

+1

We can implement manualy by some scripts. This is my code:

server.js

Disable bearerTokenBase64Encoded by adding this before booting:

app.use(loopback.token({
  model: app.models.accessToken,
  currentUserLiteral: 'me',
  bearerTokenBase64Encoded: false // here
}));

boot

Create a js file (ex: jwt.js) in boot directory and place this code:

'use strict';
const jwt = require('jsonwebtoken');
const secretKey = process.env.JWT_SECRET_KEY || null;

module.exports = function(app) {
  const User = app.models.User;
  const AccessToken = app.models.AccessToken;

  User.prototype.createAccessToken = function(ttl, cb) {
    const userSettings = this.constructor.settings;
    const expiresIn = Math.min(ttl || userSettings.ttl, userSettings.maxTTL);
    const accessToken = jwt.sign({id: this.id}, secretKey, {expiresIn});
    return cb ? cb(null, Object.assign(this, {accessToken})) : {id: accessToken};
  };

  User.logout = function(tokenId, fn) {
    // You may want to implement JWT blacklist here

    fn();
  };

  AccessToken.resolve = function(id, cb) {
    if (id) {
      try {
        const data = jwt.verify(id, secretKey);
        cb(null, {userId: data.id});
      } catch (err) {
        // Should override the error to 401
        cb(err);
      }
    } else {
      cb();
    }
  };
};

Remember to install jsonwebtoken package.

@thanh-taro Thanks for your code! But when i have the token, I passed it in header of the request:
Authorization JWT jwt_code I get invalid token

Can you help me more here? Thank you

@vinhtq Change Authorization JWT jwt_token to Authorization Bearer jwt_token. Good luck!

@thanh-taro Just try few hours ago. When I debug I figure out that

const data = jwt.verify(id, secretKey);
cb(null, {userId: data.id});

It can go here but I still have authorization required error. Seems like we need a way to tell loopback that we use jwt strategy instead right?

@thanh-taro Sorry, I figure out. I config the role wrong for the model I want to get info out.

Now it works.

I am trying to integrate social login also using jwt. Can you give me any idea how to do so?

Basically social account has no username + password!

Thank you!

@vinhtq The idea is:
step 1: use social access_token from clients (FE, mobile,...) to get user information from social networks.
-> you will have email, name, etc.
step 2: use email (or social account ID) to create a new user (or migrate with the old one).
step 3: create a JWT token and send it back to clients. You are done.

@thanh-taro Thanks! You save my day!

Any updates on that?
It should be done for lb3.
Using jwt would speed up loopback as user data and all roles would be in the token so no db queries at all.

+1
I would like to know about this with respect to lb3 too!

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS file at the top-level of this repository.

+1 for native support for jwt

+1 for native support for jwt

We're working on the next major version of loopback here: https://github.com/strongloop/loopback-next

Make an issue suggesting JWT support, or even better, ask to join the loopback-next group! We're looking for more community contributors to help build the new version. :)

@thanh-taro can you give us an example how to blacklist JWT?

@husnulhamidiah Sorry for late reply.
Simply, you can create a blacklist table in your DB and save JWT tokens when user logout. Then, you have to add some code to AccessToken.resolve to check that token in the blacklist table.
Or, if you don't care about scalable, you can save logout token in cache, file,...
Or, better way is storing on Redis. Good luck!

@thanh-taro
Thank you for the code snippet above regarding implementing JWT by means of scripts.
I am getting "invalid algorithm" when i try to make a POST request to a model configured with ACL - which does not have write access to a certain route if un-authenticated.

Any ideas how to proceed further?
Thanks.

@AurelianTimu You may need to take a look at JWT algorithm:

  1. https://github.com/auth0/node-jsonwebtoken#jwtsignpayload-secretorprivatekey-options-callback
  2. https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback

There are some issues that may be the same of your case:

  1. https://github.com/auth0/node-jsonwebtoken/issues/83
  2. https://github.com/auth0/node-jsonwebtoken/issues?q=is%3Aissue+invalid+algorithm+is%3Aclosed

Hi. Got 500 - JWT malformed when trying to make a login (post). Using the thanh-taro code.

@thanh-taro's solution worked fine for ~4 weeks until now when I tried using built-in reset password logic. After spending ~2 hours debugging why it doesn't work, I have figured out that I had changed the AccessToken creation behavior (for JWT) and reset password's built in logic also depends on it.

Do we have any good alternative for this JWT hack?

We can implement manualy by some scripts. This is my code:

server.js

Disable bearerTokenBase64Encoded by adding this before booting:

app.use(loopback.token({
  model: app.models.accessToken,
  currentUserLiteral: 'me',
  bearerTokenBase64Encoded: false // here
}));

boot

Create a js file (ex: jwt.js) in boot directory and place this code:

'use strict';
const jwt = require('jsonwebtoken');
const secretKey = process.env.JWT_SECRET_KEY || null;

module.exports = function(app) {
  const User = app.models.User;
  const AccessToken = app.models.AccessToken;

  User.prototype.createAccessToken = function(ttl, cb) {
    const userSettings = this.constructor.settings;
    const expiresIn = Math.min(ttl || userSettings.ttl, userSettings.maxTTL);
    const accessToken = jwt.sign({id: this.id}, secretKey, {expiresIn});
    return cb ? cb(null, Object.assign(this, {accessToken})) : {id: accessToken};
  };

  User.logout = function(tokenId, fn) {
    // You may want to implement JWT blacklist here

    fn();
  };

  AccessToken.resolve = function(id, cb) {
    if (id) {
      try {
        const data = jwt.verify(id, secretKey);
        cb(null, {userId: data.id});
      } catch (err) {
        // Should override the error to 401
        cb(err);
      }
    } else {
      cb();
    }
  };
};

Remember to install jsonwebtoken package.
you are my hero bro!

Was this page helpful?
0 / 5 - 0 ratings