<?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: Kiran Mali</title>
    <description>The latest articles on DEV Community by Kiran Mali (@kdhttps).</description>
    <link>https://dev.to/kdhttps</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%2F151351%2Ffe6b525d-236f-4645-8bb6-0e89022ba76f.png</url>
      <title>DEV Community: Kiran Mali</title>
      <link>https://dev.to/kdhttps</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kdhttps"/>
    <language>en</language>
    <item>
      <title>AppAuth JS integration in React</title>
      <dc:creator>Kiran Mali</dc:creator>
      <pubDate>Mon, 10 Aug 2020 12:28:03 +0000</pubDate>
      <link>https://dev.to/kdhttps/appauth-js-integration-in-react-1m3e</link>
      <guid>https://dev.to/kdhttps/appauth-js-integration-in-react-1m3e</guid>
      <description>&lt;p&gt;❤️ What is OpenID Connect and why Authorization Code flow for React(SPA) Application?&lt;br&gt;
👉 &lt;a href="https://dev.to/kdhttps/the-best-security-for-single-page-applications-spa-openid-connect-oauth-2-0-authorization-code-pkce-flow-544p"&gt;Check my blog here for answer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎯 The &lt;a href="https://github.com/openid/AppAuth-JS" rel="noopener noreferrer"&gt;AppAuth JS&lt;/a&gt; is the best library to integrate OpenID Connect Authorization Code PKCE Flow at your React or any single page application technology.&lt;/p&gt;

&lt;p&gt;🔥 Here is React JS code with AppAuth JS integration.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kdhttps" rel="noopener noreferrer"&gt;
        kdhttps
      &lt;/a&gt; / &lt;a href="https://github.com/kdhttps/appauth-react" rel="noopener noreferrer"&gt;
        appauth-react
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Appauth JS integration with React 🎯
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;App Auth React&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/openid/AppAuth-JS" rel="noopener noreferrer"&gt;App-Auth JS&lt;/a&gt; integration with the React App.
This project was bootstrapped with &lt;a href="https://github.com/facebook/create-react-app" rel="noopener noreferrer"&gt;Create React App&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/kdhttps/appauth-react./public/react-flow.gif"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fkdhttps%2Fappauth-react.%2Fpublic%2Freact-flow.gif" alt="react-flow"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Prerequisites&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Node JS &amp;gt;= 10.x.x&lt;/li&gt;
&lt;li&gt;Auth0 client - Currently for I am using auth0.com as a OP Server. Demo should work with every OP Provider.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Configuration&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Use &lt;code&gt;environment.js&lt;/code&gt; to set OP Client configuration.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Start&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Install Dependencies&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Start Application&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Runs the app in the development mode.&lt;br&gt;
Open &lt;a href="http://localhost:4200" rel="nofollow noopener noreferrer"&gt;http://localhost:4200&lt;/a&gt; to view it in the browser.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kdhttps/appauth-react" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  📚 Let's Go Step by Step
&lt;/h2&gt;

&lt;p&gt;Before start, You need to create an OP Client using your OP Admin Panel. Setup client, client id, client secret, redirect login URL, response_type = code, grant_type = authorization_code and refresh_token(as per your need).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;https://server.com&lt;/code&gt; is just for example. You need to use your OP server URL.&lt;/p&gt;
&lt;/blockquote&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%2Fzgds6m0n0ykpq30oihlb.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%2Fzgds6m0n0ykpq30oihlb.png" alt="Appauth-authorization-code-pkce-flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  There are 3 main steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Authorization Request to OP Server&lt;/li&gt;
&lt;li&gt;Get a &lt;code&gt;code&lt;/code&gt; from URL and get &lt;code&gt;access_token&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Get user info using access_token&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  ⭐ Authorization Request to OP Server
&lt;/h2&gt;

&lt;p&gt;The first task is to make the authorization requests to the OpenID Connect server.&lt;/p&gt;

&lt;p&gt;Below all code in one file. Please check my &lt;a href="https://github.com/kdhttps/appauth-react" rel="noopener noreferrer"&gt;appauth-react&lt;/a&gt; repo for whole code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; First step is to initialize the &lt;code&gt;RedirectRequestHandler&lt;/code&gt;. This object is responsible to handle the redirect task. It needs 4 Parameters.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A. Define Storage
B. URL Parameter Parser to get query params
C. Current location or URL
D. Crypto Method - to generate code_verifier and code_challenge
&lt;/code&gt;&lt;/pre&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;RedirectRequestHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;LocalStorageBackend&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DefaultCrypto&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@openid/appauth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NoHashQueryStringUtils&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./noHashQueryStringUtils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authorizationHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RedirectRequestHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LocalStorageBackend&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; 
       &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NoHashQueryStringUtils&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; 
       &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DefaultCrypto&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;&lt;strong&gt;2.&lt;/strong&gt; Second step is to configure query param parser&lt;/p&gt;

&lt;p&gt;It is for URL parsing. Default it assume that you have &lt;strong&gt;#&lt;/strong&gt; in URL. If you worked on OLD Angular.js then it uses &lt;strong&gt;#&lt;/strong&gt; for client-side routing. &lt;/p&gt;

&lt;p&gt;If you want to change this method then you can easily overwrite the method like below code:&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;BasicQueryStringUtils&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@openid/appauth&lt;/span&gt;&lt;span class="dl"&gt;'&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;NoHashQueryStringUtils&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BasicQueryStringUtils&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useHash&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="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="cm"&gt;/* never use hash */&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;&lt;strong&gt;3.&lt;/strong&gt; Third Step is AppAuth needs your OP Server configuration information that is provided by endpoint &lt;code&gt;https://server.com/.well-known/openid-configuration&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Below AppAuthJS code help you hit, get info, and stored info in local storage. This information is internally used by AppAuthJS.&lt;/p&gt;

&lt;p&gt;You just need to pass two parameters.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A. Your OP Server URL: for example: https://server.com
B. FetchRequester: It is Javascript Fetch API to make an HTTP Request to OP configuration endpoint. If you miss this parameter, It will use JQuery and we don't want to use JQuery in React Application.
&lt;/code&gt;&lt;/pre&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;AuthorizationServiceConfiguration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;FetchRequestor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@openid/appauth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;AuthorizationServiceConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchFromIssuer&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;your_op_seerver_url&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FetchRequestor&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;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;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="c1"&gt;// You need to add auth request code here&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;&lt;strong&gt;4.&lt;/strong&gt; Make an auth request. Below is a combined code with configuration info step.&lt;/p&gt;

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

 &lt;span class="nx"&gt;AuthorizationServiceConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchFromIssuer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FetchRequestor&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&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;authRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="na"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your_client_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;redirect_uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your_redirect_login_url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openid email profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;response_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthorizationRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RESPONSE_TYPE_CODE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="c1"&gt;// extras: environment.extra&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;

               &lt;span class="c1"&gt;// Please check next point 5 for this.&lt;/span&gt;
&lt;span class="nx"&gt;authorizationHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;performAuthorizationRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authRequest&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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;Pass extra parameters using &lt;strong&gt;extra&lt;/strong&gt; property.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.&lt;/strong&gt; Redirect to OP for Auth&lt;/p&gt;

&lt;p&gt;It needs two parameters first configuration information and second is auth Request.&lt;/p&gt;

&lt;p&gt;Use the below code for this. Once this code executes, it will redirect you to OP Server.&lt;/p&gt;

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

&lt;span class="nx"&gt;authorizationHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;performAuthorizationRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  ⭐ OP Server will authenticate the user and redirect back to your side with &lt;strong&gt;code&lt;/strong&gt; in URL. Let's assume you configure redirect login URL is &lt;code&gt;https://client.com/callback&lt;/code&gt;. Please check my &lt;a href="https://github.com/kdhttps/appauth-react" rel="noopener noreferrer"&gt;appauth-react&lt;/a&gt; repo for Flow GIF and code. You will get an idea.
&lt;/h4&gt;
&lt;h2&gt;
  
  
  ⭐ Get a &lt;code&gt;code&lt;/code&gt; from URL and get &lt;code&gt;access_token&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Let's assume URL in the browser is like now &lt;code&gt;https://client.com/callback?code=[code_send_by_op_server]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;we are now on &lt;code&gt;/callback&lt;/code&gt; react-router. so you need to handle the next operations on this route.&lt;/p&gt;

&lt;p&gt;Note: You can combine these steps into one file. Currently, for an easy explanation, I am doing it in different files.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; The first step you need to configure the &lt;code&gt;AuthorizationNotifier&lt;/code&gt; which will trigger when you want to process code(the code from URL).&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;AuthorizationServiceConfiguration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;RedirectRequestHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;AuthorizationNotifier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;FetchRequestor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LocalStorageBackend&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DefaultCrypto&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@openid/appauth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;NoHashQueryStringUtils&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./noHashQueryStringUtils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authorizationHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RedirectRequestHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LocalStorageBackend&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NoHashQueryStringUtils&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DefaultCrypto&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;notifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationNotifier&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;authorizationHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAuthorizationNotifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAuthorizationListener&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="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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="c1"&gt;// response object returns code which is in URL i.e. response.code&lt;/span&gt;
    &lt;span class="c1"&gt;// request object returns code_verifier i.e request.internal.code_verifier&lt;/span&gt;
    &lt;span class="c1"&gt;// you will need to add here token request process&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Above notifier only trigger when you want it using below code:&lt;/p&gt;

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

&lt;span class="nx"&gt;authorizationHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;completeAuthorizationRequestIfPossible&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Once this code executes, it will trigger the notifier and in the response object, you will get code from URL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Request for access_token &lt;/p&gt;

&lt;p&gt;The below code is inside the notifier.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A. First, you need to create a token request object
B. Again get configuration information
C. Hit `/token` endpoint and get token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;tokenHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BaseTokenRequestHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FetchRequestor&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAuthorizationListener&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="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization request complete &lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="s2"&gt;`Authorization Code  &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;extras&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&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;request&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;extras&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
                    &lt;span class="nx"&gt;extras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code_verifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code_verifier&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c1"&gt;// A. First, you need to create a token request object&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tokenRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TokenRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="na"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your_client_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;redirect_uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your_redirect_login_url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;grant_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GRANT_TYPE_AUTHORIZATION_CODE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nx"&gt;extras&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;

                &lt;span class="c1"&gt;// B. Again get configuration information&lt;/span&gt;
&lt;span class="nx"&gt;AuthorizationServiceConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchFromIssuer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FetchRequestor&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;oResponse&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;configuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;oResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                        &lt;span class="c1"&gt;// C. Hit `/token` endpoint and get token&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tokenHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;performTokenRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenRequest&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;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;oResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;access_token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="c1"&gt;// do operation now as per your need&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;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/profile&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="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oError&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;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oError&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;Now, you have &lt;code&gt;access_token&lt;/code&gt;, you can store it in localStorage and use it in the whole application.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⭐ Get user info using access_token
&lt;/h2&gt;

&lt;p&gt;You don't need AppAuthJS for this task. You just need to hit the &lt;code&gt;/userinfo&lt;/code&gt; endpoint of your OP Server and it will return you the user information.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;https://server.com&lt;/code&gt; is just for example. You need to use your OP server URL.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;let's assume we are now on &lt;code&gt;/profile&lt;/code&gt; page.&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;fetchUserInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://server.com/userinfo`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&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;const&lt;/span&gt; &lt;span class="nx"&gt;Profile&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;userInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUserInfo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&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;fetchToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;access_token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;fetchUserInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;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;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nf"&gt;setUserInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&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="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="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;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;Done.&lt;/p&gt;

&lt;p&gt;We just integrated AppAuth JS into React Application.&lt;/p&gt;

&lt;p&gt;Please check my &lt;a href="https://github.com/kdhttps/appauth-react" rel="noopener noreferrer"&gt;appauth-react&lt;/a&gt; repo for whole integration.&lt;/p&gt;

&lt;p&gt;If you are on angular then please check my &lt;a href="https://github.com/kdhttps/appauth-angular" rel="noopener noreferrer"&gt;appauth-angular&lt;/a&gt; repo.&lt;/p&gt;

&lt;p&gt;You can integrate AppAuthJS in any client-side technology using the above steps.&lt;/p&gt;

&lt;p&gt;Hope this will help !!!&lt;/p&gt;

&lt;h4&gt;
  
  
  #HappySharing #HappyHelping
&lt;/h4&gt;

</description>
      <category>appauth</category>
      <category>react</category>
      <category>security</category>
      <category>openidconnect</category>
    </item>
    <item>
      <title>The Best Security for Single Page Applications(SPA) - OpenID Connect OAuth 2.0 Authorization Code PKCE Flow</title>
      <dc:creator>Kiran Mali</dc:creator>
      <pubDate>Fri, 07 Aug 2020 12:27:23 +0000</pubDate>
      <link>https://dev.to/kdhttps/the-best-security-for-single-page-applications-spa-openid-connect-oauth-2-0-authorization-code-pkce-flow-544p</link>
      <guid>https://dev.to/kdhttps/the-best-security-for-single-page-applications-spa-openid-connect-oauth-2-0-authorization-code-pkce-flow-544p</guid>
      <description>&lt;p&gt;The user identity and data security is a crucial part of your application. Your application should need to be 100% sure that the one who is using the application is the correct user. The only username/password security to identify users and for application security is a bad idea 👎 .&lt;/p&gt;

&lt;h3&gt;
  
  
  What is OpenID Connect OAuth 2.0?
&lt;/h3&gt;

&lt;p&gt;🎯 &lt;code&gt;OpenID Connect OAuth 2.0&lt;/code&gt; is the best security framework available nowadays. &lt;/p&gt;

&lt;p&gt;You must have seen in so many applications that &lt;strong&gt;log in with Twitter, Gmail, Facebook&lt;/strong&gt;. So Once we click on a button it redirects us to specific social media(OP - OpenID Connect Server). We login to social media, redirect back to the current application and the current application allows us to log in. So How can social media platform allows the other application to authenticate and authorized user so This is OpenID Connect OAuth 2.0 security. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://openid.net/connect/"&gt;More Details&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of building your own just username/password security, you should have to integrate implement or integrate OpenID Connect OAuth 2.0 security.&lt;/p&gt;

&lt;p&gt;There are many security flows available in OpenID Connect OAuth 2.0. As per your Application requirements and flow, you can choose the flow.&lt;/p&gt;

&lt;p&gt;There are three flow for &lt;strong&gt;Single Page Application(SPA)&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Implicit flow&lt;/li&gt;
&lt;li&gt;Authorization Code Flow (without PKCE) - This is not really for SPA Applications&lt;/li&gt;
&lt;li&gt;Authorization Code PKCE Flow&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  ❌ Why not &lt;strong&gt;implicit flow&lt;/strong&gt;?
&lt;/h2&gt;

&lt;p&gt;Because it exposes access_token into the browser URL and you will not have &lt;strong&gt;refresh_token&lt;/strong&gt; facility because OP client is not able to call &lt;strong&gt;/token&lt;/strong&gt; endpoint which requires client authentication.&lt;/p&gt;

&lt;p&gt;Below is the implicit flow diagram which helps you to understand the whole flow.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: server.com and client.com are just for example. You need to use endpoints as per your OpenID Providers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m256ySWy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k7aly1bl3t37w1qgejhk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m256ySWy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k7aly1bl3t37w1qgejhk.png" alt="Alt Text" width="880" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ❌ Why not &lt;strong&gt;Authorization Code Flow (without PKCE)&lt;/strong&gt; for SPA?
&lt;/h2&gt;

&lt;p&gt;Stop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K_f6omAg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k4ue3k96dgc3xsodzca7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K_f6omAg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k4ue3k96dgc3xsodzca7.gif" alt="Alt Text" width="220" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't use it. Without PKCE that means You need to store the client secret on your browser to request &lt;strong&gt;/token&lt;/strong&gt; endpoint and get an access token. Store client secret at the browser is a big security risk.&lt;/p&gt;

&lt;p&gt;This flow is generally used at the server-side. Where we can safely store client id and client secret. In this case, the &lt;strong&gt;/token&lt;/strong&gt; endpoint is protected by &lt;a href="http://webconcepts.info/concepts/oauth-token-endpoint-auth-method/"&gt;&lt;strong&gt;Token Endpoint authentication methods&lt;/strong&gt;&lt;/a&gt;. ✔️ You don't need PKCE flow if you are managing authentication flow using the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✔️ Why to use &lt;strong&gt;Authorization Code PKCE flow.&lt;/strong&gt;?
&lt;/h2&gt;

&lt;p&gt;❤️ If you have a SPA(Single Page Application), the best security flow for this is the &lt;strong&gt;Authorization Code with PKCE flow.&lt;/strong&gt; Because It &lt;strong&gt;does not expose access token&lt;/strong&gt; to the browser in URL and you &lt;strong&gt;don't need client secret&lt;/strong&gt; at all.&lt;/p&gt;

&lt;p&gt;PKCE stands for &lt;strong&gt;Proof Key for Code Exchange&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this case, the &lt;strong&gt;/token&lt;/strong&gt; endpoint is not protected by &lt;a href="http://webconcepts.info/concepts/oauth-token-endpoint-auth-method/"&gt;&lt;strong&gt;Token Endpoint authentication methods&lt;/strong&gt;&lt;/a&gt;. Because of PCKE, OP Server use &lt;strong&gt;code_challenge&lt;/strong&gt; and &lt;strong&gt;code_verifier&lt;/strong&gt; to verify request. You also need to check what should be the token endpoint auth method for PKCE flow. This is vary as per oidc service provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✔️ Authorization Code PKCE flow and implementation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rSrpTi4s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zgds6m0n0ykpq30oihlb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rSrpTi4s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zgds6m0n0ykpq30oihlb.png" alt="Alt Text" width="880" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: server.com and client.com are just for example. You need to use endpoints as per your OpenID Connect Providers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;1.First, you need to &lt;strong&gt;code_verifier&lt;/strong&gt; and &lt;strong&gt;code_challenge&lt;/strong&gt;. Below is the code of Node.js to generate &lt;strong&gt;code_challenge&lt;/strong&gt;. &lt;strong&gt;code_verifier&lt;/strong&gt; is just a random string.&lt;br&gt;
&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;var&lt;/span&gt; &lt;span class="nx"&gt;code_verifier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s4vqXQA0ePi98eS9Px4jcghBi7UQHRaQl6jMRwLkBj9Eh8g1yxnesereK4jUHdAT0HkLEWBPLZ8z35HX1Ditxf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base64url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code_verifier&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;code_challenge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base64url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code_challenge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is a simple Node.js code. For SPA applications, there is the best library available that is &lt;a href="https://github.com/openid/AppAuth-JS"&gt;AppAuth JS&lt;/a&gt;. I've a integrate it with Angular and React Please check links&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kdhttps"&gt;
        kdhttps
      &lt;/a&gt; / &lt;a href="https://github.com/kdhttps/appauth-angular"&gt;
        appauth-angular
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Appauth JS integration with Angular 🚀 🛡️
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
App Auth Angular&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/openid/AppAuth-JS"&gt;App-Auth JS&lt;/a&gt; integration with the Angular App.
This project was generated with &lt;a href="https://github.com/angular/angular-cli"&gt;Angular CLI&lt;/a&gt; version 8.3.20.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/kdhttps/appauth-angular./src/assets/angular-flow.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRiLCHM_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/kdhttps/appauth-angular./src/assets/angular-flow.gif" alt="angular-flow"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Prerequisites&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Node JS &amp;gt;= 10.x.x&lt;/li&gt;
&lt;li&gt;@angular/cli &amp;gt;= 8.3.21&lt;/li&gt;
&lt;li&gt;Auth0 client - Currently for I am using auth0.com as a OP Server. Demo should work with every OP Provider.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
Configuration&lt;/h2&gt;
&lt;p&gt;Use &lt;code&gt;environment.ts&lt;/code&gt; to set OP Client configuration.&lt;/p&gt;
&lt;h2&gt;
Start&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Install Dependencies&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Run &lt;code&gt;ng serve&lt;/code&gt; for a dev server. Navigate to &lt;code&gt;http://localhost:4200/&lt;/code&gt;. The app will automatically reload if you change any of the source files.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kdhttps/appauth-angular"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kdhttps"&gt;
        kdhttps
      &lt;/a&gt; / &lt;a href="https://github.com/kdhttps/appauth-react"&gt;
        appauth-react
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Appauth JS integration with React 🎯
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
App Auth React&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/openid/AppAuth-JS"&gt;App-Auth JS&lt;/a&gt; integration with the React App.
This project was bootstrapped with &lt;a href="https://github.com/facebook/create-react-app"&gt;Create React App&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/kdhttps/appauth-react./public/react-flow.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dCFkN0qz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/kdhttps/appauth-react./public/react-flow.gif" alt="react-flow"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Prerequisites&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Node JS &amp;gt;= 10.x.x&lt;/li&gt;
&lt;li&gt;Auth0 client - Currently for I am using auth0.com as a OP Server. Demo should work with every OP Provider.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
Configuration&lt;/h2&gt;
&lt;p&gt;Use &lt;code&gt;environment.js&lt;/code&gt; to set OP Client configuration.&lt;/p&gt;
&lt;h2&gt;
Start&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Install Dependencies&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Start Application&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Runs the app in the development mode.&lt;br&gt;
Open &lt;a href="http://localhost:4200" rel="nofollow"&gt;http://localhost:4200&lt;/a&gt; to view it in the browser.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kdhttps/appauth-react"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;2.Authorization request to OP Server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;HTTP Get redirect

https://server.com/authorize
?redirect_uri&lt;span class="o"&gt;=&lt;/span&gt;https://client.com/callback
&amp;amp;client_id&lt;span class="o"&gt;=[&lt;/span&gt;your_client_id]
&amp;amp;response_type&lt;span class="o"&gt;=&lt;/span&gt;code
&amp;amp;state&lt;span class="o"&gt;=[&lt;/span&gt;uuid]
&amp;amp;scope&lt;span class="o"&gt;=&lt;/span&gt;openid%20email%20profile
&amp;amp;code_challenge&lt;span class="o"&gt;=[&lt;/span&gt;code_challenge]
&amp;amp;code_challenge_method&lt;span class="o"&gt;=&lt;/span&gt;S256
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;3.OP Server authenticates the user and redirects back to &lt;code&gt;https://client.com/callback&lt;/code&gt; with code in URL. You can check the above flow diagram.&lt;/p&gt;

&lt;p&gt;4.Now request to &lt;strong&gt;&lt;a href="https://server.com/token"&gt;https://server.com/token&lt;/a&gt;&lt;/strong&gt; with &lt;strong&gt;code&lt;/strong&gt; and &lt;strong&gt;code_challenge&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;HTTP POST https://server.com/token
content-type: application/x-www-form-urlencoded
accept: application/json

Form Data:
grant_type: authorization_code
client_id: &lt;span class="o"&gt;[&lt;/span&gt;your_client_id]
redirect_uri: &lt;span class="o"&gt;[&lt;/span&gt;your_callback_url]
code: &lt;span class="o"&gt;[&lt;/span&gt;code]
code_verifier: &lt;span class="o"&gt;[&lt;/span&gt;code_verifier]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This request will return your JSON response with &lt;strong&gt;access_token&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;5.Request to &lt;strong&gt;&lt;a href="https://server.com/usernifo"&gt;https://server.com/usernifo&lt;/a&gt;&lt;/strong&gt; endpoint with &lt;strong&gt;access_token&lt;/strong&gt; and get user info. &lt;/p&gt;

&lt;p&gt;I am not forcing you to use PKCE flow but it is better than the implicit flow.&lt;/p&gt;

&lt;p&gt;I've integrated the Authorization Code PKCE flow in my Angular and React App. Code links are given below:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kdhttps"&gt;
        kdhttps
      &lt;/a&gt; / &lt;a href="https://github.com/kdhttps/appauth-angular"&gt;
        appauth-angular
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Appauth JS integration with Angular 🚀 🛡️
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kdhttps"&gt;
        kdhttps
      &lt;/a&gt; / &lt;a href="https://github.com/kdhttps/appauth-react"&gt;
        appauth-react
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Appauth JS integration with React 🎯
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I've one application on Heroku. If you want to check then click here &lt;a href="https://mean-star.herokuapp.com"&gt;https://mean-star.herokuapp.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am using &lt;a href="//auth0.com"&gt;auth0.com&lt;/a&gt; as my OpenID Connect Server. You can use any provider which provides you OpenID Connect Standards. I would like to list here some: &lt;a href="//jans.io"&gt;Janssen Project Auth Server&lt;/a&gt;, &lt;a href="//gluu.org"&gt;Gluu Server&lt;/a&gt;, Auth0, Okta, KeyCloak. Please comment if you have more OpenID Connect Providers&lt;/p&gt;

&lt;p&gt;You can also use Google, Twitter, Facebook who provide this feature.&lt;/p&gt;

&lt;p&gt;Happy Helping 😊, Thank you !!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kdhttps.com"&gt;For More Blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openidconnect</category>
      <category>appauth</category>
      <category>angular</category>
      <category>react</category>
    </item>
    <item>
      <title>The Idea behind Netlify and Heroku Free Deployment and Domain linking</title>
      <dc:creator>Kiran Mali</dc:creator>
      <pubDate>Sun, 05 Jul 2020 10:57:36 +0000</pubDate>
      <link>https://dev.to/kdhttps/the-idea-behind-netlify-and-heroku-free-deployment-and-domain-linking-1mn8</link>
      <guid>https://dev.to/kdhttps/the-idea-behind-netlify-and-heroku-free-deployment-and-domain-linking-1mn8</guid>
      <description>&lt;p&gt;Everyone knows that Netlify and Heroku has a free plan where you can deploy your application. My main idea behind this blog is &lt;code&gt;Free deployment and linking with a custom domain&lt;/code&gt; so that &lt;code&gt;web traffic will keep remain on your domain&lt;/code&gt;. In case your user increase, you can buy dedicated servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminology 📚
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Custom Domain&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The domain which you buy from a domain provider e.g. &lt;a href="//godaddy.com"&gt;Godaddy.com&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technology Stack ❤️
&lt;/h2&gt;

&lt;p&gt;The Technology stack which I've used for my blog site &lt;a href="https://kdhttps.com"&gt;https://kdhttps.com&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Angular: You can use any SPA e.g. React, Vue.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scully.io/"&gt;Scully&lt;/a&gt; - Angular Static Site Generator. There are many options available for Vue and React.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mdbootstrap.com"&gt;mdBootstrap&lt;/a&gt; for CSS and Design &lt;/li&gt;
&lt;li&gt;Node&lt;/li&gt;
&lt;li&gt;Mongo&lt;/li&gt;
&lt;li&gt;Express&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Problems 🧐
&lt;/h2&gt;

&lt;p&gt;So below are the problems which I faced:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://heroku.com"&gt;Heroku&lt;/a&gt; allows you to deploy the full dynamic site but &lt;code&gt;for custom domain linking you have to buy a paid plan.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://netlify.com"&gt;Netlify&lt;/a&gt; allows you to deploy the &lt;a href="https://jamstack.org/"&gt;JAM Stack&lt;/a&gt;. In short, It allows us to deploy the static HTML. You can only use High-Level Languages(Node, PHP, Ruby, etc...) to build your project. &lt;code&gt;You can not deploy your server(e.g. Node JS) application on Netlify.&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;h2&gt;
  
  
  Solution 🤩
&lt;/h2&gt;

&lt;p&gt;Solution is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Deploy Backend Node Application on Heroku&lt;/li&gt;
&lt;li&gt;Deploy Frontend Angular Scully Application on Netlify&lt;/li&gt;
&lt;li&gt;I used Heroku to write my blogs, store it in MongoDB, and display blogs on Netlify Frontend Application.&lt;/li&gt;
&lt;li&gt;Link domain with Netlify, So that Web traffic always on your domain.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Images 🥙
&lt;/h2&gt;

&lt;p&gt;For resources, assets and images. I am using GitHub so that less space on Heroku and Netlify. &lt;/p&gt;



&lt;h2&gt;
  
  
  Github Code
&lt;/h2&gt;

&lt;p&gt;😍 &lt;a href="https://github.com/kdhttps/kdhttps:"&gt;https://github.com/kdhttps/kdhttps:&lt;/a&gt; The code which I've deployed on Netlify.&lt;/p&gt;

&lt;p&gt;😎 &lt;a href="https://github.com/kdhttps/mean-star:"&gt;https://github.com/kdhttps/mean-star:&lt;/a&gt; The code which I've deployed on Heroku.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;You need to deploy your Netlify project after every new blog because it will build a new static page for new pages and you have all Scully and SEO features.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion 📖
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;By the great combination of Heroku and Netlify, you can &lt;code&gt;freely deploy your applications&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;you just need to buy a domain. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This technology stack and deployment techniques will help you understand CI/CD modules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You &lt;code&gt;don't need to pay any money&lt;/code&gt; and &lt;code&gt;credit card&lt;/code&gt; for the whole implementation. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Note :📚
&lt;/h2&gt;

&lt;p&gt;Buy a dedicated server when your users increases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next 🎯
&lt;/h2&gt;

&lt;p&gt;If you build the blog site next thing you need is SEO. It is really important to bring users to your blog website.&lt;/p&gt;

&lt;p&gt;Check &lt;a href="https://dev.to/kdhttps/seo-tips-and-tricks-with-spa-1bcj"&gt;here my SEO Blog&lt;/a&gt;, It will help you with setting SEO for your SPA.&lt;/p&gt;

</description>
      <category>heroku</category>
      <category>netlify</category>
      <category>free</category>
      <category>blog</category>
    </item>
    <item>
      <title>SEO Tips and Tricks with Single Page Application Angular React Vue</title>
      <dc:creator>Kiran Mali</dc:creator>
      <pubDate>Thu, 25 Jun 2020 15:30:40 +0000</pubDate>
      <link>https://dev.to/kdhttps/seo-tips-and-tricks-with-spa-1bcj</link>
      <guid>https://dev.to/kdhttps/seo-tips-and-tricks-with-spa-1bcj</guid>
      <description>&lt;p&gt;Before starting work on Blog or any content site. You should have to &lt;code&gt;do some research on whether your technology stack supports SEO things or not&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example: I am using Angular &lt;a href="https://scully.io/"&gt;Scully&lt;/a&gt; which is an angular static site generator. The problem which I faced with the &lt;code&gt;only angular is not enough&lt;/code&gt; because as other SPA Technology, it is &lt;code&gt;render HTML after page load&lt;/code&gt; so Whenever crawler scrap your website. It &lt;code&gt;failed to find out the meta tags&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The solution is you have to use &lt;code&gt;Server Side Rendering&lt;/code&gt; or &lt;code&gt;Static Site Generator&lt;/code&gt; or &lt;a href="https://github.com/GoogleChrome/rendertron"&gt;rendertron&lt;/a&gt;. There are many options available for every SPA(Angular, Vue, and React).&lt;/p&gt;

&lt;p&gt;If you have already developed SPA application and you &lt;code&gt;don't want to add server-side rendering&lt;/code&gt; then you can use &lt;a href="https://github.com/GoogleChrome/rendertron"&gt;rendertron&lt;/a&gt; which is pretty much good design for this purpose.&lt;/p&gt;



&lt;h2&gt;
  
  
  SEO(Search Engine Optimazation) Tips and Tricks 🤩
&lt;/h2&gt;



&lt;h3&gt;
  
  
  1. Register your domain to google search console
&lt;/h3&gt;

&lt;p&gt;Search Console tools and reports help you measure your site's Search traffic and performance, fix issues, and make your site shine in Google Search results.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open Link &lt;a href="https://search.google.com/search-console/welcome"&gt;https://search.google.com/search-console/welcome&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Add your domain in &lt;code&gt;URL prefix&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Verify your ownership&lt;/li&gt;
&lt;li&gt;Choose the &lt;code&gt;HTML Tag&lt;/code&gt; verify technique which I think easy.&lt;/li&gt;
&lt;li&gt;Done&lt;/li&gt;
&lt;/ul&gt;



&lt;h3&gt;
  
  
  2. SEO Tips to Choose the Best title for your Blog
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://chrome.google.com/webstore/detail/ubersuggest/nmpgaoofmjlimabncmnmnopjabbflegf?hl=en"&gt;Ubersuggest&lt;/a&gt; tool which use to check &lt;code&gt;trend&lt;/code&gt; and &lt;code&gt;volume search about the topic&lt;/code&gt;.  You can easily &lt;code&gt;install the extension&lt;/code&gt; and just &lt;code&gt;search on google&lt;/code&gt;. It will show you &lt;code&gt;details on the right side of the page&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Update your &lt;code&gt;&amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;&lt;/code&gt; tag with your &lt;code&gt;title&lt;/code&gt; which is really important. The title &lt;code&gt;should not be the same&lt;/code&gt; across whole the website.&lt;/p&gt;

&lt;p&gt;This is the best SEO Tips and Tricks which helps you to find out the correct title for your content or blog.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;Just type in google search `SEO Tips`. it will show you the number of times search these words in google search engine.

Also Update Title. 
&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;SEO Tips and Tricks with SPA | kdhttps.com&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h3&gt;
  
  
  3. Blog link should contain the title
&lt;/h3&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://kdhttps.com/blog/seo%20tips%20and%20tricks%20with%20spa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the link has a blog title that just &lt;code&gt;helps Google to improve SEO&lt;/code&gt;.&lt;/p&gt;



&lt;h3&gt;
  
  
  4. Blog heading should contain your title for Good SEO
&lt;/h3&gt;

&lt;p&gt;Blog heading means the &lt;code&gt;heading tags(h1, h2, ...., h6)&lt;/code&gt;. It should contain your title with some description. Like just take on of my blog example.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Metatags
&lt;/h3&gt;

&lt;p&gt;This is the most important part. The metatags which should be on your page. These are the tags that are generally scrapping by the crawler(google, twitter crawler).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;og:image&lt;/code&gt; and &lt;code&gt;twitter:image&lt;/code&gt; should have a &lt;code&gt;full path of the image&lt;/code&gt;, otherwise the crawler will fail to show the image on your social site.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"website"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"The Idea behind Technology Stack for Blog site with Netlify and Heroku free deployment and free domain linking"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://raw.githubusercontent.com/kdhttps/generator/master/assets/blog-1-tech-stack.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"The Idea summary behind Netlify and Heroku Free Deployment and Domain linking"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://kdhttps.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"The Idea behind Technology Stack for Blog site with Netlify and Heroku free deployment and free domain linking"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:card"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"summary_large_image"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://raw.githubusercontent.com/kdhttps/generator/master/assets/blog-1-tech-stack.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"The Idea summary behind Netlify and Heroku Free Deployment and Domain linking"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://kdhttps.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"The Idea behind Technology Stack for Blog site with Netlify and Heroku free deployment and free domain linking"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:site"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"@kdhttps"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:creator"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"@kdhttps"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h3&gt;
  
  
  6. Image
&lt;/h3&gt;

&lt;p&gt;You should have to &lt;code&gt;add at least one image&lt;/code&gt; in your blog and don't forgot to add &lt;code&gt;alt&lt;/code&gt; attribute with values. Sometimes we search only for images and users may click on images and google will redirect users to your website.&lt;/p&gt;

&lt;p&gt;For Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"blog-1-tech-stack.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"SEO Tips and Tricks with SPA"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h3&gt;
  
  
  7. Repeat your title in your content
&lt;/h3&gt;

&lt;p&gt;At least repeat 2-3 times your title in your blogs. It is best google directly highlight this content. But make sure it is looks and sound goods otherwise users may not like it.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Point 2. SEO Tips to Choose the Best title for your Blog.

You can see, I've repeated `SEO`, `Tips`, and `Tricks` words in a whole blog.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is my first blog on Dev.to so suggestions are welcome about anything change in the blog. I hope it will help someone. &lt;/p&gt;

&lt;p&gt;Originally published on my own site &lt;a href="https://kdhttps.com/blog/seo%20tips%20and%20tricks%20with%20spa"&gt;https://kdhttps.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y6U6MP_z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media1.giphy.com/media/9Gp5ZwY8FRvna/200_d.gif%3Fcid%3De826c9fc824561ff5cacd5179c5b6d82ecc312296b532108%26rid%3D200_d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y6U6MP_z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media1.giphy.com/media/9Gp5ZwY8FRvna/200_d.gif%3Fcid%3De826c9fc824561ff5cacd5179c5b6d82ecc312296b532108%26rid%3D200_d.gif" alt="thank you"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>seo</category>
      <category>spa</category>
      <category>tips</category>
    </item>
  </channel>
</rss>
