jeyzorus
jeyzorus

Reputation: 125

Nodejs Restify - Valide Jwt id_token with jwks

We develop an application with VuejS in front and an api Nodejs(Restify) in back. We use a third party for give us authentification (Identity provider with OpenId Connect protocole).

So with VueJs we can authenticate, get an access_token and id_token and we pass it in each nodejs request header with bearer.

Now we need to verify,in back, if this token is valid and if the user can access this routes.

Our Identity provider give us an endpoint (jwks_uri) with a keys like:

{
  "keys": [
    {
      "kty": "RSA",
      "kid": "AXDJKLFJDLKFJLKJFLKSJDFLKJSFL",
      "e": "AQAB",
      "n": "2T3QDw6gcSDFS........................VRtQSDQSDQSDQSD"
    }
  ]
}

I extracted public key from this and the results is something like:

-----BEGIN PUBLIC KEY-----
MIIB......................OCAQ8AMIIBCgKCAQEA2T3QDw6gcqrTZRy74XWy
Bn0JoQzg/H2QX.............................................fqX13O
4QIDAQAB
-----END PUBLIC KEY-----

Now i want to verify the id_token with this public key i try something like this

jwt.verify(token, publicKey, { algorithms: ['RS256'] }, function(err, decoded) {
    //This will display the decoded JWT token.
    console.log(decoded)  
});
  1. But i dont know how to use correctly verify to check validity ? claims ?

  2. Do I have to redo the same treatment each time for each road I want to protect? something like this ?

server.get('/data1', async function (req, res, next) {
    try {
        helper.validAccessToken(req).then(function(res) => {
            if(res){
                data=getData();
                res.send(data) ;
            } else{
                res.send(401, {message: 'Unauthorizd'}) 
            }
        });
    } catch (err) {

        return next(err);
    }
});

Upvotes: 0

Views: 584

Answers (2)

jeyzorus
jeyzorus

Reputation: 125

Finally i was inspired by your proposal.

I implemented a function that checks the token and add a req attributes. This function I use as "middleware"

 async function authUser(req, res, next) {
  try{    
    req.isLogged=false
    console.log(req.params);
    let isvalid = await validAccessToken(req);
    console.log(">>> isValid : " + isvalid);
    if(isvalid===true){
      //token verifié on passe en preview false
      req.isLogged=true
      return next()
    }else{
      console.log("Unauthorized");
      req.isLogged=false
      return next()                
    }
  }catch(error){

    res.send(401, 'Unauthorized ' + error)
    return next()
  }
}

I put the function like a middleware in restify server:

server.use(openid.authUser);

After this, in each routes i want to secure, i check this attribute:

const preview = ! req.isLogged ;

Upvotes: 0

aleksxor
aleksxor

Reputation: 8380

I believe the optimal way for small to medium sized application is just to make jwt verification work as a middleware. Something like:

// authUser.js

module.exports = function authUser(req, res, next) {
    const token = getJwtToken(req)
    jwt.verify(token, publicKey, { algorithms: ['RS256'] }, function(err, decoded) {
        if (err) {
          res.send(401, 'Unauthorized')
          return next(false)
        }
        return next()
    })
}

And include it into the middleware chain for the routes you want to restrict access to.

server.get("/secure", authUser, function (req, res, next) {
  res.send(200, "secure route response");
  return next();
});

server.get("/", function (req, res, next) {
  res.send(200, "public route response");
  return next();
});

codesandbox link

For large application I believe you'd need something more flexible and configurable. Ability to introduce different security levels and auth strategies. And more flexible route configurations.

Upvotes: 1

Related Questions