{"id":1987,"date":"2021-07-19T12:00:00","date_gmt":"2021-07-19T10:00:00","guid":{"rendered":"https:\/\/kindsonthegenius.com\/blog\/nestjs-authentication-and-authorization-with-auth0-simplified-step-by-step\/"},"modified":"2026-07-05T03:26:03","modified_gmt":"2026-07-05T01:26:03","slug":"nestjs-authentication-and-authorization-with-auth0-simplified-step-by-step","status":"publish","type":"post","link":"https:\/\/kindsonthegenius.com\/blog\/nestjs-authentication-and-authorization-with-auth0-simplified-step-by-step\/","title":{"rendered":"NestJS Authentication and Authorization with Auth0 Simplified \u2013 Step by Step"},"content":{"rendered":"<p>In this step by step tutorial, you will learn how to secure your REST API endpoints using Auth0.<\/p>\n<ol>\n<li><a href=\"#t1\">Create a NestJs Application<\/a><\/li>\n<li><a href=\"#t2\">Add Two More API Endpoints<\/a><\/li>\n<li><a href=\"#t3\">Create Authorization Module and Authorization Guard<\/a><\/li>\n<li><a href=\"#t4\">Modify the Authorization Guard<\/a><\/li>\n<li><a href=\"#t5\">Create New API for Auth0<\/a><\/li>\n<li><a href=\"#t6\">Let&#8217;s Use a .env File<\/a><\/li>\n<li><a href=\"#t7\">Add the ConfigService to the Authorization Guard<\/a><\/li>\n<li><a href=\"#t8\">Finally Protect an API Endpoint<\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t1\">1. Create a Nestjs Application<\/strong><\/h5>\n<p><strong>Step 1<\/strong> &#8211; Install the Nestjs command line interface.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">npm install -g @nestjs\/cli\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 2<\/strong> &#8211; Create an Nestjs Application\u00a0 using the command below<br \/>\n<!-- HTML generated using hilite.me --><\/p>\n<pre style=\"margin: 0; line-height: 125%;\">nest new nestjs-auth-demo\r\n<\/pre>\n<p>Choose npm when prompted<\/p>\n<p><strong>Step 3<\/strong> &#8211; Once the application is created, you can open it using VS Code or any other editor.<\/p>\n<p><strong>Step 4<\/strong> &#8211; Launch it using the command:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">npm run start -dev\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 5<\/strong> &#8211; Go to http:\/\/localhost:3000 to make sure it works. You will see the message &#8220;Hello World&#8221;<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t2\">2. Add Two More Endpoints<\/strong><\/h5>\n<p>We now need to add two endpoints: one that would be accessed without authentication and a second one that we would require authentication.<\/p>\n<p><strong>Step 1<\/strong> &#8211; Open the app.controller.ts file and add the following after the getHello() function<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #ff0000; background-color: #ffaaaa;\">@<\/span>Get(<span style=\"background-color: #fff0f0;\">'\/public'<\/span>)\r\ngetPublic()<span style=\"color: #333333;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">string<\/span> {\r\n  <span style=\"color: #008800; font-weight: bold;\">return<\/span> <span style=\"color: #008800; font-weight: bold;\">this<\/span>.appService.getPublic();\r\n}\r\n\r\n<span style=\"color: #ff0000; background-color: #ffaaaa;\">@<\/span>Get(<span style=\"background-color: #fff0f0;\">'\/protected'<\/span>)\r\ngetProtected()<span style=\"color: #333333;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">string<\/span> {\r\n  <span style=\"color: #008800; font-weight: bold;\">return<\/span> <span style=\"color: #008800; font-weight: bold;\">this<\/span>.appService.getPrivate();\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 2<\/strong> &#8211; Open the app.service.ts file and add the following as well<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">getPrivate()<span style=\"color: #333333;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">string<\/span> {\r\n  <span style=\"color: #008800; font-weight: bold;\">return<\/span> <span style=\"background-color: #fff0f0;\">'This is a public resource. Welcome visitor!'<\/span>;\r\n}\r\n\r\ngetPublic()<span style=\"color: #333333;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">string<\/span> {\r\n  <span style=\"color: #008800; font-weight: bold;\">return<\/span> <span style=\"background-color: #fff0f0;\">'This is a protected resource. Welcome member'<\/span>;\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 3<\/strong> &#8211; Restart the server and test the all the endpoints. For now, we&#8217;ve not protected any of them<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t3\">3. Create an Authorization Module and Authorization Guard<\/strong><\/h5>\n<p>With an authorization guard, we would protect certain endpoints. This means that to access this endpoints, and authorization token will be required.<\/p>\n<p><strong>Step 1<\/strong> &#8211; Generate authorization module using the command below:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<pre style=\"margin: 0; line-height: 125%;\">nest generate module authorization --no-spec\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 2<\/strong> &#8211; Generate an authorization guard using the command below:<br \/>\n<!-- HTML generated using hilite.me --><\/p>\n<pre style=\"margin: 0; line-height: 125%;\">nest generate guard authorization --no-spec\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 3<\/strong> &#8211; (optional) &#8211; Move the authorization guard into the authorization folder<\/p>\n<p><strong>Step 4<\/strong> &#8211; Install the following dependency:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">npm install jwks-rsa express-jwt\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t4\">4. Modify the Authorization Guard<\/strong><\/h5>\n<p>We now need open the authorization guard file and make some changes<\/p>\n<p><strong>Step 1<\/strong> &#8211; Add the following imports while removing the observable import<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">import<\/span> { expressJwtSecret, GetVerificationKey } from <span style=\"background-color: #fff0f0;\">'jwks-rsa'<\/span>;\r\n<span style=\"color: #008800; font-weight: bold;\">import<\/span> {promisify} from <span style=\"background-color: #fff0f0;\">'util'<\/span>;\r\n<span style=\"color: #008800; font-weight: bold;\">import<\/span> {expressjwt} from <span style=\"background-color: #fff0f0;\">'express-jwt'<\/span>;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 2<\/strong> &#8211; Inside the canActivate function, create a checkJwt function like shown below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">  <span style=\"color: #008800; font-weight: bold;\">const<\/span> checkJwt <span style=\"color: #333333;\">=<\/span> promisify(\r\n    jwt({\r\n      secret: <span style=\"color: #333399; font-weight: bold;\">expressJwtSecret<\/span>({\r\n        cache: <span style=\"color: #333399; font-weight: bold;\">true<\/span>,\r\n        rateLimit: <span style=\"color: #333399; font-weight: bold;\">true<\/span>,\r\n        jwksRequestsPerMinute: <span style=\"color: #333399; font-weight: bold;\">5<\/span>,\r\n        jwksUri<span style=\"color: #333333;\">:<\/span> <span style=\"background-color: #fff0f0;\">''<\/span>,\r\n      }) as GetVerificationKey,\r\n      audience<span style=\"color: #333333;\">:<\/span> <span style=\"background-color: #fff0f0;\">''<\/span>,\r\n      issuer<span style=\"color: #333333;\">:<\/span> <span style=\"background-color: #fff0f0;\">''<\/span>,\r\n      algorithms<span style=\"color: #333333;\">:<\/span> [<span style=\"background-color: #fff0f0;\">'RS256'<\/span>]\r\n    }),\r\n  );\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 3<\/strong> &#8211; Replace the return true line with the code below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">try<\/span>{\r\n  await checkJwt(req, res);\r\n  <span style=\"color: #008800; font-weight: bold;\">return<\/span> <span style=\"color: #008800; font-weight: bold;\">true<\/span>;\r\n} <span style=\"color: #008800; font-weight: bold;\">catch<\/span>(error) {\r\n  <span style=\"color: #008800; font-weight: bold;\">throw<\/span> <span style=\"color: #008800; font-weight: bold;\">new<\/span> UnauthorizedException(error);\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 4<\/strong> &#8211; Change the canActivate function to an async function<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t5\">5. Create a New API for Auth0<\/strong><\/h5>\n<p>Now this part is very important as you need to complete it to continue with the next steps.<\/p>\n<p><strong>Step 1<\/strong> &#8211; Visit <a href=\"https:\/\/manage.auth0.com\/\" target=\"_blank\" rel=\"noopener\">https:\/\/manage.auth0.com\/<\/a> and create an account free.<\/p>\n<p><strong>Step 2<\/strong> &#8211; In your terminal, install Auth0 cli using the command below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">brew install auth0\/auth0-cli\/auth0\r\n<\/pre>\n<p>This command is for Mac. For Auth0 cli installation on Windows or Linux, see procedure here.<\/p>\n<p><strong>Step 3<\/strong> &#8211; In your application terminal run the following to install the deploy cli<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">npm i -g auth0-deploy-cli\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 4<\/strong> &#8211; Run the following command to create a new\u00a0 Auth0 API<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">auth0 apis create\r\n<\/pre>\n<p>Provide a name for it nest-api-demo<\/p>\n<p>You will notice that the auth0 api is created with the domain kindson.eu.auth0.com (yours may be different, so watch the video for clarification)<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t6\">6. Let&#8217;s Use a .env File<\/strong><\/h5>\n<p>We would have to create a .env file and add our variables in it.<\/p>\n<p><strong>Step 1<\/strong> &#8211; Create a .env file<\/p>\n<p><strong>Step 2<\/strong> &#8211; Add the following in it.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">AUTH0_AUDIENCE=nest-api-demo\r\nAUTH0_DOMAIN=https:\/\/kindson.eu.auth0.com\/\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 3<\/strong> &#8211; To use the environment variables, install the nest config library using the command below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">npm install @nestjs\/config\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 4<\/strong> &#8211; Import the config into the authorization guard file like so:<br \/>\n<!-- HTML generated using hilite.me --><\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">import<\/span> { ConfigService } from <span style=\"background-color: #fff0f0;\">'@nestjs\/config'<\/span>;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 5<\/strong> &#8211; Add the ConfigModule to the imports section of the app module like so:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">imports<span style=\"color: #333333;\">:<\/span> [AuthorizationModule, ConfigModule.forRoot()],\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t7\">7. Add the ConfigService to the Authorization Guard<\/strong><\/h5>\n<p>To use the ConfigService in the Authorization Guard, follow the steps below:<\/p>\n<p><strong>Step 1<\/strong> &#8211; Create two variables\u00a0 to hold the values of the AUTH0_AUDIENCE and the AUTH0_DOMAIN like so:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">private<\/span> AUTH0_AUDIENCE: <span style=\"color: #333399; font-weight: bold;\">string<\/span>;\r\n<span style=\"color: #008800; font-weight: bold;\">private<\/span> AUTH0_DOMAIN: <span style=\"color: #333399; font-weight: bold;\">string<\/span>;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 2<\/strong>\u00a0&#8211; Create a constructor in the authorization.guard.ts file and inject the ConfigService like so:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">constructor<\/span>( <span style=\"color: #008800; font-weight: bold;\">private<\/span> configService: <span style=\"color: #333399; font-weight: bold;\">ConfigService<\/span>){\r\n  <span style=\"color: #008800; font-weight: bold;\">this<\/span>.AUTH0_AUDIENCE <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">this<\/span>.configService.get(<span style=\"background-color: #fff0f0;\">'AUTH0_AUDIENCE'<\/span>);\r\n  <span style=\"color: #008800; font-weight: bold;\">this<\/span>.AUTH0_DOMAIN <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">this<\/span>.configService.get(<span style=\"background-color: #fff0f0;\">'AUTH0_DOMAIN'<\/span>);\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 3<\/strong> &#8211; Now update the jwt audience, issuer(domain) and the jwt secret jwkUri. Modified part of the code is given below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">...\r\n  jwksUri<span style=\"color: #333333;\">:<\/span> <span style=\"color: #ff0000; background-color: #ffaaaa;\">`<\/span>${<span style=\"color: #008800; font-weight: bold;\">this<\/span>.AUTH0_DOMAIN}.well<span style=\"color: #333333;\">-<\/span>known<span style=\"color: #333333;\">\/<\/span>jwks.json<span style=\"color: #ff0000; background-color: #ffaaaa;\">`<\/span>,\r\n}),\r\naudience: <span style=\"color: #333399; font-weight: bold;\">this.AUTH0_AUDIENCE<\/span>,\r\nissuer: <span style=\"color: #333399; font-weight: bold;\">this.AUTH0_DOMAIN<\/span>,\r\n...\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t8\">8. Finally, to protect and api endpoint,<\/strong><\/h5>\n<p>Simply add this annotation to the controller endpoint:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">@UseGuards(AuthorizationGuard)\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>At this point,\u00a0 you can now start the server and try to access the api endpoints. You&#8217;ll see that that protected endpoint would require authorization. This response is shown below using Postman<\/p>\n<figure id=\"attachment_14740\" aria-describedby=\"caption-attachment-14740\" style=\"width: 1024px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.kindsonthegenius.com\/wp-content\/uploads\/2021\/07\/Screenshot-2021-07-19-at-15.09.47.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-14740 size-large\" src=\"https:\/\/www.kindsonthegenius.com\/wp-content\/uploads\/2021\/07\/Screenshot-2021-07-19-at-15.09.47-1024x688.png\" alt=\"Accessing protected resource using Auth0\" width=\"1024\" height=\"688\" srcset=\"https:\/\/www.kindsonthegenius.com\/wp-content\/uploads\/2021\/07\/Screenshot-2021-07-19-at-15.09.47-1024x688.png 1024w, https:\/\/www.kindsonthegenius.com\/wp-content\/uploads\/2021\/07\/Screenshot-2021-07-19-at-15.09.47-300x202.png 300w, https:\/\/www.kindsonthegenius.com\/wp-content\/uploads\/2021\/07\/Screenshot-2021-07-19-at-15.09.47-768x516.png 768w, https:\/\/www.kindsonthegenius.com\/wp-content\/uploads\/2021\/07\/Screenshot-2021-07-19-at-15.09.47-600x403.png 600w, https:\/\/www.kindsonthegenius.com\/wp-content\/uploads\/2021\/07\/Screenshot-2021-07-19-at-15.09.47-272x182.png 272w, https:\/\/www.kindsonthegenius.com\/wp-content\/uploads\/2021\/07\/Screenshot-2021-07-19-at-15.09.47.png 1164w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption id=\"caption-attachment-14740\" class=\"wp-caption-text\">Accessing protected resource using Auth0<\/figcaption><\/figure>\n<p>&nbsp;<\/p>\n<p>You can get the jwt token from your Auth0 dashboard and include it in the request and then you can access it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this step by step tutorial, you will learn how to secure your REST API endpoints using Auth0. Create a NestJs Application Add Two More &hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"pagelayer_contact_templates":[],"_pagelayer_content":"","footnotes":""},"categories":[414],"tags":[],"class_list":["post-1987","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1987","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/comments?post=1987"}],"version-history":[{"count":1,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1987\/revisions"}],"predecessor-version":[{"id":2155,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1987\/revisions\/2155"}],"wp:attachment":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/media?parent=1987"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/categories?post=1987"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/tags?post=1987"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}