<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: blake-buck</title>
    <description>The latest articles on DEV Community by blake-buck (@blakebuck).</description>
    <link>https://dev.to/blakebuck</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F451449%2F80f4e35b-656c-40f8-9392-d92918f96581.jpeg</url>
      <title>DEV Community: blake-buck</title>
      <link>https://dev.to/blakebuck</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/blakebuck"/>
    <language>en</language>
    <item>
      <title>A primer on the Amazon  Cognito Node SDK</title>
      <dc:creator>blake-buck</dc:creator>
      <pubDate>Sun, 06 Sep 2020 21:25:38 +0000</pubDate>
      <link>https://dev.to/blakebuck/a-primer-on-the-amazon-cognito-node-sdk-27i6</link>
      <guid>https://dev.to/blakebuck/a-primer-on-the-amazon-cognito-node-sdk-27i6</guid>
      <description>&lt;p&gt;Amazon Cognito is an authentication service provided by AWS. It is commonly used with AWS Amplify to provide authentication for applications, and Amazon provides plenty of documentation for that purpose. &lt;/p&gt;

&lt;p&gt;However, resources for using the Cognito SDK directly are more scarce. It's my hope that this article can save you the various Stack Overflow answers, AWS documentation articles, and pure trial and error it it took me to get a functional authentication system using this service.&lt;/p&gt;

&lt;p&gt;Included at the end of the article is a Github repo for a bare-bones Express app demonstrating some of the Cognito methods. The line "for the purposes of this tutorial" indicates a step I took while creating the User Pool for that application.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up Cognito
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the Cognito service in the AWS console&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click "Manage user pools", then "Create a user pool"&lt;/p&gt;
&lt;h3&gt;
  
  
  Create your User Pool
&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enter your pool name and click "step through settings"&lt;/p&gt;
&lt;h3&gt;
  
  
  Attributes
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cflpwTak--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tq73kow2zuqp6r8jncdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cflpwTak--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tq73kow2zuqp6r8jncdw.png" alt="Image depicting the Attributes configuration page in Cognito"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose how you want your uses to be able to sign in &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the purposes of this tutorial I'll be going with email only&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select any required attributes you wish each user to have&lt;/p&gt;
&lt;h3&gt;
  
  
  Policies
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--smeXlllq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/omq929rfrrlairpefhej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--smeXlllq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/omq929rfrrlairpefhej.png" alt="Image depicting the Policies configuration page in Cognito"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose your password requirements &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose if users can sign themselves up, or if admins need to register users&lt;/p&gt;
&lt;h3&gt;
  
  
  MFA and verifications
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xg_ybAGv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pbnjdmgd75b98f1m7s59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xg_ybAGv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pbnjdmgd75b98f1m7s59.png" alt="Image depicting the MFA and verifications configuration page in Cognito"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose if you want to enable Multi Factor Authentication &lt;br&gt;
– MFA adds a level of complexity that's out of scope for this tutorial; may be the topic of a future article however.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose how you want users to be able to recover their accounts&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the purposes of this tutorial I'll be going with "email only"&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Message Customization
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--98L2tQjT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rnpjuwfq8x4cp63u7i53.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--98L2tQjT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rnpjuwfq8x4cp63u7i53.png" alt="Image depicting the Message configuration page in Cognito"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Message Customization: here you can customize the email messages that get sent out to users when they sign up for your application&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you don't setup AWS SES and instead use Cognito to send emails, you're limited to 50 emails per day. This isn't good enough for production usage, but for personal/side projects it should fit your needs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Email verification – Code vs Link&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Link based verification: user is emailed a link, they click the link, user is verified to login.&lt;/li&gt;
&lt;li&gt;Code based verification: user is emailed a code, your application uses the "confirmSignUp" method to verify code, user is verified to login.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add any necessary resource tags&lt;/p&gt;
&lt;h3&gt;
  
  
  Devices
&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose if you want to remember user devices – this is related to MFA.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't click "Always" unless you're using MFA! Doing so changes the required parameters for certain Cognito methods.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  App clients
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---I-UPgOt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qg9wukeudu86qnz3r3cr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---I-UPgOt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qg9wukeudu86qnz3r3cr.png" alt="Image depicting the App client page in Cognito"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click "add an app client" – fill in name and token refresh values&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure "Generate Client Secret" is checked&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Under Auth Flows, make sure "ALLOW_ADMIN_USER_PASSWORD_AUTH" is checked.&lt;/p&gt;
&lt;h3&gt;
  
  
  Triggers
&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Assign any necessary lambda functions to certain triggers. &lt;/p&gt;
&lt;h3&gt;
  
  
  Review
&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make sure you've filled in all the fields mentioned in the previous steps&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pay special attention to Attributes, they can't be changed after Pool Creation!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click "Create"&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Using Cognito in your application
&lt;/h1&gt;

&lt;h3&gt;
  
  
  NPM Packages you'll need
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/aws-sdk"&gt;aws-sdk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/jwk-to-pem"&gt;jwk-to-pem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/jsonwebtoken"&gt;jsonwebtoken&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Environment Variables
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AWS_SECRET_ACCESS_KEY: grab this from the security credentials page of your AWS account (alternatively, you can create an &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console"&gt;IAM User&lt;/a&gt; and use its secret hash)&lt;/li&gt;
&lt;li&gt;AWS_ACCESS_KEY_ID: grab this from the security credentials page of your AWS account (alternatively, you can create an &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console"&gt;IAM User&lt;/a&gt; and use its access key)&lt;/li&gt;
&lt;li&gt;AWS_REGION: the region your user pool is in e.g. us-east-1.&lt;/li&gt;
&lt;li&gt;AWS_CLIENT_ID: grab this from your Cognito console. Can be found under General Settings → App clients or App Integration → App client settings.&lt;/li&gt;
&lt;li&gt;AWS_COGNITO_SECRET_HASH: grab this from your Cognito console. Found under General Settings → App clients. Click the show details button on your app client to show the field.&lt;/li&gt;
&lt;li&gt;AWS_USER_POOL_ID: grab this from your Cognito console. Found under General Settings.&lt;/li&gt;
&lt;li&gt;SERVER_NAME: The name you entered for your Cognito server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Important helper functions
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//  Authentication flows require the value returned by this function&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;AWS_COGNITO_SECRET_HASH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AWS_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./environment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createSecretHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AWS_COGNITO_SECRET_HASH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;AWS_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Authentication flows require request headers to be formatted as an&lt;/span&gt;
&lt;span class="c1"&gt;// array of objects with the shape {headerName: string, headerValue: string}&lt;/span&gt;

&lt;span class="c1"&gt;// this tutorial assumes you're using express and formats the headers &lt;/span&gt;
&lt;span class="c1"&gt;// according to that assumption&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;formatHeaders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;formattedHeaders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headerName&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;formattedHeaders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="nx"&gt;headerName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="na"&gt;headerValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;headerName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;formattedHeaders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Validating the JWT signature
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a jwks.json file at the root of your app

&lt;ul&gt;
&lt;li&gt;the contents of the file should be pulled from a url with the following structure: 
&lt;code&gt;https://cognito-idp.{YOUR_AWS_REGION}.amazonaws.com/{YOUR_AWS_USER_POOL_ID}/.well-known/jwks.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;alternatively, you can make a GET request from your app to the above URL and use the request results&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use the following function whenever you need to verify a JWT signature
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jsonwebtoken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwkToPem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jwkToPem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./jwks.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;verifyTokenSignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// alternatively you can use jsonwebtoken.decode() &lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tokenHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;properJwk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jwk&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;jwk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kid&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;tokenHeader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwkToPem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properJwk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="nx"&gt;pem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;algorithms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RS256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt; 
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decodedToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;One important thing to note: there are still steps you should take after verifying a JWT signature (read more &lt;a href="https://www.pingidentity.com/en/company/blog/posts/2019/jwt-security-nobody-talks-about.html"&gt;here&lt;/a&gt; and &lt;a href="https://github.com/awslabs/aws-support-tools/tree/master/Cognito/decode-verify-jwt"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Example usage
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cognito&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CognitoIdentityServiceProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;secretAccessKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;accessKeyId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_COGNITO_POOL_REGION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;ClientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_AWS_CLIENT_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;SecretHash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;createSecretHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cognito&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Things to watch out for
&lt;/h3&gt;

&lt;p&gt;When the register method is called and a user already exists with the given username, Cognito returns the message 'An account with the given email already exists.' This gives bad actors the ability to mount a user enumeration action against your app (&lt;a href="https://blog.rapid7.com/2017/06/15/about-user-enumeration/"&gt;read more&lt;/a&gt;). One possible solution is to check for this specific message whenever you're handling errors, and return the default success message for registration instead of an error.&lt;/p&gt;

&lt;p&gt;When you're calling the refresh token flow of the adminInitiateAuth method, use the username field from the user's access token (looks like a random string of characters) instead of their email; otherwise you'll get a 'Failure to verify secret hash' message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Once you get the pool setup and some basic helper functions written out, using Cognito becomes as simple as passing in the correct parameters to the necessary function. Securing your server doesn't end with setting up Cognito; there are plenty of other important steps to take. OWASP's cheat sheets are a great place to learn more about securing your application. &lt;/p&gt;

&lt;h2&gt;
  
  
  Reference Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html"&gt;AWS SDK documentation for Cognito&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/blake-buck/cognito-sampler"&gt;Cognito Sampler Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html"&gt;OWASP Cheat Sheet on NodeJS Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html"&gt;OWASP Cheat Sheet on Authentication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>node</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
