Developing a Secure API with NestJS

Hi, thanks for the excellent tutorial, but I had problems with the implementation of this API, because I don’t understand how the frontend works, if I need to add a token in the request header to the Auth0. Can you show the frontend code of this application?

1 Like

Thank you for joining the Auth0 community and for your kind feedback :slight_smile:

:pray: Sorry for the late reply. I missed the notification. It’s definitely in the works to release the client application with a tutorial. I’ve been making some tweaks as the current app uses a demo launcher to bootstrap the Auth0 values.

Right now that client is built with React and RxJS. Is that an architecture that interests you?

My goal is to provide it in both React and Angular. I think that for React it may be more mainstream to use the Context API instead of RxJS.

Adan, I am currently working on this to simplify the client application and its corresponding tutorial.

@zacksinclair, @mob, @jajaperson and anyone else who may know: Is there a best practice or commended way to initiate a module such as MongooseModule using an environmental variables? I essentially need to use a secret in the connection string to MongoDB Cloud but I have not found an easy way to make this work with the existing ConfigModule and ConfigService.

The goal is to have something like this:

@Module({
  imports: [
    ConfigModule.forRoot(),
    MenusModule,
    LocationsModule,
    ItemsModule,
    MongooseModule.forRoot(
      `mongodb+srv://<USERNAME>:<PASSWORD>@someclustername.mongodb.net/test?retryWrites=true&w=majority`,
    ),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

But I’d like USERNAME and PASSWORD to come from an .env file.

Thank you for any insight you may provide me on this :slight_smile:

I think this may be the best way :thinking:

1 Like

Dan I responded to the email! Yes the user guide works except it’s designed to use with mogoose and I wanted to use mongoDb so this is what I did:

In the app.module I wrote

//app.module

import { Module } from '@nestjs/common';
import { ItemsModule } from './items/items.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Item } from './items/item.entity';
import * as dotenv from 'dotenv';

dotenv.config();

@Module({
 imports: [ItemsModule, TypeOrmModule.forRoot({
   type: 'mongodb',
   url: process.env.URL,
   database: process.env.DATABASE,
   entities: [Item],
   synchronize: true
})],
 controllers: [],
 providers: [],
})
export class AppModule { }

Then I wrote the service like this:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { getMongoRepository } from 'typeorm';
import { Item } from './item.entity';


@Injectable()
export class ItemsService {

 manager = getMongoRepository(Item);

 async create(newItem: Item): Promise<void> {
   try {
     await this.manager.insert(newItem);
  } catch (err) {
     return err;
  }
}
}

I used the MongoDB TypeORM definition
https://github.com/typeorm/typeorm/blob/master/docs/mongodb.md

As far as dotEnv I really did not have problems.

Hope this helps,

Adan

Really great tutorial.

Suggest to change the example so that the audience variable ends with a “/”.

I just spent over an hour trying to figure out what’s wrong with my code, eventually it was the missing “/”. This is missing in your example as well.

2 Likes

Thanks for letting us know @MrRennen!

Howdy, welcome to the Auth0 Community. Thank you for your feedback and I am glad that you enjoyed the tutorial.

:thinking: When you created the identifier, did you perhaps add the / at the end? The identifier can be anything you want. The tutorial suggests using https://menu-api.demo.com but you can use any other string value:

The value of AUTH0_AUDIENCE in the .env file just needs to match whatever the value of the Identifier is :slight_smile:

That’s correct, I have created the identifier with a / suffix. Nice catch.

Can you please elaborate why the identifier and the auth0domain variables are causing this conflict? I thought the identifier is a standalone value that could even potentially be a string (non uri format).

1 Like

Happy to help! :thinking: Could you please expand a bit on what the conflict is between the Auth0 Domain and the Identifier value? They are independent of each other, but I’d like to understand your perception to provide you with a proper answer. Thank you!

Auth0 is amazing, so is NestJS, but it really takes this article to bring the two together. Thanks to this article I have a trusted basis for implementing role-based authorisation, rather than whatever I would have ended up with if I had to work it out myself (not to mention the time for that). I need to understand the security concepts, and want to have control, but I absolutely want the detail abstracted away - which is why I love Auth0.

My only suggestion would be highlighting that where in the tutorial you’ve manually assigned roles, that in a real-world app we can use rules to populate the roles claims (e.g. from a database) on login.

Thank you Dan.

2 Likes

Thanks @markau for providing that context!

Howdy, Mark! Welcome to the our Auth0 Community and thank you for your reading, I am glad that you enjoyed the post :slight_smile: Your suggestion is a great one. We’ll be exploring more advances concepts soonish, I’ll be sure to add this one to our conversations.

Hey, thanks for this tutorial. It’s exactly what I was looking for.

But… :wink:

I think I have followed the lesson to the letter, but I get 401 Unauthorized no matter what I do. It never let’s me in.

Anyone got any ideas why that would be?

Nick

Howdy, Nick. Welcome to the Auth0 Community. Thank you for reading this tutorial! I’d be happy to assist you with getting the code up and running. In which tutorial chapter did you start seeing the 401 Unauthorized Error? Also, on what view of the client application are you seeing that error? Thanks!

Dan –

I believe it was this chapter: Full-Stack TypeScript Apps: Developing a Secure API with NestJS

I follow the instructions to the letter, or at least as best I can. I can’t seem to get the WHATABYTE site to work for me, so I have been using Postman to send the requests.

If I include UseGuards(AuthGuard('jwt') it will always return a 401. I can’t seem to find the right way to make it do anything other than that.

Very frustrating.

Thanks for sharing that. I am following that tutorial chapter right now to spot any problems :+1:

Nick,

I was able to complete the “Managing Identity” and " Managing Roles" chapters without any errors. I started in the Identity chapter and cloned the repo from that point.

I was able to log in as an admin user to see the Admin UI options and to modify the API store items through the WAB Dashboard.

On the chapter “Managing Roles”, do you see the Admin UI Options in the WAB Dashboard before the Guards in Nest are implemented (before the following the section “Implement Role-Based Access Control in NestJS”) ?

Could you also please double check if the role that you created is menu-admin , please? This role is hard-coded in the client application.

Hey Dan,

I have this exact problem - in the managing roles chapter. I can see all the options for admins on the WAB dashboard, and when I inspect the Network, I see that an Authorization: Bearer <access_token> is appended to the request.

Nonetheless, I still get a 401, Unauthorized response from my server. It’s definitely a server configuration issue. Any ideas?

1 Like

Kesiena, thank you for reading the blog post and for joining our Auth0 community. I’ll look more into it. Did you start the tutorial from the first chapter or did you start at a later one?

When I re-run it, everything was working for me, but I’ll ask one of my teammates to audit the content to double check. Do you happen to have a repo with your server so that we could test this out and determine some steps to reproduce the issue?

Thank you!