Kim Lindqvist
Kim Lindqvist

Reputation: 393

Identity Server 4 for NodeJS API

I'm trying to figure out how to do the identity server 4 authentication below using NodeJS - way out of my comfort zone here.

services.AddAuthentication(IdentityServerAuthenticationDefaults
.AuthenticationScheme)
    .AddIdentityServerAuthentication(
         options =>
         {
          options.Authority = "<authority-url>";
          options.ApiName = "<api-url>";
          });

I'm missing something in the flow here as the C# implementation isn't provided a secret or similar - so the token is probably verified via identity server? How would I verify the token using NodeJS if I don't have a 'secret' to verify it with?

I've stumbled on introspection endpoint - am I heading in the right direction?

Upvotes: 6

Views: 9557

Answers (3)

Abolfazl Roshanzamir
Abolfazl Roshanzamir

Reputation: 14872

If you want only to validate your token you can use the following package:

npm install token-introspection --save

This package is configured with endpoint and client credentials, and a function is returned. Calling that function with token, and optional token_type_hint will return a Promise.

const tokenIntrospection = require('token-introspection')({
    endpoint: 'https://example.com/introspect',
    client_id: '<Client ID>',
    client_secret: '<Client Secret>',
});
 
tokenIntrospection(token).then(console.log).catch(console.warn);

Example :

Here is a middleware to validate the token :

module.exports = (req, res, next) => {
    
    const token = "wEvxS0y2TkvCjLpKP33oGTK0BcKUb6MHt1u3AeMu8h4"; // get your token from your request 

    const tokenIntrospection = require('token-introspection')({
        endpoint: 'http://localhost:5000/connect/introspect',
        client_id: 'api1',
        client_secret: 'apisecret',
    });
    tokenIntrospection(token).then(result => {
        console.log(result);
        next();
    }).catch(console.warn);
}

then you can use it as below :

const auth = require('./atuh')

app.get('/', auth, (req, res, next) => {
    res.send("Hi");
})

Upvotes: 0

Nima Maskani
Nima Maskani

Reputation: 85

The accepted question is right. but i wanted to fix some of it's trial errors. you can easily (it took me 4 days) add authentication to your express api with ids4. it's how its work:

creating a middleware:

const jwt = require("express-jwt"),
jwksClient = require("jwks-rsa");

const auth = jwt({
  secret: jwksClient.expressJwtSecret({
    cache: true, // see https://github.com/auth0/node-jwks-rsa#caching
    rateLimit: true, // see https://github.com/auth0/node-jwks-rsa#rate-limiting
    jwksRequestsPerMinute: 2,
    jwksUri: `${issuer}/.well-known/openid-configuration/jwks`,
  }),

  audience: "api1.resource", // <---- its your api resource.
  issuer: issuer, // <----- address of identityserver4.
  algorithms: ["RS256"], //<----- its needed algorithm to handle secret.
});

The following auth middleware is like following code in .net:

services.AddAuthentication(IdentityServerAuthenticationDefaults
.AuthenticationScheme)
    .AddIdentityServerAuthentication(
         options =>
         {
          options.Authority = "<authority-url>";
          options.ApiName = "<api-url>";
          });

to secure a nodejs route you can use following example:

// this is the secured route by identityserver4
// the jwt module set the ids4 auth result in req.user object
// so you can use it to access logged in user claims and stuff.
// for example testing with client credentials it return some info about the jwt token sent to the /me endpoint.
app.get("/me", auth, (req, res) => {
  const user = req.user;
  debug("req.user: %O", user);

  return res.json(user);
});

// this a unsecured route. so anyone can call this route without any restrictions.
app.get("/", (req, res) => {
  return res.send("Hello");
});

It takes me so long to find how to secure nodejs or express with identityserver4 but it was as simple as it look like.

The code here is from the following identityserver4 community example with full ids4 and node api and javascript client and .net console client: https://github.com/lyphtec/idsvr4-node-jwks

There is a good documentation about this example in its own github repository too.

You can download the node api and run it with yarn start or npm run start.

I tested it with client credentials flow and it worked like a charm.

Wish all of you luck.

Upvotes: 3

Kim Lindqvist
Kim Lindqvist

Reputation: 393

I was able to solve this using the jwks -endpoint and it's public keys to verify tokens and then I also found a nice package that I used to prepare the middleware:

private issuer: string = process.env.idsrv;


auth = jwt({
    secret: jwksClient.expressJwtSecret({
        cache: true,        // see https://github.com/auth0/node-jwks-rsa#caching,
        cacheMaxAge: ms('24h'),
        rateLimit: true,    // see https://github.com/auth0/node-jwks-rsa#rate-limiting
        jwksRequestsPerMinute: 100,
        jwksUri: `${this.issuer}/.well-known/jwks`
    }),

    // validate the audience & issuer from received token vs JWKS endpoint
    audience: `${this.issuer}/resources`,
    issuer: this.issuer,
    algorithms: ["RS256"]
});

Upvotes: 5

Related Questions