<?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: Si Le</title>
    <description>The latest articles on DEV Community by Si Le (@omnisyle).</description>
    <link>https://dev.to/omnisyle</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%2F79442%2F763d7ebf-17c1-4434-9a33-23d4d4ce1436.jpeg</url>
      <title>DEV Community: Si Le</title>
      <link>https://dev.to/omnisyle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/omnisyle"/>
    <language>en</language>
    <item>
      <title>Handle form and validation with React</title>
      <dc:creator>Si Le</dc:creator>
      <pubDate>Sat, 13 Jun 2020 04:24:48 +0000</pubDate>
      <link>https://dev.to/omnisyle/handle-form-and-validation-with-react-1a9p</link>
      <guid>https://dev.to/omnisyle/handle-form-and-validation-with-react-1a9p</guid>
      <description>&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;Handling form is an extremely common usecase for web applications. In this post, let's explore a way to handle form inputs and validations using React without using a third-party library.&lt;/p&gt;

&lt;h1&gt;
  
  
  Requirements
&lt;/h1&gt;

&lt;p&gt;We will cover the most popular functionalities that will apply for most usecases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;code&gt;onSubmit&lt;/code&gt; callback for components using the form.&lt;/li&gt;
&lt;li&gt;Validation for single input (front-end only).&lt;/li&gt;
&lt;li&gt;Validation onSubmit, not onBlur.&lt;/li&gt;
&lt;li&gt;Reset form.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  How does it work?
&lt;/h1&gt;

&lt;p&gt;We will create a Form context that will hold all the states and define all state interactions for all form inputs. &lt;/p&gt;

&lt;p&gt;When an input is mounted, certain information passed in these inputs will be used to supply to the Form context.&lt;/p&gt;

&lt;p&gt;When an input within the form context changes, it will submit its new value to form context. Form context receives the values and changes its state to new value and pass it down to the input (controlled input). &lt;/p&gt;

&lt;p&gt;When the form is submitted, it will run through all the validations that was registered when the input mounted and set the errors for specific fields. Those will then be passed down to the right input and rendered accordingly.&lt;/p&gt;

&lt;p&gt;The figure below summarizes the responsibilities for each type of component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz27ekkxcz91cjv8z0vs0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz27ekkxcz91cjv8z0vs0.png" alt="form component structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Form State
&lt;/h2&gt;

&lt;p&gt;This form state needs to be able to hold 3 pieces of information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Form data - for user's input data.&lt;/li&gt;
&lt;li&gt;Validations - for field specific validations.&lt;/li&gt;
&lt;li&gt;Errors - for field specific errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think this object should be sufficient to work with.&lt;/p&gt;

&lt;div class="highlight js-code-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;FORM_STATE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="na"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="na"&gt;errors&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;We will also make a convention that every input must have a unique name prop to identify itself. It is similar to how a regular HTML5 form &lt;code&gt;input&lt;/code&gt; has &lt;code&gt;name&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;It is important for the name to be unique because we will use them as keys in our state structure.&lt;/p&gt;

&lt;p&gt;For example, an input with the name &lt;code&gt;first_name&lt;/code&gt; will be store in FORM_STATE as follow:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&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;validators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;first_name&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="s2"&gt;error message&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Form Context
&lt;/h2&gt;

&lt;p&gt;To inject form state and methods to every components that want to subscribe to it, we will use context provider pattern. You can read more about context &lt;a href="https://reactjs.org/docs/context.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In my understanding, context is a wrapper that inject props into any child component that subscribe to it through a consumer. There is a convenient way to subscribe to context by using &lt;code&gt;useContext&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;We will also create an HOC to encapsulate the context subscription logic in one place so that our input can be as purely UI as possible. In other words, inputs are presentational components that will only listen to prop changes. Form context is the container that will hold most of the logic.&lt;/p&gt;
&lt;h2&gt;
  
  
  Form Methods
&lt;/h2&gt;

&lt;p&gt;Let's go through step by step how &lt;code&gt;form context&lt;/code&gt; should behave. &lt;/p&gt;
&lt;h3&gt;
  
  
  Registration
&lt;/h3&gt;

&lt;p&gt;When an input is mounted, it should register itself with form context. On registration, we simply will copy validators from that input to store inside form context.&lt;/p&gt;

&lt;p&gt;When an input is unmounted, we should clear its validations, errors, and any data associated with that input. Here's the registration function.&lt;/p&gt;
&lt;div class="highlight js-code-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;registerInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validators&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="nf"&gt;setFormState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;validators&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;validators&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="c1"&gt;// clear any errors&lt;/span&gt;
      &lt;span class="na"&gt;errors&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&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;span class="c1"&gt;// returning unregister method&lt;/span&gt;
  &lt;span class="k"&gt;return &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="nf"&gt;setFormState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// copy state to avoid mutating it&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentValidators&lt;/span&gt; &lt;span class="p"&gt;}&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="nx"&gt;state&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="c1"&gt;// clear field data, validations and errors&lt;/span&gt;
      &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;currentValidators&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentValidators&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;The registration function will return a function to unregister this input. It will only remove that input with the same name. &lt;/p&gt;
&lt;h3&gt;
  
  
  Input data control
&lt;/h3&gt;

&lt;p&gt;Controlled inputs require us to use an onChange function to set a value somewhere, either in a redux store or in a state. In our form, we will hijack it and set a value in our form context before passing up the value. That way, the input itself is more flexible, although, it does come with some confusion. I'll explain this point later on.&lt;/p&gt;

&lt;p&gt;When an input changes, we simply set its value to our form context's &lt;code&gt;data&lt;/code&gt; object. Here is the implementation.&lt;/p&gt;
&lt;div class="highlight js-code-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;setFieldValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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="nf"&gt;setFormState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;data&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;errors&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&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;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In addition to setting the input's data, we also clear its own errors under the assumption that if there was an error when the form submitted, user must have seen the inline errors. Now they're correcting the value for that field.&lt;/p&gt;
&lt;h3&gt;
  
  
  Submission and validation
&lt;/h3&gt;

&lt;p&gt;Next, we have the validation and submission part of the form. The process is simple. When the user click submits, we'll run through every validator in form context, call the validator with 2 arguments: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The value of the input.&lt;/li&gt;
&lt;li&gt;The data object as a whole.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why do we pass data objects into validators? Technically, we don't have to, but I think it's nice to have the validator aware of the whole form data. That way, we can perform cross input validation if we want.&lt;/p&gt;

&lt;p&gt;If all validators return empty messages. It's good. The form will call onSubmit callback.&lt;/p&gt;

&lt;p&gt;If ANY validator returns an error message, we'll set the &lt;code&gt;errors&lt;/code&gt; hash with that input's name and error messages. The form is now invalid and onSubmit callback will not be called.&lt;/p&gt;

&lt;p&gt;Let's take a look at the implementation.&lt;/p&gt;
&lt;div class="highlight js-code-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;validate&lt;/span&gt; &lt;span class="o"&gt;=&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;validators&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// always reset form errors&lt;/span&gt;
    &lt;span class="c1"&gt;// in case there was form errors from backend&lt;/span&gt;
    &lt;span class="nf"&gt;setFormState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;errors&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validators&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="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formErrors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validators&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formState&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;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validator&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&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;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;result&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="p"&gt;},&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="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messages&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;errors&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formErrors&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="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="nf"&gt;setFormState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formErrors&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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;blockquote&gt;
&lt;p&gt;It's important to note that we're running through all validators and collect all errors before returning. Otherwise, when users have errors in 2 fields, they'll have to fix one, submit, get another error, and fix the second field. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it! We've got our form context ready. Here's the full code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  Form HOC
&lt;/h2&gt;

&lt;p&gt;Now that we have form context, we will make an wrapper to inject those context methods into any input component. This is optional because you can always use a context hook. Though, I think it's convenient.&lt;/p&gt;

&lt;p&gt;The HOC will handle input registration, filtering errors and input value, and set data in form context.&lt;/p&gt;

&lt;p&gt;First, let's subscribe to form context with &lt;code&gt;useContext&lt;/code&gt; hook. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;setFieldValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;registerInput&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;FormContext&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;After that, we'll register to Form context with &lt;code&gt;useEffect&lt;/code&gt;. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;registerInput&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="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validators&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;We also return the unregistration function, so when this input is unmounted, it will not affect the form data or its validations anymore.&lt;/p&gt;

&lt;p&gt;Then, we need to get the right input value and error for the wrapped input.&lt;/p&gt;
&lt;div class="highlight js-code-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;inputValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;inputErrors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Error will always be an array of error messages. An empty error array means there are no errors. &lt;/p&gt;

&lt;p&gt;Lastly, we need to hijack the onChange callback so we can store this wrapped input's value to form context.&lt;/p&gt;
&lt;div class="highlight js-code-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;onChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setFieldValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;val&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="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&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;Here is the entire implementation.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  Text Input
&lt;/h2&gt;

&lt;p&gt;Finally, something usable. Let's make a text input using our form. Our input will have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A label&lt;/li&gt;
&lt;li&gt;The input itself&lt;/li&gt;
&lt;li&gt;Any errors&lt;/li&gt;
&lt;li&gt;onChange callback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It will receive in errors and value from form context. Based on form context, it will render accordingly. This is quite simple to implement.&lt;/p&gt;

&lt;p&gt;Here's the implementation.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h1&gt;
  
  
  All together now!
&lt;/h1&gt;

&lt;p&gt;We've arrived at the end! Yay! Let's put together a sign-up form as an example. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TextInput&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;first_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;validators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="nx"&gt;requiredValidator&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
    &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TextInput&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;validators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="nx"&gt;requiredValidator&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
    &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Last Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;// .... truncate&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit-btn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;Register&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit-btn danger&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reset&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;Reset&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We'll simply log out the data for now. We'll also put in a few validators to make sure that it works. Let's take a look at a sample validator.&lt;/p&gt;

&lt;div class="highlight js-code-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;requiredValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;val&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="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This field is required&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="k"&gt;return&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;Try clicking submit and reset to see how it works!&lt;/p&gt;

&lt;p&gt;Thank you for reading to this point. I hope this is useful. Let me know your thoughts and comments :)&lt;/p&gt;

&lt;h1&gt;
  
  
  Form in action
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/minimal-form-js-fciv2?fontsize=14&amp;amp;hidenavigation=1&amp;amp;theme=dark" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodesandbox.io%2Fstatic%2Fimg%2Fplay-codesandbox.svg" alt="Edit minimal-form-js"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/minimal-form-js-fciv2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>webpack</category>
    </item>
    <item>
      <title>Simple JWT Authentication with Golang (Part 3)</title>
      <dc:creator>Si Le</dc:creator>
      <pubDate>Sat, 01 Jun 2019 23:11:09 +0000</pubDate>
      <link>https://dev.to/omnisyle/simple-jwt-authentication-with-golang-part-3-1ja3</link>
      <guid>https://dev.to/omnisyle/simple-jwt-authentication-with-golang-part-3-1ja3</guid>
      <description>&lt;p&gt;This is part three of a three-part series tutorial that builds a small but complete JWT authentication solution for internal API (most concepts can also be applied to build JWT auth for public API).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 1 — &lt;a href="https://dev.to/omnisyle/simple-jwt-authentication-for-golang-part-1-3kfo"&gt;Public/secret key generation and storage&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 2 —&lt;a href="https://dev.to/omnisyle/simple-jwt-authentication-with-golang-part-2-263"&gt;Build a CLI to create/retrieve App object&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 3 — Build the JWT authentication middleware&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RG2pxQHC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AQoUJBQLOv6Vh_pgEYctC_A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RG2pxQHC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AQoUJBQLOv6Vh_pgEYctC_A.png" alt="" width="880" height="461"&gt;&lt;/a&gt;&lt;a href="https://jwt.io"&gt;https://jwt.io&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;This is the last part of the tutorial series, we will finally write methods to authenticate requests with JWT token in Authorization header. There are two parts to this.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;JWT Authentication functions&lt;/li&gt;
&lt;li&gt;Example of middleware using JWT authentication&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  JWT Authentication
&lt;/h3&gt;

&lt;p&gt;In this part, we will use a JWT library to provide a way for us to parse and encode JWT token. There are a few of them and you can select your favourite one at &lt;a href="https://jwt.io/"&gt;jwt.io&lt;/a&gt;. In this project, I chose &lt;a href="https://github.com/dgrijalva/jwt-go"&gt;jwt-go&lt;/a&gt;. I’ve used it before so I’m more familiar with it than others.&lt;/p&gt;

&lt;p&gt;I think it's good to wrap jwt-go in my own class and expose only what I need to use. It has three main benefits.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I don't have to remember the documentation for the library until I need another thing from it since everything I need is written by me and documented myself.&lt;/li&gt;
&lt;li&gt;It’s a great way to learn how to use the library and actually understand its interface.&lt;/li&gt;
&lt;li&gt;Other parts of the code don’t need to be aware of the library so we can switch to another one relatively easy.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Parse JWT Token
&lt;/h3&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;ParseJWT takes a token and a secret key to verify the signature of the token and returns a Claims object. We use the most common signing method, HMAC, to sign the token. There are other ones in the library that you can use. They’re all defined as constants, so it’s quite convenient and readable.&lt;/p&gt;

&lt;p&gt;Next, we check if the token is properly generated with token.Valid and return the claims wrapped under our own Claimstype. I handled some errors. However, I think one thing we can do is to wrap those errors in our own errors and propagate them up. The errors package is great for this. You can find it &lt;a href="https://godoc.org/github.com/pkg/errors"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are many opinions on error handling. I was lazy and simply propagate the errors straight up. I think wrapping it to preserve the stack trace and provide more details will be helpful when we need to debug. One thing to note is since this package is meant to be a library package, we should not log anything out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encode JWT Token
&lt;/h3&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;EncodingJWT is quite straight forward. Again, I’m simply pushing the errors up the stack and not handle them here. It takes two arguments, a secret key, and a Claims object. We use jwt.NewWithClaims to create a new Token object. Then, we use SignedString to generate the token string.&lt;/p&gt;

&lt;p&gt;Most of the time, we need to attach something to the token as we generate them. That’s why I only want to expose NewWithClaims method and always create a Claims object. If we don’t want to have any claims, we simply make an empty Claims object to pass in. That way, we don’t have to make 2 different methods and remember the difference between the two.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use it in a middleware
&lt;/h3&gt;

&lt;p&gt;Now that we have the JWT auth service, how do we use it to authenticate a request from the client? If you’ve read all three parts of the tutorial, you will know that we store all the client credentials as App . That means the client needs to be registered with us before sending a request to our service.&lt;/p&gt;

&lt;p&gt;Each client should have a public/secret key pair. The public key will be used to identify the client with the API. Using the public key, we can get the secret for the client from our database. The client used its secret key to generate a JWT token to send to the API in the Authorization header in this format: Bearer asdfasdfadsf . Therefore, we need the same secret key to verify the token.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The process is as follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract the token from the request header.&lt;/li&gt;
&lt;li&gt;Parse it with the secret key. If we get claims back, it means the token is valid. We proceed with the request.&lt;/li&gt;
&lt;li&gt;Otherwise, we don’t let the user proceed and return a Forbidden status code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I excluded the part where you need to get the public/secret key pair from the database. This is an example, not a 100% implementation. If you want to identify each client, then you’ll need to query the database to find a public/secret key pair that the client registered before making a request. On the other hand, if there is only one client (in the case of an internal web service) then you probably don’t need to identify it. In addition, there are many things you might want to do when you receive a request from the client. For example, you may need to get the user’s ID or email to do authorization. Middleware/handler logic varies depends on your use case.&lt;/p&gt;

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

&lt;p&gt;And there you have it, implementation of JWT authentication using Golang for web services. You can find all the code &lt;a href="https://github.com/omnisyle/goliauth"&gt;here&lt;/a&gt;. If you have any suggestions, I’d love to listen. If you have any questions, please leave your comment below and I’ll do my best to answer. I really hope you find this tutorial series helpful. Thank you so much for reading it till the end. Cheers!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>go</category>
      <category>api</category>
      <category>jwt</category>
    </item>
    <item>
      <title>Simple JWT Authentication with Golang (Part 2)</title>
      <dc:creator>Si Le</dc:creator>
      <pubDate>Tue, 16 Apr 2019 05:22:12 +0000</pubDate>
      <link>https://dev.to/omnisyle/simple-jwt-authentication-with-golang-part-2-263</link>
      <guid>https://dev.to/omnisyle/simple-jwt-authentication-with-golang-part-2-263</guid>
      <description>&lt;p&gt;This is part two of a three-part series tutorial that builds a small but complete JWT authentication solution for internal API (most concepts can also be applied to build JWT auth for public API).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 1 — &lt;a href="https://dev.to/omnisyle/simple-jwt-authentication-for-golang-part-1-3kfo"&gt;Public/secret key generation and storage&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 2 — Build a CLI to create/retrieve App object&lt;/li&gt;
&lt;li&gt;Part 3 — &lt;a href="https://dev.to/omnisyle/simple-jwt-authentication-with-golang-part-3-1ja3"&gt;Build the JWT authentication middleware&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RG2pxQHC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AQoUJBQLOv6Vh_pgEYctC_A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RG2pxQHC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AQoUJBQLOv6Vh_pgEYctC_A.png" alt="" width="880" height="461"&gt;&lt;/a&gt;&lt;a href="https://jwt.io"&gt;https://jwt.io&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;In this part, we will build a mini CLI that helps us do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve the App (a set of public/secret key pair) object stored in our Postgres database by the public key.&lt;/li&gt;
&lt;li&gt;Generate a random key string to use as a master key.&lt;/li&gt;
&lt;li&gt;Create a new App object.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The CLI
&lt;/h3&gt;

&lt;p&gt;We will use Cobra, a CLI framework package, to quickly generate the basics of our CLI. Let’s get it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/spf13/cobra/cobra
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We will make a cmd package for all of our commands. Well, there’s only one for now. Let’s organize properly anyways. Here’s is our folder structure.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── cmd
│ ├── app.go
│ ├── key.go
│ └── root.go
├── internal
│ └── app
│ ├── app.go
│ ├── create.go
│ └── get.go
└── main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In root.go we combine all our commands under the one main command.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Root command will be called when you run go run main.go As you can see, we already have two subcommands, keyCmd and appCmd . We will call Execute in main.go's main function later on.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔑 Key Command
&lt;/h3&gt;

&lt;p&gt;We will write keyCmd first because it’s a lot simpler than appCmd . This command will generate a 32-bits key and print it to the screen.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Cobra’s command type has a few properties that we can use. However, the main ones are Use, Short, Long, and Run. The first property, Use , is crucial to identify how to call this command. In this case, we will call go run main.go key to use this command. Short and Long properties are simply descriptions of the command in short form which will be displayed in the help section of the parent command or long description when we call --help on the command itself. Run is pretty self-explanatory. It runs the function that we passed in. The function should take 2 arguments which first is the command itself, and second is the arguments of the command.&lt;/p&gt;

&lt;p&gt;We don’t use any arguments in this case since we always want to generate a 32-bits key and print it out.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔐 App Command
&lt;/h3&gt;

&lt;p&gt;This command will generate a credential key pairs, store them in the database and print out the keys. It can also fetch an App given its public key. It’s very useful when you have an internal API and want to give access to internal clients only. It can also be modified to work as an API endpoint.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;There are a few things going on here. First, we have another “rootCmd”, which in this case, the app command. This app command will be the root for two commands create and get . There are a few new things here compare to key command earlier. We use Args property as a validation mechanism to enforce certain rules. In bothcreate and get , we want to have at least one argument. They are [name] and [public_key] respectively.&lt;/p&gt;

&lt;p&gt;Second, we use a flag to take in a database URL connection. For simplicity, I defined var db string as a package variable. However, please feel free to refactor it to be contained in a struct or so. It’s important that we know where to connect to the database so we’ll make --db flag required. To bind a flag, we will call .StringVarP(destination *string, longFlag string, shortFlag string, defaultValue string, description string). As for .PersistentFlag() , we make the flag persistent because we bind it on the app command and not on create or get . A persistent flag will make the flag available even when you call child commands. Otherwise, flags are available under local scope only and you won’t be able to access var db value. Here are the complete commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go app &lt;span class="nt"&gt;--db&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;dbURL] create &lt;span class="o"&gt;[&lt;/span&gt;name]
go run main.go app &lt;span class="nt"&gt;--db&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;dbURL] get &lt;span class="o"&gt;[&lt;/span&gt;public&lt;span class="se"&gt;\_&lt;/span&gt;key]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now that we have the commands set up. Let’s dive into the handlers.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The handlers are small because we delegate most of the work to other services that will do the work for us. Those services are concerned with how to create an App object given the information from the commands. These handlers are only responsible for calling those services. In addition, we will also have a data access layer that will take care of saving all of the information to the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oq90ef2b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/316/1%2A-xo3Mq8qQJ-kH-86VwoA6Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oq90ef2b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/316/1%2A-xo3Mq8qQJ-kH-86VwoA6Q.png" alt="" width="316" height="411"&gt;&lt;/a&gt;Layers for the CLI&lt;/p&gt;

&lt;p&gt;Since the data access layer is quite long with SQL commands, I’d recommend you to take a look at the &lt;a href="https://github.com/omnisyle/goliauth"&gt;GitHub repo&lt;/a&gt; itself. It’s under goliauth/internal/app/app.go . For now, we will focus on the two service functions that are used to create and get an App object.&lt;/p&gt;

&lt;h3&gt;
  
  
  💁🏻‍♂️ Services Layer
&lt;/h3&gt;

&lt;p&gt;Welcome to our CLI service. Here we have the CreateApp function that will… create an app, obviously. We begin by generating 2 random keys to be used as a public and secret key. Then, we encrypt the secret key and pass along the app’s name from our command to form an App struct. When everything is properly formed, we call .Create to instruct the data access layer to save all the information to the database given the URL.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Next, we have GetApp function that will find our credentials given a public key. Using the public key, we can query the database and returns an App object that will contain an encrypted key. We will proceed to turn that key into bytes. Then, we decrypt that key an assign it back to the App object for reading. Finally, we will read it from the command and print it out.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Voila, that’s all there is to the CLI. Let’s see if it works&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aA1kS9fn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/558/1%2AcWQaqzNuvwAflS_nm2o-MQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aA1kS9fn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/558/1%2AcWQaqzNuvwAflS_nm2o-MQ.gif" alt="" width="558" height="145"&gt;&lt;/a&gt;See higher resolution at &lt;a href="https://asciinema.org/a/241101"&gt;&lt;/a&gt;&lt;a href="https://asciinema.org/a/241101"&gt;https://asciinema.org/a/241101&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Full Github repo is here &lt;a href="https://github.com/omnisyle/goliauth"&gt;https://github.com/omnisyle/goliauth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading to the end!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>go</category>
      <category>api</category>
      <category>jwt</category>
    </item>
    <item>
      <title>Simple JWT Authentication for Golang (Part 1)</title>
      <dc:creator>Si Le</dc:creator>
      <pubDate>Mon, 01 Apr 2019 03:54:51 +0000</pubDate>
      <link>https://dev.to/omnisyle/simple-jwt-authentication-for-golang-part-1-3kfo</link>
      <guid>https://dev.to/omnisyle/simple-jwt-authentication-for-golang-part-1-3kfo</guid>
      <description>&lt;p&gt;When it comes to an API, we need authentication for users to access their information. JWT is widely used for API authentication because of its stateless nature. In this tutorial series, I will share with you what I’ve learned when I implemented JWT authentication.&lt;/p&gt;

&lt;p&gt;There are three parts in this tutorial&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 1 — Public/secret key generation and storage&lt;/li&gt;
&lt;li&gt;Part 2 — &lt;a href="https://dev.to/omnisyle/simple-jwt-authentication-with-golang-part-2-263"&gt;Build a CLI to create/retrieve App object&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 3 — &lt;a href="https://dev.to/omnisyle/simple-jwt-authentication-with-golang-part-3-1ja3"&gt;Build the JWT authentication middleware&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADNxfiTZFOcrj694IM3W7Yg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADNxfiTZFOcrj694IM3W7Yg.png"&gt;&lt;/a&gt;&lt;a href="https://jwt.io" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://jwt.io" rel="noopener noreferrer"&gt;https://jwt.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this tutorial, we’ll use the following tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Golang 1.11 Darwin&lt;/li&gt;
&lt;li&gt;Postgres&lt;/li&gt;
&lt;li&gt;JWT library recommended by jwt.io: &lt;a href="http://github.com/dgrijalva/jwt-go" rel="noopener noreferrer"&gt;github.com/dgrijalva/jwt-go&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Golang built-in crypto packages&lt;/li&gt;
&lt;li&gt;Developer (very important: please feed some coffee fuel before use)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Assumptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You know AES encryption (just enough to use, no need to read the research papers)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer: All the codes here are not 100% mine. It’s a compilation from multiple sources such as open-source projects, go documentation, etc.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I will include the resources I used at the end of the tutorial. For now, let’s dive in.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ The process
&lt;/h3&gt;

&lt;p&gt;To authenticate with our API, every request must include a public key and a JWT token in its headers. The JWT token is a bearer token in “Authorization” header. The process to authenticate a request is as follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When our API receives the request, we check for its public key header.&lt;/li&gt;
&lt;li&gt;We use that public key to check if the app trying to access our API is registered in our database.&lt;/li&gt;
&lt;li&gt;If we found the app using its public key, we will use its secret key (also stored in our database) to verify its JWT signature.&lt;/li&gt;
&lt;li&gt;Otherwise, we return status 401 to the client.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole process can be visualized like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F729%2F1%2ANYoZL5SU8X93H4pCMWcRHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F729%2F1%2ANYoZL5SU8X93H4pCMWcRHg.png"&gt;&lt;/a&gt;JWT Authentication Flow for our API&lt;/p&gt;

&lt;h3&gt;
  
  
  🗝 The key couple
&lt;/h3&gt;

&lt;p&gt;For any apps that want to use our API, we need to give them a secret and public key to authenticate. To do this, we will generate two random 16 bytes keys and store it in our database. To protect the secret keys, we will use AES encryption to encrypt the key before we write it to the database.&lt;/p&gt;

&lt;p&gt;Why encryption? The secret key is an app’s password, it needs to be protected. However, unlike passwords, we will need the original value to verify the JWT signature. Therefore, encryption is a better solution to store the secret keys in our database.&lt;/p&gt;

&lt;p&gt;There are two parts we need to use AES encryption. First, we need a master secret key on our side. We will use the same secret to encrypt all secret keys. Second, for each secret key, we will include a salt (or iv in this case) to vary the final encrypted key. The final data struct will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// App is a generated public/secret key pair&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;  
  &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="n"&gt;EncryptedSecretKey&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="n"&gt;PublicKey&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="n"&gt;CreatedAt&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;
  &lt;span class="n"&gt;UpdatedAt&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now we only need to write a SQL command to create an App table with those columns&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Next, we will write a function to generate a random key string. This function will generate a 32 bytes random string to be used as a public key or secret key. Basically, we’ll call it twice to get the original values for both keys. You can change the number of bytes to adjust the length of the key. One thing to note is fmt.Sprintf("%x", key) will print out 2 characters per byte (&lt;a href="https://golang.org/pkg/fmt/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;), so you will get a string twice the length of the byte array. In our case, it will generate a string of 64 characters. Read more about go strings &lt;a href="https://blog.golang.org/strings" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  🔒 Encryption
&lt;/h3&gt;

&lt;p&gt;To store our secret key securely in the database, we will have a master key used to encrypt every secret key with an Initial Value (IV, or nonce, or salt, whatever you’d like to call it). The master key will be stored as an environment variable (for simplicity). The length of the master key is important to determine whether the final encrypted value is an AES128, 192 or 256. The master key must be 32, 48 or 64 characters long, corresponding to AES128, 192, and 256.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will use AES256-GCM to encrypt our secret key. Go has a built-in aes package that can do the job for us. Here are our Encrypt and Decrypt functions.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;First is our Encrypt function. I’ve separated it from our Decrypt function below so we have everything we need in one file. The process can be simplified as follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the master secret key.&lt;/li&gt;
&lt;li&gt;Make a new AES cipher block.&lt;/li&gt;
&lt;li&gt;Make a new GCM cipher block which returns an AEAD object.&lt;/li&gt;
&lt;li&gt;Generate a random IV with the same size of the required nonce length (default to 12 bytes). This IV will be prepended to the final key.&lt;/li&gt;
&lt;li&gt;Finally, “Seal” the nonce and in the key to an encrypted value to a destination (dst). That’s why we use the nonce as the destination. It will append the encrypted key to the nonce. Here for reference.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;Seal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;additionalData&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  🔓 Decryption
&lt;/h3&gt;

&lt;p&gt;Similar to our encryption process, we will utilize go’s built-in packages to decrypt encrypted keys stored in our database to be used in JWT signature verification. Here is our function.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Again, here’s the summary of our process.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the master secret key.&lt;/li&gt;
&lt;li&gt;Make a new AES cipher block.&lt;/li&gt;
&lt;li&gt;Make a new GCM cipher block which returns an AEAD object.&lt;/li&gt;
&lt;li&gt;Verify the encrypted key’s length.&lt;/li&gt;
&lt;li&gt;Finally, “Open” the encrypted key by passing in nil for the destination, then the nonce which was prepended in the final key, then the actual encrypted key bytes (the latter part), and nil for extra data.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Open(dst, nonce, ciphertext, additionalData [][byte](https://golang.org/pkg/builtin/#byte)) ([][byte](https://golang.org/pkg/builtin/#byte), [error](https://golang.org/pkg/builtin/#error)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it for our encryption functions. Here is the final code on &lt;a href="https://github.com/omnisyle/goliauth" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. I hope this is helpful 😁.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.comparitech.com/blog/information-security/what-is-aes-encryption" rel="noopener noreferrer"&gt;https://www.comparitech.com/blog/information-security/what-is-aes-encryption&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://golang.org/pkg/crypto/cipher/" rel="noopener noreferrer"&gt;https://golang.org/pkg/crypto/cipher/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Galois/Counter_Mode" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Galois/Counter_Mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://golang.org/pkg/crypto/aes/#NewCipher" rel="noopener noreferrer"&gt;https://golang.org/pkg/crypto/aes/#NewCipher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://golang.org/pkg/encoding/hex/#DecodeString" rel="noopener noreferrer"&gt;https://golang.org/pkg/encoding/hex/#DecodeString&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/golang/go/blob/master/src/crypto/cipher/gcm.go#L162" rel="noopener noreferrer"&gt;https://github.com/golang/go/blob/master/src/crypto/cipher/gcm.go#L162&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.tclaverie.eu/posts/understanding-golangs-aes-implementation-t-tables/" rel="noopener noreferrer"&gt;https://blog.tclaverie.eu/posts/understanding-golangs-aes-implementation-t-tables/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/gtank/cryptopasta" rel="noopener noreferrer"&gt;https://github.com/gtank/cryptopasta&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>go</category>
      <category>jwt</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Firebase Firestore Initial Payload with onSnapshot</title>
      <dc:creator>Si Le</dc:creator>
      <pubDate>Thu, 06 Sep 2018 18:42:19 +0000</pubDate>
      <link>https://dev.to/omnisyle/firebase-firestore-initial-payload-with-onsnapshot-3i98</link>
      <guid>https://dev.to/omnisyle/firebase-firestore-initial-payload-with-onsnapshot-3i98</guid>
      <description>&lt;h1&gt;
  
  
  Firebase Firestore Initial Payload with onSnapshot
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_BXN0ISH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AB0Av_NnFrCKsyC7gN94ytg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_BXN0ISH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AB0Av_NnFrCKsyC7gN94ytg.png" alt="" width="880" height="440"&gt;&lt;/a&gt;Image from &lt;a href="https://firebase.google.com/images/social.png"&gt;&lt;/a&gt;&lt;a href="https://firebase.google.com/images/social.png"&gt;https://firebase.google.com/images/social.png&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt; : This approach only works for web because Firestore doesn’t offer caching for web. On iOS and Android, you must take another approach to handle initial payload and subsequent updates due to caching. The first response from a subscription on iOS or Android will come from cache. Second response is new updates from Firestore and subsequent responses are updates/create/destroy only.&lt;/p&gt;

&lt;p&gt;I’ve been using Firebase for a while now. One of the problems I’ve had with Firebase is this weird behaviour when you want to &lt;a href="https://firebase.google.com/docs/firestore/query-data/listen"&gt;subscribe to a query&lt;/a&gt;, it returns the whole result on the first call and returns new/updated documents afterward.&lt;/p&gt;

&lt;p&gt;Let’s say I want to ignore the initial load and only listen to new changes. That’s just purely subscription. &lt;strong&gt;How do you know which one is the first call?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Firebase doesn’t provide any ways to check whether the result set is the first one. I’ve tried stackoverflow to see if anybody encountered the same problem. This &lt;a href="https://stackoverflow.com/questions/49798693/differentate-between-first-time-querysnapshot-and-change-listener-in-firestore"&gt;thread&lt;/a&gt; is promising:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uCifmHd6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AlZTfjQWe_7AfK1P7fi8EIA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uCifmHd6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AlZTfjQWe_7AfK1P7fi8EIA.png" alt="" width="880" height="569"&gt;&lt;/a&gt;Stackoverflow Thread &lt;a href="https://stackoverflow.com/questions/49798693/differentate-between-first-time-querysnapshot-and-change-listener-in-firestore"&gt;&lt;/a&gt;&lt;a href="https://stackoverflow.com/questions/49798693/differentate-between-first-time-querysnapshot-and-change-listener-in-firestore"&gt;https://stackoverflow.com/questions/49798693/differentate-between-first-time-querysnapshot-and-change-listener-in-firestore&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looks like the first query snapshot only contains added event. Sure, but what if you want to listen to new document events too? Do you have to handle the first added event the same as subsequent added events?&lt;/p&gt;

&lt;p&gt;In my case, I want to &lt;strong&gt;ignore the first payload&lt;/strong&gt; altogether and only listen to new updates. A new update can be an added event other other events. Therefore, checking whether it’s an added event for first payload doesn’t work.&lt;/p&gt;

&lt;p&gt;What if I can count the number of invocation of the callback function and ignore the first invocation all together? Here’s a generic function wrapper that count the number of times the wrapped function is called.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;createFnCounter() takes 2 arguments, first is the function being wrapped, and second is the number of invocation needed before the wrapped function is called. Therefore, createFnCounter(foo, 1) will only call foo on the second call. I’m pretty sure some names in this function can be more explicit but you get the idea (in case you want to discuss, I’m down for it).&lt;/p&gt;

&lt;p&gt;How do you use this function? I have a collection named activities that contains all the activities happened to my chat channels collection. When a user sent a message to another user, there’s a new activity created/modified to notify the chat client, it’s saying, “Hey, there’s a new activity on this channel, do your thing”. The client received the event, and does its things. When the client initialize, I subscribe to activities collection as follow.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let’s incorporate createFnCounter to only receive updates and ignore initial payload.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Too verbose, I know, but 6 months from now when I look back at this code, I’ll know what happened.&lt;/p&gt;

&lt;p&gt;What if I want to get that initial payload too but do something different with it? Well, here we go&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;There you go, now you have a way to distinguish between initial load and subsequent updates when subscribing to documents on Firestore. Have other methods? Let me know!&lt;/p&gt;

&lt;p&gt;Thanks for reading! ≈&lt;/p&gt;

</description>
      <category>realtime</category>
      <category>javascript</category>
      <category>programming</category>
      <category>firestore</category>
    </item>
  </channel>
</rss>
