12
votes

I'm trying to understand how I can fit a custom JWT routing into loopbacks security model. My application has an authentication "dance" involving SMS that results in a valid JWT token using the excellent description. I'm using the jsonwebtoken and things work as expected. After obtaining the token my angular.js client sends the token with each request in the Authorisation: JWT ..token.. header (found conflicting documentation, one says JWT, one Bearer, but I can figure that out).

Now I want to make use of the token inside a loopback application. I'd like to use the ACL system loopback provides. I did read the following resources:

And I'm not clear what my next steps are. I have working:

  • User 'login' - generating a JWT
  • User login using username/password (to be retired)
  • Working ACL implementation in loopback (when I access an ACL protected resource I get, as expected a 4xx error)
  • My JWT token properly (?) in the header of the request

I need:

  • based on the JWT token a valid user with roles compatible to loopback ACL

Help is very much appreciated

1
Did you ever figure this out? - denislexic
Thx for reminding me. Yes I did. Answer below - stwissel
The authentication scheme for JWT tokens is "Bearer". - Fred

1 Answers

3
votes

The solution turned out to be much simpler that I though it would be. For starters loopback does use its own jwt webtokens to keep a (stateless) user session. After establishing identity (in my case extracting the mobile number from my JWT token) I just need to lookup the member and generate the loopback native JWT token. My endpoint definition was this:

  Member.remoteMethod(
    'provideSMSToken', {
      accepts: [{
        arg: 'mobilenumber',
        type: 'string',
        description: 'Phone number including +65 and no spaces'
      }, {
        arg: 'token',
        type: 'string',
        description: 'the token received through SMS'
      }],
      returns: {
        arg: 'token',
        type: 'string'
      },
      description: 'provide SMS token to confirm login',
      http: {
        path: '/smsauthenticate',
        verb: 'post'
      },
      isStatic: true
    }

  );

and the provideSMSToken function like that:

 // Exchange the SMS Token with a login token
  Member.provideSMSToken = function(mobilenumber, token, cb) {
    var app = Member.app;
    // CHeck if the token does exist for the given phone number
    // if yes, check for the respective memeber

    if (!app.smsVerificationToken || !app.smsVerificationToken[mobilenumber] || app.smsVerificationToken[mobilenumber] !== token) {
      var wrongToken = new Error("Wrong or missing token");
      cb(wrongToken, "Wrong or missing token");
    } else {
      var timetolive = 86400;
      Member.lookupByPhone(mobilenumber, function(err, theOne) {
        if (err) {
          cb(err, "Sorry, no such member here!");
        } else {
          // We can provide a token now for authentication
          // using the default createAccessToken method
          theOne.createAccessToken(timetolive, function(err, accesstoken) {
            cb(err, accesstoken);
          })
        }
      });
    }
  }

Works like a charm