<?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: Henrik VT</title>
    <description>The latest articles on DEV Community by Henrik VT (@henrikvtcodes).</description>
    <link>https://dev.to/henrikvtcodes</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%2F592119%2F07ef0d03-694e-43a3-9e5b-928e17e370cb.PNG</url>
      <title>DEV Community: Henrik VT</title>
      <link>https://dev.to/henrikvtcodes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/henrikvtcodes"/>
    <language>en</language>
    <item>
      <title>Use NextAuth to authenticate API requests</title>
      <dc:creator>Henrik VT</dc:creator>
      <pubDate>Tue, 24 May 2022 14:19:11 +0000</pubDate>
      <link>https://dev.to/henrikvtcodes/use-nextauth-to-authenticate-api-requests-6gf</link>
      <guid>https://dev.to/henrikvtcodes/use-nextauth-to-authenticate-api-requests-6gf</guid>
      <description>&lt;p&gt;NextAuth is a great way to authenticate users for your Next.js app. However, Next.js API Routes are not a good substitute for a full backend framework. In this article, we'll address all the setup required to use NextAuth's cookies to authenticate against a separate backend. While I am using NestJS as my backend framework, the general logic/flow is portable to almost any backend framework.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important Note:&lt;/strong&gt; You can avoid a lot of this by proxying your API requests through Next.js. This tutorial is specifically for an API server on a separate, &lt;strong&gt;sub&lt;/strong&gt;domain.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Basic Idea
&lt;/h2&gt;

&lt;p&gt;When a user logs in successfully, NextAuth issues an &lt;code&gt;HttpOnly&lt;/code&gt; cookie that contains either a JWT or a session token. While we could have an API route that issues a different token for accessing the API server, this adds complexity. What if, instead, we could use NextAuth's cookie as our token for the API? This is a good solution because it allows us to reduce complexity, leaving the management of the token to NextAuth. Our backend can then just validate it and move on. This is also assuming that &lt;strong&gt;your backend is on a subdomain relative to the domain of your frontend; e.g. your frontend is at &lt;code&gt;example.com&lt;/code&gt; and your backend is at &lt;code&gt;api.example.com&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Frontend
&lt;/h2&gt;

&lt;h4&gt;
  
  
  NextAuth Config
&lt;/h4&gt;

&lt;p&gt;No matter what your backend is, you'll have to set a &lt;a href="https://next-auth.js.org/configuration/options#cookies" rel="noopener noreferrer"&gt;custom configuration for the session cookie in NextAuth.&lt;/a&gt; By default, NextAuth does not specify a domain for the cookie. This results in a cookie whose domain is that of the current page (i.e. &lt;code&gt;example.com&lt;/code&gt;), not including subdomains. Other than that, all other defaults are fine.   &lt;/p&gt;

&lt;p&gt;Here's how to set it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Inside your NextAuth config object&lt;/span&gt;
&lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`__Secure-next-auth.session-token`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Make sure to add conditional logic so that the name of the cookie does not include `__Secure-` on localhost&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// All of these options must be specified, even if you're not changing them&lt;/span&gt;
      &lt;span class="na"&gt;httpOnly&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="na"&gt;sameSite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lax&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;path&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="na"&gt;secure&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="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`example.com`&lt;/span&gt; &lt;span class="c1"&gt;// Ideally, you should use an environment variable for this&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;You might be looking at that domain wondering "&lt;em&gt;How is that different?&lt;/em&gt; ". When you specify the domain, the cookie's domain value will get set with an extra period in front (i.e. &lt;code&gt;.example.com&lt;/code&gt; for this) which tells the browser that it's fine to send to subdomains.&lt;/p&gt;

&lt;h4&gt;
  
  
  Making requests
&lt;/h4&gt;

&lt;p&gt;When you make requests from your frontend, you also need to add an option to the request to send the cookie(s).  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fetch&lt;/code&gt; requests: specify &lt;code&gt;credentials: "include"&lt;/code&gt; in the request config
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials" rel="noopener noreferrer"&gt;MDN Reference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;XHR&lt;/code&gt; requests (e.g. Axios): &lt;code&gt;withCredentials = true&lt;/code&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials" rel="noopener noreferrer"&gt;MDN Reference&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll also want to make sure that your chosen method of making requests is able to make CORS preflight requests for some HTTP methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Backend
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Headers
&lt;/h4&gt;

&lt;p&gt;For this to work, we need to set up some CORS headers. Here they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;: You must specify the domains; a wildcard (&lt;code&gt;*&lt;/code&gt;) will not allow access to request credentials.
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#access-control-allow-origin" rel="noopener noreferrer"&gt;MDN Reference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Allow-Credentials&lt;/code&gt;: This must be set to &lt;code&gt;true&lt;/code&gt;.
&lt;a href="https://dev.toLink"&gt;MDN Reference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Allow-Headers&lt;/code&gt;: Make sure that the &lt;code&gt;Cookies&lt;/code&gt; header is included.
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#access-control-allow-methods" rel="noopener noreferrer"&gt;MDN Reference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Vary&lt;/code&gt;: Must be set to &lt;code&gt;Origin&lt;/code&gt;. Most frameworks/libraries set this automatically.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Authentication/Validation
&lt;/h4&gt;

&lt;p&gt;In your backend of choice, you'll need similar conditional logic to above. Assuming that you use the default cookie names, you'll access a cookie called &lt;code&gt;__Secure-next-auth.session-token&lt;/code&gt; or &lt;code&gt;next-auth.session-token&lt;/code&gt;. If this is a JWT, you'll validate it and extract the encoded information - make sure your server uses the same JWT signing secret that you provided to NextAuth. If it's a session token, you'll look it up in your database and make sure it exists + is not expired.  &lt;/p&gt;

&lt;h4&gt;
  
  
  NestJS - Passport
&lt;/h4&gt;

&lt;p&gt;Here's specifically how I implemented this in NestJS, using Passport. While I am still using Nest's Express platform, this should be mostly compatible with the Fastify platform. First, you'll need the &lt;code&gt;cors&lt;/code&gt; package, configured as followed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enableCors&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;origin&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;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&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;http://127.0.0.1:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// add your other urls here&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;allowedHeaders&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;Cookie&lt;/span&gt;&lt;span class="dl"&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;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;methods&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;GET&lt;/span&gt;&lt;span class="dl"&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;POST&lt;/span&gt;&lt;span class="dl"&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;PUT&lt;/span&gt;&lt;span class="dl"&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;PATCH&lt;/span&gt;&lt;span class="dl"&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;OPTIONS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;credentials&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="c1"&gt;// This is what sets the `Access-Control-Allow-Credentials` header.&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Secondly, you'll need the &lt;code&gt;cookie-parser&lt;/code&gt; package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cookieParser&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;cookie-parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ... other code&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cookieParser&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, I used the &lt;code&gt;passport-custom&lt;/code&gt; package to set up a custom strategy. I implemented it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cookieName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;// This turnary statement is the conditional logic I mentioned previously&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&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;__Secure-next-auth.session-token&lt;/span&gt;&lt;span class="dl"&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;next-auth.session-token&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="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NextAuthSession&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PassportStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nextauth-session&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;authService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// The Request type is imported from Express&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;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;sessionToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;cookieName&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UnauthorizedException&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No session token&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="c1"&gt;// authService.verifySession does a database lookup with Prisma&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verifySession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UnauthorizedException&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid Session&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="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Whatever you return gets added to the request object as `req.user`&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This was something that took me a bit to figure out properly, especially figuring out how to use Passport. I hope others come across this guide and find it useful.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>nextjs</category>
      <category>node</category>
      <category>api</category>
    </item>
    <item>
      <title>My List of VSCode Extensions.</title>
      <dc:creator>Henrik VT</dc:creator>
      <pubDate>Wed, 07 Jul 2021 22:58:21 +0000</pubDate>
      <link>https://dev.to/henrikvtcodes/my-list-of-vscode-extensions-3725</link>
      <guid>https://dev.to/henrikvtcodes/my-list-of-vscode-extensions-3725</guid>
      <description>&lt;p&gt;Like millions of other developers, I use VSCode. It's not particularly remarkable, but I decided to make a personal list of my favorite extensions. Many of these are plenty well known in the community, but when I started, it look me some time to find out about some of my current favorites. I figured I'd create a central list for beginners to find and that I can send to beginners. This list is separated by language/application/library; ie: Git, Markdown, etc. I will not be including language tooling or Intellisense extensions.&lt;br&gt;
If you are reading this and know of an extension you think I'd like, please leave a comment!&lt;/p&gt;

&lt;p&gt;So lets get started.&lt;/p&gt;




&lt;h2&gt;
  
  
  General Purpose &amp;amp; Miscellaneous
&lt;/h2&gt;

&lt;p&gt;These are all extensions that are not bound to any particular language or application, but just generally useful or fun to have.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=GitHub.github-vscode-theme" rel="noopener noreferrer"&gt;Github Theme&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is my theme pack of choice. Specifically, I use the Github Dark Default setting. I like that it keeps things as dark as possible, with very little deviation outside grey/black. I've also just gotten used to the syntax highlighting. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer" rel="noopener noreferrer"&gt;Bracket Pair Colorizer&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This extension is an absolute &lt;em&gt;must&lt;/em&gt;. It greatly improves readability of code and makes it easier to find errors caused by missing brackets.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=ExodiusStudios.comment-anchors" rel="noopener noreferrer"&gt;Comment Anchors&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Well documented code is &lt;em&gt;key&lt;/em&gt;. This extension allows you to create descriptive, highlighted comments. I used to use the Better Comments extension, but I switched to Comment Anchors for a couple reasons: First, it works in JSX, which better comments didn't. Second, &lt;em&gt;I can find where I left a comment.&lt;/em&gt; Even though I only recently got this extension, I can see how killer this feature can be.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=icrawl.discord-vscode" rel="noopener noreferrer"&gt;Discord Presence&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This one is a little bit vain, as it's sole purpose is to report that one is using VSCode into the Discord status process. I think it's cool though.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack" rel="noopener noreferrer"&gt;Remote Development Extension Pack&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is a must-have extension for anyone who uses WSL, like myself. Other than that, it is immensely useful for its other capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=PKief.material-icon-theme" rel="noopener noreferrer"&gt;Material Icon Theme&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I used to use vscode-icons, but I found Material Icons and just liked the "flatness" of the icons.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=Perkovec.emoji" rel="noopener noreferrer"&gt;Emoji&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is a simple extension: Insert emojis into code easily.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=bierner.emojisense" rel="noopener noreferrer"&gt;:emojisense:&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In the same vein as the last one, this also allows for even easier insertion of emojis into code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git
&lt;/h2&gt;

&lt;p&gt;These are the extensions that I like to have for general purpose git (and Github) usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens" rel="noopener noreferrer"&gt;GitLens&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This one is an obvious must. With over 10 million downloads, it fills in the git feature void in VSCode. I especially love the &lt;code&gt;git blame&lt;/code&gt; feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph" rel="noopener noreferrer"&gt;Git Graph&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This one is also quite popular, sitting around 1.5 million downloads. It's not particularly special nor necessary, but it's reallllly cool to look at.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github" rel="noopener noreferrer"&gt;Github Pull Requests and Issues&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Being able to refer back to PR's and issues without changing windows / desktops is a great time saver.&lt;/p&gt;




</description>
      <category>vscode</category>
    </item>
  </channel>
</rss>
