{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/118","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"Back in the day, when consumers wanted to access different sites and applications, they had to register first, and then log in with their…","fields":{"slug":"/identity/loginradius-federated-identity-management/"},"html":"<p>Back in the day, when consumers wanted to access different sites and applications, they had to register first, and then log in with their usernames and passwords every single time. Such experiences are no longer acceptable to consumers and they choose to opt-out of such services.</p>\n<p>The recently launched Federated Identity Management by LoginRadius is an arrangement to simplify the implementation of <a href=\"https://www.loginradius.com/single-sign-on/\">Single Sign-On (SSO)</a> and user experience across applications. </p>\n<h2 id=\"intent-behind-the-launch\" style=\"position:relative;\"><a href=\"#intent-behind-the-launch\" aria-label=\"intent behind the launch permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Intent Behind the Launch</h2>\n<p>Federated Identity Management by LoginRadius helps businesses and applications use a single set of identity data. Consumers need not create multiple accounts for multiple organizations to access their web applications. These applications do not  communicate with each other directly and standard SSO protocols like JWT, SAML, OAuth 2.0, OIDC etc are used to establish the communication.</p>\n<p><a href=\"https://www.loginradius.com/resource/federated-identity-management-datasheet\"><img src=\"/e435d1f4ffd04d5f76d28350b073d466/DS-Product-Federated-Identity-Management-1.webp\" alt=\"Federated Identity Management\"></a></p>\n<p><a href=\"https://www.loginradius.com/federated-sso/\">Federated Identity Management</a> is designed by LoginRadius to help your business in the following ways: </p>\n<ul>\n<li><strong>Gain access across multiple applications</strong>: It helps applications work together, so consumers can access multiple applications without requiring a new access credential.</li>\n<li><strong>Seamless consumer authentication</strong>: It provides seamless access to applications, making the consumer experience quicker, simpler, and more convenient. </li>\n<li><strong>Cost-effectiveness</strong>: It lowers the administrative cost as the support for maintenance of web pages like login, register, access management, consumer management is not required to be managed by your organization.</li>\n<li><strong>Highly secure model</strong>: Because there is no direct communication with multiple service providers, passwords aren't exposed, leading to higher levels of security.</li>\n</ul>\n<p><strong>Key Capabilities of Federated Identity Management by LoginRadius</strong></p>\n<p><img src=\"/59d6c30ab6d5a149de92ff9942c727df/image-2.webp\" alt=\"Federated Identity Management Features\"></p>\n<p>1. <strong>Support for industry-standard SSO protocols</strong>: LoginRadius supports the following standard SSO protocols: </p>\n<ul>\n<li><strong>SAML</strong>: The LoginRadius Admin Console offers a comprehensive self-service of SAML configurations. </li>\n<li><strong>JWT</strong>: LoginRadius offers JWT formatted, encrypted token by email, phone, and username.</li>\n<li><strong>OAuth 2.0</strong>: All authentication-related APIs of LoginRadius accept OAuth 2.0 token.</li>\n<li><strong>OpenID Connect (OIDC)</strong>: LoginRadius follows all standards specified in the OpenID Connect specs.</li>\n<li><strong>Web Services Federation</strong>: LoginRadius extends support for WS Federation by creating a token-based security model. </li>\n</ul>\n<p>2. <strong>LoginRadius Admin Console</strong>: LoginRadius offers a simple dashboard to manage all configurations required for the above mentioned SSO protocols.</p>\n<p>3. <strong>API support for protocols</strong>: LoginRadius covers end-to-end API support for the SSO protocols mentioned above which make integration and implementation relatively easy to be executed within any system.</p>\n<p>4. <strong>LoginRadius acts as Identity Provider</strong>: LoginRadius acts as an IdP which stores and authenticates the identities that consumers use to log in to systems, applications, files servers, and more depending upon the configuration.</p>\n<h2 id=\"a-final-word\" style=\"position:relative;\"><a href=\"#a-final-word\" aria-label=\"a final word permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>A Final Word</h2>\n<p>Federated Identity Management by LoginRadius is a way to connect multiple web applications and services using the same identity data. It’s a many to one mapping to help your consumers access your business and partners with a single credential set.   </p>\n<p><a href=\"https://www.loginradius.com/contact-us?utm_source=blog&#x26;utm_medium=web&#x26;utm_campaign=loginradius-federated-identity-management\"><img src=\"/8fce571f703a5970dbb1359a2fe0e51a/book-a-demo-loginradius.webp\" alt=\"LoginRadius Book a Demo\"></a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"October 15, 2020","updated_date":null,"description":"Our Federated Identity Management feature is designed to simplify the implementation of Federated SSO, so consumers now do not need to create multiple accounts for multiple organisations to access their web applications.","title":"Announcement - LoginRadius Simplifies the Implementation of Federated SSO With Federated Identity Management","tags":["industry-news"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.408450704225352,"src":"/static/534a4b5eecf3cee2ae1e2a3bb871feeb/7f8e9/fim-image.webp","srcSet":"/static/534a4b5eecf3cee2ae1e2a3bb871feeb/61e93/fim-image.webp 200w,\n/static/534a4b5eecf3cee2ae1e2a3bb871feeb/1f5c5/fim-image.webp 400w,\n/static/534a4b5eecf3cee2ae1e2a3bb871feeb/7f8e9/fim-image.webp 768w","sizes":"(max-width: 768px) 100vw, 768px"}}},"author":{"id":"Kundan Singh","github":null,"avatar":null}}}},{"node":{"excerpt":"Build a Twitter Bot with NodeJs Hey there! In this blog post, we will build a twitter bot that let us tweet using the command line directly…","fields":{"slug":"/engineering/build-a-twitter-bot-using-nodejs/"},"html":"<h2 id=\"build-a-twitter-bot-with-nodejs\" style=\"position:relative;\"><a href=\"#build-a-twitter-bot-with-nodejs\" aria-label=\"build a twitter bot with nodejs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Build a Twitter Bot with NodeJs</h2>\n<p>Hey there! In this blog post, we will build a twitter bot that let us tweet using the command line directly. </p>\n<blockquote>\n<p><a href=\"https://nodejs.org/en/download/\">Node</a> and <a href=\"https://www.npmjs.com/\">npm</a> (or, yarn) must be installed on your system. </p>\n</blockquote>\n<h2 id=\"lets-start-\" style=\"position:relative;\"><a href=\"#lets-start-\" aria-label=\"lets start  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Let's Start 🎉</h2>\n<p>We will use <strong><a href=\"https://github.com/desmondmorris/node-twitter\">twitter</a></strong> - a client library for the Twitter REST and Streaming APIs. This npm package will make the whole process of building the bot a whole lot easier and faster. </p>\n<h3 id=\"1-apply-for-a-twitter-developer-account\" style=\"position:relative;\"><a href=\"#1-apply-for-a-twitter-developer-account\" aria-label=\"1 apply for a twitter developer account permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. Apply for a Twitter Developer Account</h3>\n<p>To be able to access Twitter API, you need a Twitter Developer Account. Apply for it <a href=\"https://developer.twitter.com/en/apply-for-access\">here</a>. Click on <em>Apply for a Developer Account</em>.</p>\n<p><img src=\"/5d738c8f8819770413d37f829cde3598/twitter.webp\" alt=\"Twitter Developer Account\"></p>\n<p>It will ask you to log in. Select appropriate settings after logging in. It will also generate <strong>keys</strong> and <strong>secret tokens</strong> like Consumer Key, Consumer Secret, Access Token Key, Access Token Secret. Copy and save them somewhere for future use. </p>\n<h3 id=\"2-setup-project\" style=\"position:relative;\"><a href=\"#2-setup-project\" aria-label=\"2 setup project permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. Setup Project</h3>\n<p>Make a project folder with any name of your choice. Run <code>npm init</code> to initialize the project. This will generate a <code>package.json</code> file in your directory. Alternatively, you can run <code>npm init -y</code> to setup your project with default settings.</p>\n<blockquote>\n<p><code>package.json</code> holds all the dependencies of a project.</p>\n</blockquote>\n<p>Since our project will be dependent on <strong>twitter</strong> client library, it's time we install this dependency in our project. Run <code>npm install twitter</code> to include this in your <code>package.json</code> .</p>\n<h3 id=\"3-setup-files\" style=\"position:relative;\"><a href=\"#3-setup-files\" aria-label=\"3 setup files permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3. Setup Files</h3>\n<p>Now we will start with the actual coding part. At the moment, your project folder will have a <code>node_modules</code> folder, a <code>package.json</code> file, and a <code>package-lock.json</code> file. If you have gone with the default options while running <code>npm init</code>, then <code>index.js</code> is the file we will be working upon.</p>\n<p>Open <code>index.js</code>. To be able to use the <strong>twitter</strong> library, which we have installed, you need to include it in <code>index.js</code>. </p>\n<p><code>var Twitter = require('twitter');</code></p>\n<p>Also, remember the <strong>keys</strong> and <strong>tokens</strong> you got from Twitter Developer Portal? It's time we use them. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">client</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Twitter</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">consumer_key:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">CONSUMER_KEY</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">consumer_secret:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">CONSUMER_SECRET</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">access_token_key:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">ACCESS_TOKEN_KEY</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">access_token_secret:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">ACCESS_TOKEN_SECRET</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<p><strong>Do not add your Consumer or Access Token keys or secrets directly in the <code>index.js</code>.</strong> These should be managed accordingly using <em>environment variables</em>.</p>\n<blockquote>\n<p>We will use <code>dotenv</code> library to manage our environment variables in NodeJS.  Run <code>npm install dotenv</code> and follow <a href=\"https://www.npmjs.com/package/dotenv#usage\">these</a> instructions. Your <code>.env</code> will look something like this.</p>\n</blockquote>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">CONSUMER_KEY</span><span class=\"mtk1\">=........................................</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">CONSUMER_SECRET</span><span class=\"mtk1\">=.....................................</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">ACCESS_TOKEN_KEY</span><span class=\"mtk1\">=....................................</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">ACCESS_TOKEN_SECRET</span><span class=\"mtk1\">=.................................</span></span></code></pre>\n<h3 id=\"4-start-coding-\" style=\"position:relative;\"><a href=\"#4-start-coding-\" aria-label=\"4 start coding  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4. Start Coding 🎯</h3>\n<p>I will use <a href=\"https://github.com/15Dkatz/official_joke_api\">Official Joke API</a> to automatically fetch content for my tweet. You can visit the repository and learn more about the endpoints. But the only <a href=\"https://github.com/15Dkatz/official_joke_api#grab-a-random-joke\">endpoint</a> we will work with is <a href=\"https://official-joke-api.appspot.com/random_joke\">random_joke</a>. Click on this, and you will receive a JSON response with fields id, type, setup, and punchline. The fields we are concerned with are setup and punchline. </p>\n<p>We will use <a href=\"https://github.com/axios/axios\">axios</a> for calling the API endpoint. Run <code>npm install axios</code> and add <code>var axios = require('axios');</code> in <code>index.js</code>.</p>\n<p>Now everything has been laid out. We need to connect the dots. The Official Joke API will return a JSON response. We will grab the required data, i.e., the setup and the punchline from it. And then make use of <a href=\"https://github.com/desmondmorris/node-twitter/tree/master/examples#tweet\">client.post</a> functionality of <strong>twitter</strong> package.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">axios</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;https://official-joke-api.appspot.com/random_joke&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">Response</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">Response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">setup</span><span class=\"mtk1\">, </span><span class=\"mtk12\">Response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">punchline</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}).</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(([</span><span class=\"mtk12\">setup</span><span class=\"mtk1\">, </span><span class=\"mtk12\">punch</span><span class=\"mtk1\">]) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">client</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;statuses/update&#39;</span><span class=\"mtk1\">, {</span><span class=\"mtk12\">status:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`</span><span class=\"mtk4\">${</span><span class=\"mtk12\">setup</span><span class=\"mtk4\">}</span><span class=\"mtk6\">\\n</span><span class=\"mtk4\">${</span><span class=\"mtk12\">punch</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">}, </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">error</span><span class=\"mtk1\">, </span><span class=\"mtk12\">tweet</span><span class=\"mtk1\">, </span><span class=\"mtk12\">response</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\">(!</span><span class=\"mtk12\">error</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t\t</span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">tweet</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<p>Now run <code>node index.js</code> on the terminal and see the output.\nIf everything went well, you would see a <em>tweet</em> response, otherwise an <em>error</em> message. The successful message would look something like <a href=\"https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-statuses-update#example-response\">this</a>.</p>\n<p>At this point, your index.js should look like this.</p>\n<p><img src=\"/4081a47a94b07d7916221d3f11de5121/code.webp\" alt=\"index.js\"></p>\n<h3 id=\"congratulations-\" style=\"position:relative;\"><a href=\"#congratulations-\" aria-label=\"congratulations  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Congratulations! 🎊</h3>\n<p>That's it! You have created your first Twitter Bot, which tweets content after directly calling it from an API. You might take a look at the <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/NodeJs/TwitterBot\">repository</a> if you encountered any errors. Here, I have used different APIs to fetch content and tweet. Moreover, I have added a script that will search posts with a particular hashtag and like them. </p>\n<blockquote>\n<p><strong>While pushing your code to GitHub, make sure to add <code>.gitignore</code> file and include <code>node_modules</code> and <code>.env</code> in it.</strong></p>\n</blockquote>\n<h2 id=\"further-reading\" style=\"position:relative;\"><a href=\"#further-reading\" aria-label=\"further reading permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Further Reading</h2>\n<blockquote>\n<p>The world is yours to explore.</p>\n</blockquote>\n<p>And the dev world is based entirely on exploring technologies and frameworks. Play with this <strong>twitter</strong> library and see what interesting stuff can be built with it. Maybe, search tweets with a particular hashtag and like them? Or maybe, retweet tweets of any particular user? You are free to use your imagination and coding skills to explore more and more. If <code>axios</code> and <code>dotenv</code> are new to you, then go ahead and read their documentation. Get hold of the concepts of environment variables. And come up with your own cool Twitter Bot.</p>\n<blockquote>\n<p>Keep in mind Twitter's <a href=\"https://developer.twitter.com/en/developer-terms\">Developer Policy &#x26; Terms</a> and <a href=\"https://twitter.com/en/tos\">Twitter Terms &#x26; Conditions</a>. These should not be violated in whatever project you are building.</p>\n</blockquote>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n</style>","frontmatter":{"date":"October 14, 2020","updated_date":null,"description":"Learn how to create a twitter bot using NodeJS that let us tweet using the command line directly","title":"Build A Twitter Bot Using NodeJS","tags":["NodeJs","Twitter","Bot"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/820019d481163bc17d6c095404abb359/58556/cover.webp","srcSet":"/static/820019d481163bc17d6c095404abb359/61e93/cover.webp 200w,\n/static/820019d481163bc17d6c095404abb359/1f5c5/cover.webp 400w,\n/static/820019d481163bc17d6c095404abb359/58556/cover.webp 800w,\n/static/820019d481163bc17d6c095404abb359/99238/cover.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Vineeta Jain","github":"Ninjavin","avatar":null}}}},{"node":{"excerpt":"Motivation Maps are an effective, intuitive way to understand data in some use-cases. Interactive web maps can help us visualize the data…","fields":{"slug":"/engineering/visualizing-data-using-leaflet-and-netlify/"},"html":"<h2 id=\"motivation\" style=\"position:relative;\"><a href=\"#motivation\" aria-label=\"motivation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Motivation</h2>\n<p>Maps are an effective, intuitive way to understand data in some use-cases. Interactive web maps can help us visualize the data better and derive better insights.</p>\n<p>Different map visualizations can highlight different aspects of a dataset. Heatmaps, Choropleth maps and Clustering maps are frequently used for this purpose.</p>\n<p>In this blog, I shall go over using a powerful JavaScript library to build a web map and deploy it on Netlify.</p>\n<h2 id=\"using-leaflet\" style=\"position:relative;\"><a href=\"#using-leaflet\" aria-label=\"using leaflet permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using Leaflet</h2>\n<p>The Leaflet is a great library for implementing interactive web maps as it provides many UI features, like smooth canvas panning, zooming, mouse events, and all the involved work in animations, which one would otherwise have to implement from scratch.</p>\n<blockquote>\n<p>Leaflet is the leading open-source JavaScript library for mobile-friendly interactive maps. Weighing just about 39 KB of JS, it has all the mapping features most developers ever need.</p>\n<p><em>source: leafletjs.com</em></p>\n</blockquote>\n<p><img src=\"/7efc920eb3f4c7321711cf133a19b18c/leaflet.webp\" alt=\"Leaflet Logo\"></p>\n<p>We can include Leaflet in our application by including the CSS stylesheet and the JS file from the unpkg CDN. Let's start building the application by starting with the following code at the project root. Create a file named <code>index.html</code> and put the following markup in it. The map shall be rendered in <code>div#mapid</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span><span class=\"mtk12\">index</span><span class=\"mtk1\">.</span><span class=\"mtk12\">html</span><span class=\"mtk1\">--&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!</span><span class=\"mtk12\">DOCTYPE</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk1\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lang</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">charset</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;UTF-8&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;viewport&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;width=device-width, initial-scale=1.0&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">MapViz</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://unpkg.com/leaflet/dist/leaflet.css&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      #mapid </span><span class=\"mtk4\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk12\">fixed</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">width</span><span class=\"mtk1\">: </span><span class=\"mtk7\">100</span><span class=\"mtk1\">%;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">100</span><span class=\"mtk1\">%;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">top</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">left</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">id</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;mapid&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">defer</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://unpkg.com/leaflet/dist/leaflet.js&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>Now, we gather a link to the GeoJSON file for metro stations in Washington D.C., that we shall be visualizing, from the <a href=\"https://docs.mapbox.com/help/glossary/geojson/\">MapBox documentation</a>. It should look similar to the following:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">https://docs.mapbox.com/help/data/stations.geojson</span></code></pre>\n<p>Create a new JavaScript file named <code>script.js</code> in the same directory as the HTML file. Include this file in the web page by adding the following line to it.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span><span class=\"mtk12\">index</span><span class=\"mtk1\">.</span><span class=\"mtk12\">html</span><span class=\"mtk1\">--&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">defer</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://unpkg.com/leaflet/dist/leaflet.js&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;script.js&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span></code></pre>\n<p>In <code>script.js</code>, we can use the Fetch API to make an AJAX request and get the data as a response to a <code>GET</code> request using promises and take a look at what we are dealing with.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// script.js</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">data</span><span class=\"mtk1\"> = {};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">dataUrl</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;https://cors-anywhere.herokuapp.com/https://docs.mapbox.com/help/data/stations.geojson&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">dataUrl</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">response</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">error</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\">));</span></span></code></pre>\n<p>We can take a look at the data in the Developer Console. We observe that it is a JavaScript object. The various properties associated with the data can be viewed by checking the individual features.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;type&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;FeatureCollection&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;features&quot;</span><span class=\"mtk1\">: [</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk8\">&quot;geometry&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;type&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Point&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;coordinates&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> [-</span><span class=\"mtk7\">76.9750541388</span><span class=\"mtk1\">, </span><span class=\"mtk7\">38.8410857803</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk8\">&quot;type&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Feature&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk8\">&quot;properties&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;description&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Southern Ave&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;marker-symbol&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;rail-metro&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;title&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Southern Ave&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;url&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;http://www.wmata.com/rider_tools/pids/showpid.cfm?station_id=107&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;lines&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> [</span><span class=\"mtk8\">&quot;Green&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;address&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;1411 Southern Avenue, Temple Hills, MD 20748&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Before we begin adding the layers to our map, we need to instantiate a Leaflet <code>map</code> object with the DOM ID of the map container and center it on our point of interest at a specified initial zoom level.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">map</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">map</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;mapid&#39;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">setView</span><span class=\"mtk1\">([</span><span class=\"mtk7\">38.8977</span><span class=\"mtk1\">, -</span><span class=\"mtk7\">77.0365</span><span class=\"mtk1\">], </span><span class=\"mtk7\">15</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>As we need a base map (the base layer) for our map, we can use one that is provided by Mapbox. In order to use that, you need a Mapbox API access token that you can create on <a href=\"https://account.mapbox.com/\">their portal</a>.</p>\n<p>The following snippet instantiates a <code>tileLayer</code> object and adds it to our map:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">tileLayer</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}&#39;</span><span class=\"mtk1\">, {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">attribution:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;Map data &copy; &lt;a href=&quot;https://www.openstreetmap.org/&quot;&gt;OpenStreetMap&lt;/a&gt; contributors, &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/2.0/&quot;&gt;CC-BY-SA&lt;/a&gt;, Imagery © &lt;a href=&quot;https://www.mapbox.com/&quot;&gt;Mapbox&lt;/a&gt;&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">maxZoom:</span><span class=\"mtk1\"> </span><span class=\"mtk7\">18</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">id:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;mapbox/streets-v11&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">tileSize:</span><span class=\"mtk1\"> </span><span class=\"mtk7\">512</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">zoomOffset:</span><span class=\"mtk1\"> -</span><span class=\"mtk7\">1</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">accessToken:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;your_mapbox_api_access_token&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>We can use the following snippet to parse the GeoJSON and add it to the map.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">geoJSON</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Replace the code in <code>script.js</code> with the following, and refresh the web page:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">data</span><span class=\"mtk1\"> = {};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">dataUrl</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;https://cors-anywhere.herokuapp.com/https://docs.mapbox.com/help/data/stations.geojson&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">map</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">map</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;mapid&#39;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">setView</span><span class=\"mtk1\">([</span><span class=\"mtk7\">38.8977</span><span class=\"mtk1\">, -</span><span class=\"mtk7\">77.0365</span><span class=\"mtk1\">], </span><span class=\"mtk7\">15</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">tileLayer</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}&#39;</span><span class=\"mtk1\">, {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">attribution:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;Map data &copy; &lt;a href=&quot;https://www.openstreetmap.org/&quot;&gt;OpenStreetMap&lt;/a&gt; contributors, &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/2.0/&quot;&gt;CC-BY-SA&lt;/a&gt;, Imagery © &lt;a href=&quot;https://www.mapbox.com/&quot;&gt;Mapbox&lt;/a&gt;&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">maxZoom:</span><span class=\"mtk1\"> </span><span class=\"mtk7\">18</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">id:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;mapbox/streets-v11&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">tileSize:</span><span class=\"mtk1\"> </span><span class=\"mtk7\">512</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">zoomOffset:</span><span class=\"mtk1\"> -</span><span class=\"mtk7\">1</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">accessToken:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;your_mapbox_api_access_token&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">dataUrl</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">response</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">geoJSON</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">error</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\">));</span></span></code></pre>\n<p>As the dataset contains <code>Point</code> features, markers will be added at the respective coordinates. Our web page will now look like the following:</p>\n<p><img src=\"/c9f8918ca84e4084cdde9b01eb30f2ad/mapInitial.webp\" alt=\"Map with Markers\"></p>\n<p>We can show tooltips upon clicking on the markers by modifying the code as follows, to include some custom HTML using the properties in the feature, in the popup:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// script.js</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">dataUrl</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">response</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">geoJSON</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">, {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk11\">onEachFeature</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">feature</span><span class=\"mtk1\">, </span><span class=\"mtk12\">layer</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">layer</span><span class=\"mtk1\">.</span><span class=\"mtk11\">bindPopup</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk8\">&#39;&lt;h4&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk12\">feature</span><span class=\"mtk1\">.</span><span class=\"mtk12\">properties</span><span class=\"mtk1\">.</span><span class=\"mtk12\">title</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;/h4&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;p&gt;&#39;</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          +  </span><span class=\"mtk12\">feature</span><span class=\"mtk1\">.</span><span class=\"mtk12\">properties</span><span class=\"mtk1\">.</span><span class=\"mtk12\">address</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;/p&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">error</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span></code></pre>\n<p>Uupon clicking any marker, we will now see the following popup:</p>\n<p><img src=\"/d9a6e0e68d17fb7cdd0e12d87710ef35/mapPopup.webp\" alt=\"Map with Popups\"></p>\n<p>We can also customize the marker icon using the <code>pointToLayer</code> option of the <code>geoJSON</code> constructor as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// scripts.js</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">geoJSON</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">, {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk11\">pointToLayer</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">feature</span><span class=\"mtk1\">, </span><span class=\"mtk12\">coords</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">marker</span><span class=\"mtk1\">(</span><span class=\"mtk12\">coords</span><span class=\"mtk1\">, {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk12\">icon:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">L</span><span class=\"mtk1\">.</span><span class=\"mtk10\">Icon</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">iconSize:</span><span class=\"mtk1\"> [</span><span class=\"mtk7\">30</span><span class=\"mtk1\">, </span><span class=\"mtk7\">30</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">iconAnchor:</span><span class=\"mtk1\"> [</span><span class=\"mtk7\">15</span><span class=\"mtk1\">, </span><span class=\"mtk7\">15</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">popupAnchor:</span><span class=\"mtk1\"> [</span><span class=\"mtk7\">1</span><span class=\"mtk1\">, -</span><span class=\"mtk7\">24</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">iconUrl:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;https://cdn.iconscout.com/icon/free/png-256/metro-subway-underground-train-railway-engine-emoj-symbol-30744.webp&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk11\">onEachFeature</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">feature</span><span class=\"mtk1\">, </span><span class=\"mtk12\">layer</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">layer</span><span class=\"mtk1\">.</span><span class=\"mtk11\">bindPopup</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk8\">&#39;&lt;h4&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk12\">feature</span><span class=\"mtk1\">.</span><span class=\"mtk12\">properties</span><span class=\"mtk1\">.</span><span class=\"mtk12\">title</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;/h4&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;p&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk12\">feature</span><span class=\"mtk1\">.</span><span class=\"mtk12\">properties</span><span class=\"mtk1\">.</span><span class=\"mtk12\">address</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;/p&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ...</span></span></code></pre>\n<p>Our updated web page will now look like the following:</p>\n<p><img src=\"/d40f991754a9a42ad009adce6c048fe1/mapIcon.webp\" alt=\"Map with Custom Icon\"></p>\n<p>Now, we can move on to deploy this web page on Netlify.</p>\n<h2 id=\"deploying-on-netlify\" style=\"position:relative;\"><a href=\"#deploying-on-netlify\" aria-label=\"deploying on netlify permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Deploying on Netlify</h2>\n<p>Netlify is an awesome platform to host your web applications. It also offers many other features such as serverless functions.</p>\n<p><img src=\"/ff0c5f52e4df420ed6d72e2e1aadcc07/netlify.webp\" alt=\"Netlify Logo\"></p>\n<p>Once you have pushed your web page to a Git repository, hosted either on GitHub, GitLab or BitBucket, navigate to <a href=\"https://app.netlify.com\">Netlify</a> and click on the <strong>New Site from Git</strong> button.</p>\n<p><img src=\"/0a99824fbd69eb99c04d16316448f05b/netlifySigningUp.webp\" alt=\"Starting with Netlify\"></p>\n<p>Next, select your Git provider and your repository:</p>\n<p><img src=\"/cd777ecec352e4ac8c0aa3849788b084/gitRepo.webp\" alt=\"Git Provider Selection\"></p>\n<p><img src=\"/9b6e31356e117401e9c79c2d54e36047/repoSelection.webp\" alt=\"Git Respository Selection\"></p>\n<p>Go ahead with the defaults, and now your site shall be published on Netlify, and all future pushes should result in a Netlify deployment:</p>\n<p><img src=\"/9875f707227b97720d89714f152c4b92/deployment.webp\" alt=\"Netlify Deployment\"></p>\n<p>Nice! Now we have a web map, even though a very basic one, live! Check out the <a href=\"https://leafletjs.com/reference.html\">Leaflet documentation</a> for more!</p>\n<h2 id=\"source-code\" style=\"position:relative;\"><a href=\"#source-code\" aria-label=\"source code permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Source Code</h2>\n<p>Demonstration: <a href=\"https://priceless-poincare-9647e3.netlify.app/\">Priceless Poincare</a></p>\n<p>GitHub: <a href=\"https://github.com/sudiptog81/leaflet-netlify-starter\">leaflet netlify starter</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk17 { color: #808080; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","frontmatter":{"date":"October 14, 2020","updated_date":null,"description":"Let's visualize geospatial data on the web using Leaflet and host it on Netlify!","title":"Visualizing Data using Leaflet and Netlify","tags":["GIS","Serverless","JavaScript"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":2.0618556701030926,"src":"/static/f09ca52cdb62e663db2958fa17ee7f4a/58556/map.webp","srcSet":"/static/f09ca52cdb62e663db2958fa17ee7f4a/61e93/map.webp 200w,\n/static/f09ca52cdb62e663db2958fa17ee7f4a/1f5c5/map.webp 400w,\n/static/f09ca52cdb62e663db2958fa17ee7f4a/58556/map.webp 800w,\n/static/f09ca52cdb62e663db2958fa17ee7f4a/99238/map.webp 1200w,\n/static/f09ca52cdb62e663db2958fa17ee7f4a/42314/map.webp 1366w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Sudipto Ghosh","github":"sudiptog81","avatar":null}}}},{"node":{"excerpt":"Introduction The Secure Enclave is a hardware-based key manager that’s isolated from the main processor to provide an extra layer of…","fields":{"slug":"/engineering/secure-enclave-ios-app/"},"html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>The Secure Enclave is a hardware-based key manager that’s isolated from the main processor to provide an extra layer of security. Using a secure enclave, we can create the key, securely store the key, and perform operations with the key. Thus makes it difficult for the key to be compromised. </p>\n<p>We usually save data persistently in the app using UserDefaults, Keychain, Core Data or SQLite.\nFor example, To save the session of logged in user, we save username and password. But this process puts our data at high-security risk. So it's always recommended to store sensitive data in an encrypted format. But again, it's a challenge to secure keys used in encryption/decryption.</p>\n<p><img src=\"/52c5d8e0a1d8ee7238f2080cc0689c39/image2.webp\" alt=\"Secure Enclave\"></p>\n<p>Now here <strong>Secure Enclave</strong> comes in the role. </p>\n<p>In this blog, we will use Secure Enclave to generate key pair and use those in encryption/decryption of sensitive data further.</p>\n<p>Here I will create a wrapper to generate key pair using Secure Enclave and use them to encrypt/decrypt sensitive data. And also a viewcontroller to show how to use a wrapper to get encrypted and decrypted data.\nYou may implement wrapper's methods as common methods and use wherever needed in the project. But its recommended to use a separate wrapper for handling communication with Secure Enclave.</p>\n<h2 id=\"wrapper\" style=\"position:relative;\"><a href=\"#wrapper\" aria-label=\"wrapper permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Wrapper</h2>\n<p> I have created .h and .m files named as SecEnclaveWrapper as a subclass of NSObject.\nIn .h file I am declaring function for being accessible from other classes like: </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">Return encrypted value of data using kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM algo</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)encryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)data ;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">Return decryrpted data of encrypted data  using kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM algo</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)decryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)data ;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">Return an initialized instance of the wrapper</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">instancetype</span><span class=\"mtk1\">)init;</span></span></code></pre>\n<p>Then in .m file, define the following methods as : </p>\n<p>The method <code>init</code> initializes and returns the object of this wrapper class. And 'encryptData' and 'decryptData' method return encrypted data and decrypted data of encrypted data, respectively.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">instancetype</span><span class=\"mtk1\">)init {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    self = [super init];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(![self lookupPublicKeyRef] || ![self lookupPrivateKeyRef])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        [self generatePasscodeKeyPair];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> self;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)encryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)data {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (data && </span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">length</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        CFDataRef cipher = </span><span class=\"mtk11\">SecKeyCreateEncryptedData</span><span class=\"mtk1\">(publicKeyRef, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)data, </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (__bridge </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)cipher;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    } </span><span class=\"mtk15\">else</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\">*)decryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)data {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(data && </span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">length</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        CFDataRef plainData = </span><span class=\"mtk11\">SecKeyCreateDecryptedData</span><span class=\"mtk1\">(privateKeyRef, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)data, </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\">  (__bridge </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)plainData;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">else</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The 'lookupPublicKeyRef' method below will lookup keychain for public key &#x26; 'lookupPrivateKeyRef' method search for the private key and return key if found.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (SecKeyRef) lookupPublicKeyRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> sanityCheck = noErr;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *tag;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">id</span><span class=\"mtk1\"> keyClass;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (publicKeyRef != </span><span class=\"mtk4\">NULL</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\">// if already resides in memory, return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> publicKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    tag = [kPublicKeyName dataUsingEncoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    keyClass = (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClassPublic;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSDictionary</span><span class=\"mtk1\"> *queryDict = @{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClass : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClassKey,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyType : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyTypeEC,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrApplicationTag : tag,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClass : keyClass,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecReturnRef : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">//else look key in keychain and return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    sanityCheck = </span><span class=\"mtk11\">SecItemCopyMatching</span><span class=\"mtk1\">((__bridge CFDictionaryRef) queryDict, (CFTypeRef *) &publicKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (sanityCheck != errSecSuccess) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Error trying to retrieve key from server.  sanityCheck: %d&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)sanityCheck);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> publicKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (SecKeyRef) lookupPrivateKeyRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFMutableDictionaryRef getPrivateKeyRef = newCFDict;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecClass, kSecClassKey);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecAttrKeyClass, kSecAttrKeyClassPrivate);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecAttrLabel, kPrivateKeyName);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecReturnRef, kCFBooleanTrue);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> status = </span><span class=\"mtk11\">SecItemCopyMatching</span><span class=\"mtk1\">(getPrivateKeyRef, (CFTypeRef *)&privateKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (status == errSecItemNotFound)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (SecKeyRef)privateKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The following methods will actually deal with Secure Enclave to generate a private key and public key.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">bool</span><span class=\"mtk1\">) generatePasscodeKeyPair</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFErrorRef error = </span><span class=\"mtk4\">NULL</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    SecAccessControlRef sacObject = </span><span class=\"mtk11\">SecAccessControlCreateWithFlags</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    kCFAllocatorDefault,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    kSecAccessControlPrivateKeyUsage,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    &error</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (error != errSecSuccess) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Generating key pair, error: %@</span><span class=\"mtk6\">\\n</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">, error);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [self generateKeyPairWithAccessControlObject:sacObject];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">bool</span><span class=\"mtk1\">) generateKeyPairWithAccessControlObject:(SecAccessControlRef)accessControlRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// create dictionary of private key </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFMutableDictionaryRef accessControlDict = newCFDict;;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#if</span><span class=\"mtk4\"> </span><span class=\"mtk1\">!</span><span class=\"mtk11\">TARGET_IPHONE_SIMULATOR</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(accessControlDict, kSecAttrAccessControl, accessControlRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#endif</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(accessControlDict, kSecAttrIsPermanent, kCFBooleanTrue);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(accessControlDict, kSecAttrLabel, kPrivateKeyName);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// create dictionary for saving key into keychain</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFMutableDictionaryRef generatePairRef = newCFDict;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#if</span><span class=\"mtk4\"> </span><span class=\"mtk1\">!</span><span class=\"mtk11\">TARGET_IPHONE_SIMULATOR</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecAttrTokenID, kSecAttrTokenIDSecureEnclave);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#endif</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecAttrKeyType, kSecAttrKeyTypeEC);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecAttrKeySizeInBits, (__bridge </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk4\">void</span><span class=\"mtk1\"> *)([</span><span class=\"mtk10\">NSNumber</span><span class=\"mtk1\"> numberWithInt:</span><span class=\"mtk7\">256</span><span class=\"mtk1\">]));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecPrivateKeyAttrs, accessControlDict);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> status = </span><span class=\"mtk11\">SecKeyGeneratePair</span><span class=\"mtk1\">(generatePairRef, &publicKeyRef, &privateKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (status != errSecSuccess){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Error trying to retrieve key from server.  sanityCheck: %d&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)status);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">NO</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    [self savePublicKeyFromRef:publicKeyRef];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">YES</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The private key is generated and stored in Secure Enclave which cannot be directly used. Whereas public key have to be stored manually in keychain by following method.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">bool</span><span class=\"mtk1\">) savePublicKeyFromRef:(SecKeyRef)publicKeyRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{   </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> sanityCheck = noErr;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *tag;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">id</span><span class=\"mtk1\"> keyClass;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    tag = [kPublicKeyName dataUsingEncoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    keyClass = (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClassPublic;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSDictionary</span><span class=\"mtk1\"> *saveDict = @{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClass : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClassKey,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyType : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyTypeEC,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrApplicationTag : tag,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClass : keyClass,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecValueData : (__bridge </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)</span><span class=\"mtk11\">SecKeyCopyExternalRepresentation</span><span class=\"mtk1\">(publicKeyRef,</span><span class=\"mtk4\">nil</span><span class=\"mtk1\">),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeySizeInBits : [</span><span class=\"mtk10\">NSNumber</span><span class=\"mtk1\"> numberWithUnsignedInteger:</span><span class=\"mtk7\">256</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrEffectiveKeySize : [</span><span class=\"mtk10\">NSNumber</span><span class=\"mtk1\"> numberWithUnsignedInteger:</span><span class=\"mtk7\">256</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanDerive : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanEncrypt : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanDecrypt : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanVerify : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanSign : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanWrap : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanUnwrap : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    sanityCheck = </span><span class=\"mtk11\">SecItemAdd</span><span class=\"mtk1\">((__bridge CFDictionaryRef) saveDict, (CFTypeRef *)&publicKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (sanityCheck != errSecSuccess) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Error trying to retrieve key from server.  sanityCheck: %d&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)sanityCheck);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> publicKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<h2 id=\"demo\" style=\"position:relative;\"><a href=\"#demo\" aria-label=\"demo permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Demo</h2>\n<p>Now I am creating ViewController.h and .m files. In viewDidLoad in .m file, having a string to be stored in UserDefaults. I will encrypt this string by a private key generated above and then store persistently encrypted data for later use.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">void</span><span class=\"mtk1\">)viewDidLoad {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    [super viewDidLoad];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strDatatosave = </span><span class=\"mtk8\">@&quot;example data to save&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *bundleIdentifier = [[</span><span class=\"mtk10\">NSBundle</span><span class=\"mtk1\"> mainBundle] bundleIdentifier];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strGroupID = [</span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> stringWithFormat:</span><span class=\"mtk8\">@&quot;group.%@&quot;</span><span class=\"mtk1\">,bundleIdentifier];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    SecEnclaveWrapper *keychainItem = [[SecEnclaveWrapper alloc] init];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *encrypted = [keychainItem encryptData:[strDatatosave dataUsingEncoding:NSUTF8StringEncoding]];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strEncrypted = [[</span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> alloc] initWithData:encrypted encoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;encrypted string %@&quot;</span><span class=\"mtk1\">,strEncrypted);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *decrypted =[keychainItem decryptData:encrypted];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strDecrypted = [[</span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> alloc] initWithData:decrypted encoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;decrypted string as real string%@&quot;</span><span class=\"mtk1\">,strDecrypted);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>In this blog, we learned about the basics of key generation via Secure Enclave and encryption and decryption using keys.\nBy default, key-pairs are generated in the Secure Enclave. The private key is available only at creation time and can not be obtained later as it is saved in Secure Enclave. Operations can be performed with it without exposing it to user code. Only Public Key will be stored and retrieved.</p>\n<p>You can find the complete repository link <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/iOS/SecureEnclave/SecureEnclaveDemo\">here</a></p>\n<p>Thanks for reading the blog. For detailed information and execution example of this blog, please refer to the video below:</p>\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/c_1E_NV4NBk\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"October 13, 2020","updated_date":null,"description":"SecureEnclaveDemo is an xcode project containing helper named as SecEnclaveWrapper. You can use this wrapper in your project to encrypt/decrypt sensitive data using Secure Enclave. Let's understand more about in the blog.","title":"Secure Enclave in iOS App","tags":["ios","security","data","encryption","private key","xcode"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/e677a934323b29af4619ee797f0286b8/58556/CoverImage.webp","srcSet":"/static/e677a934323b29af4619ee797f0286b8/61e93/CoverImage.webp 200w,\n/static/e677a934323b29af4619ee797f0286b8/1f5c5/CoverImage.webp 400w,\n/static/e677a934323b29af4619ee797f0286b8/58556/CoverImage.webp 800w,\n/static/e677a934323b29af4619ee797f0286b8/210c1/CoverImage.webp 900w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Tanvi Jain","github":"tanvijn","avatar":null}}}},{"node":{"excerpt":"What is STL? STL stands for Standard Template Library. If you've used C++ even in small projects, you've likely already used STL - which is…","fields":{"slug":"/engineering/cpp-stl-containers/"},"html":"<h2 id=\"what-is-stl\" style=\"position:relative;\"><a href=\"#what-is-stl\" aria-label=\"what is stl permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is STL?</h2>\n<p>STL stands for Standard Template Library. If you've used C++ even in small projects, you've likely already used STL - which is a great thing! Using STL in C++ makes your code more expressive, simple, and easy to understand. This post will give you an overview of how STL works, some examples, and the basic knowledge you need to get started!</p>\n<h2 id=\"stl-components\" style=\"position:relative;\"><a href=\"#stl-components\" aria-label=\"stl components permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>STL Components</h2>\n<p>Loosely speaking, the first components you'd typically understand and use of STL are Containers &#x26; Algorithms. Then there's also Iterators &#x26; Functors, but you should try to take them on one by one, in that order perhaps. This blog will expand a bit on STL Containers.</p>\n<h3 id=\"containers\" style=\"position:relative;\"><a href=\"#containers\" aria-label=\"containers permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Containers</h3>\n<p>Suppose you are at your favorite cinema hall and it's the launch of a big movie. Since it's the launch, there are likely many people waiting in line to buy their tickets. Naturally, you join the queue at the back and wait for your turn. In the computing world, we have a queue too! This is a popular data structure. If you've had a Data Structures class before, you are most likely familiar with some other data structures as well. These are often used, so the STL provides a great implementation of all these data structures, otherwise known as containers.</p>\n<p>Take arrays, for example. Arrays are elements with the same type, stored in contiguous blocks of memory. In C++, you can use arrays as you would in C, like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"cpp\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">std</span><span class=\"mtk1\">::string </span><span class=\"mtk12\">students</span><span class=\"mtk1\">[</span><span class=\"mtk7\">10</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">students</span><span class=\"mtk1\">[</span><span class=\"mtk7\">0</span><span class=\"mtk1\">] = </span><span class=\"mtk8\">&quot;Adam&quot;</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>But wait, STL provides a container for arrays too. It's available in the header <code>&#x3C;array></code>. Example usage of it would look like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"cpp\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">#include</span><span class=\"mtk4\"> </span><span class=\"mtk8\">&lt;iostream&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#include</span><span class=\"mtk4\"> </span><span class=\"mtk8\">&lt;string&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">int</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">std</span><span class=\"mtk1\">::array&lt;</span><span class=\"mtk10\">std</span><span class=\"mtk1\">::string, </span><span class=\"mtk7\">10</span><span class=\"mtk1\">&gt; students;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">students</span><span class=\"mtk1\">[</span><span class=\"mtk7\">0</span><span class=\"mtk1\">] = </span><span class=\"mtk8\">&quot;Adam&#39;s Friend&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    cout &lt;&lt; </span><span class=\"mtk12\">students</span><span class=\"mtk1\">[</span><span class=\"mtk7\">0</span><span class=\"mtk1\">] &lt;&lt; endl;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>So, what's the difference? Why should you use the STL Container class? The performance difference is negligible, but what makes the container classes better is that it is a class. A wrapper class around normal arrays, and offers some advantages like passing by values, bounds checking, etc. As a side note, you'd normally want to use an <code>std::vector</code> instead - which is a dynamically resizable array.</p>\n<h4 id=\"other-examples\" style=\"position:relative;\"><a href=\"#other-examples\" aria-label=\"other examples permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Other examples</h4>\n<p>Other containers in C++ include:</p>\n<ul>\n<li>\n<p>Sequence containers: (accessibility in a sequential manner)</p>\n<ul>\n<li><code>std::array</code></li>\n<li>\n<p><code>std::vector</code>: Dynamically resizable arrays.\nArrays have a set size, while <code>std::vector</code> doesn't. You can keep adding elements in contigious blocks of memory. For example:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"cpp\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">std</span><span class=\"mtk1\">::vector&lt;</span><span class=\"mtk10\">std</span><span class=\"mtk1\">::string&gt; students;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">students</span><span class=\"mtk1\">.</span><span class=\"mtk11\">push_back</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Paul&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">students</span><span class=\"mtk1\">.</span><span class=\"mtk11\">push_back</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Jack&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Paul &#x26; Jack are stored in contiguous memory blocks, even though we didn't provide a specific limit at the start - as we do with arrays.</p>\n</li>\n<li>\n<p><code>std::forward_list</code>: Singly linked-list.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">A -&gt; B -&gt; C -&gt; D</span></code></pre>\n<p>This is a simple example of linked-lists. Once you're at a point, let's say \"C\" - you can only go forwards.</p>\n</li>\n<li>\n<p><code>std::list</code>: Doubly linked-list.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">A &lt;-&gt; B &lt;-&gt; C &lt;-&gt; D</span></code></pre>\n<p>Above is a simple example of a doubly linked-list. Unlike Singly linked-lists, if you're at \"C\", you can go either way. To \"B\" or \"D\".</p>\n</li>\n<li><code>std::deque</code>: Double-ended queues - insertion and removal possible at both ends.</li>\n</ul>\n</li>\n<li>\n<p>Container Adaptors: (different interface of accessibility from sequence containers)</p>\n<ul>\n<li><code>std::queue</code>: A standard queue, where removals are done from the front, and insertions are done at the end. The queue is a FIFO structure (First in, First out).</li>\n<li><code>std::priority_queue</code>: A queue in which elements can have a varying level of importance. The ones with the highest importance are at the front, and thus processed first.\nFor example, let's say you're at a barbershop. A person arrived after you. If that person would've made a prior appointment to the shop, he would automatically be placed ahead of you with more \"importance\". Priority queues work similarly.</li>\n<li><code>std::stack</code>:\nSuppose you have a pile of 10 books. If you need a book from middle - of course, like most people, you will pull it right from the middle in one go. Let's think about how computers would take this problem. A computer needs a step-by-step instruction, so the first thing it would do is remove the book from the top. And continue to do that until it reaches the book. To keep books as they were again, it would place books one by one at the top of the pile.\nThus, insertions and removals in a stack are only done at the \"top\". </li>\n</ul>\n</li>\n<li>\n<p>Associative containers: (sorted in a specific order, these containers boast search speeds of O(log N))</p>\n<ul>\n<li><code>std::set</code>: Each element inserted into a set is it's own identifier, meaning that unique elements are entered. Each element acts as it's own \"key\" - which uniquely identifies it. For example, suppose you are a volunteer for entering student information for new students entering into the semester. They are uniquely identified by their roll numbers. Suppose you enter the same student's Roll No (the ID) twice into a set, it will be inserted just once - because a \"set\" can only have unique values.</li>\n<li><code>std::multiset</code>: Like a set, but here the same multiple elements are allowed. Entering the roll no from before twice into an <code>std::multiset</code> will result in it being added twice.</li>\n<li><code>std::map</code>: Take a literal map, for example. When you point to a location on the map, it tells you the details. The \"point\" is the key, and the details of that location are the \"values\". The keys are unique, and values can be anything. An <code>std::map</code> works the same way. Perhaps an example will help understanding more about it:</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"cpp\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// This maps a student name to his marks. But is this correct?</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk10\">std</span><span class=\"mtk1\">::map&lt;</span><span class=\"mtk10\">std</span><span class=\"mtk1\">::string, </span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; mapOfStudentNameToMarks;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// The answer is no. A student&#39;s name isn&#39;t necessarily unique, multiple students with the same name will have a clash this way.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// Thus, the correct way would be:</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk10\">std</span><span class=\"mtk1\">::map&lt;</span><span class=\"mtk4\">int</span><span class=\"mtk1\">, </span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; mapOfStudentIDToMarks;</span><span class=\"mtk3\"> // This is correct, because StudentIDs are unique!</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">mapOfStudentIDToMarks</span><span class=\"mtk1\">[</span><span class=\"mtk7\">1</span><span class=\"mtk1\">] = </span><span class=\"mtk7\">100</span><span class=\"mtk1\">;</span><span class=\"mtk3\">   // StudentID 1 -&gt; 100 Marks.</span></span></code></pre>\n<ul>\n<li><code>std::multimap</code>: Can you guess what this might do, based on <code>std::multiset</code>?\nMultimap allows multiple elements to have the same key. So, for example, 10 -> 100 &#x26; 10 -> 150 are both valid for a multimap.</li>\n</ul>\n</li>\n<li>\n<p>Unordered Associative containers: (like associative containers, but implemented as hash-tables. They can be accessed at O(1), i.e., constant time.</p>\n<ul>\n<li><code>std::unordered_set</code></li>\n<li><code>std::unordered_multiset</code></li>\n<li><code>std::unordered_map</code></li>\n<li><code>std::unordered_multimap</code>\n-- </li>\n</ul>\n</li>\n</ul>\n<h3 id=\"stl---what-next\" style=\"position:relative;\"><a href=\"#stl---what-next\" aria-label=\"stl   what next permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>STL - What next?</h3>\n<p>Containers aren't the only part of STL. It is huge! You are encouraged to read up more on STL, as it makes your life easier in every manner! You don't need to reinvent the wheel. Next, you could try looking up the various algorithms contained in the STL. They're present in the header file <code>&#x3C;algorithm></code>. Good luck on your journey!</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n</style>","frontmatter":{"date":"October 13, 2020","updated_date":null,"description":"Learn how Standard Template Library works in C++ with interactive examples and what you need to get started","title":"STL Containers & Data Structures in C++","tags":["C++","STL"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/4ec0001784cd81b020aea7e2bbf26abb/58556/cover.webp","srcSet":"/static/4ec0001784cd81b020aea7e2bbf26abb/61e93/cover.webp 200w,\n/static/4ec0001784cd81b020aea7e2bbf26abb/1f5c5/cover.webp 400w,\n/static/4ec0001784cd81b020aea7e2bbf26abb/58556/cover.webp 800w,\n/static/4ec0001784cd81b020aea7e2bbf26abb/99238/cover.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Aryan Rawlani","github":"aryanrawlani28","avatar":null}}}},{"node":{"excerpt":"Before we get into details of finding out optimal clusters, let's first see what the KMeans clustering algorithm is and some basics about it…","fields":{"slug":"/engineering/optimal-clusters-kmeans/"},"html":"<p>Before we get into details of finding out optimal clusters, let's first see what the KMeans clustering algorithm is and some basics about it.</p>\n<h2 id=\"what-is-clustering\" style=\"position:relative;\"><a href=\"#what-is-clustering\" aria-label=\"what is clustering permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is Clustering?</h2>\n<p>Clustering is an unsupervised ML technique wherein we cluster the data to get insights from it. Clustering the data is quite essential for some business models and problems. It gives us conclusions on what is a cluster, i.e. data which is similar and in the form of cluster or groups.</p>\n<blockquote>\n<p>Clustering is the process of dividing the entire data into groups (also known as clusters) based on the patterns in the data.</p>\n</blockquote>\n<h2 id=\"what-is-the-kmeans-clustering-algorithm\" style=\"position:relative;\"><a href=\"#what-is-the-kmeans-clustering-algorithm\" aria-label=\"what is the kmeans clustering algorithm permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is the KMeans clustering algorithm?</h2>\n<p>It is an algorithm for clustering. We will be discussing this method with code in the further sections.</p>\n<h2 id=\"initial-imports-\" style=\"position:relative;\"><a href=\"#initial-imports-\" aria-label=\"initial imports  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Initial Imports :</h2>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> pandas </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> pd</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> numpy </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> np</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> matplotlib.pyplot </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> plt</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> sklearn.cluster </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> KMeans</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">%matplotlib inline</span></span></code></pre>\n<h2 id=\"method-\" style=\"position:relative;\"><a href=\"#method-\" aria-label=\"method  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Method :</h2>\n<p>Now let's discuss the method behind finding out the right number of clusters on a K-Means clustering algorithm.\nSo we will learn how to decide what number of clusters to input into your K-Means algorithm.\nHere we've got a data science problem.\nWe've got only two variables, x and y coordinates.</p>\n<p>Now, if we run the K means clustering algorithm on this dataset with three clusters or with K pre-determine the clusters to be three, then the result will look something like this.</p>\n<p><img src=\"/f2f1dc62cdf496de947a76353a248a23/initial.webp\" alt=\"initial\"></p>\n<p>We need a specific metric, we need a way to understand or evaluate how a certain number of clusters performs compared to a different number of clusters, and preferably, that metric should be quantifiable.</p>\n<p>So what kind of metric can we impose upon our clustering algorithm that will tell us something about the final result?\nThere is such a metric called the within-cluster sum of squares. (WCSS)</p>\n<p><img src=\"/9e24eb349c5a9a1d35919c74606a5fe1/Wcss.webp\" alt=\"Wcss\"></p>\n<p>So you can see here that it jumps from 8000 down to 3000, that's a massive change of 5000. Let's just call them units, 5000 units and then from 3000 as we increase the number of the close from 2 to 3, they jump from 3000 to 1000.</p>\n<p>Again quite a large drop and then from three to four what's going to happen is going to jump from 1000 to maybe eight hundred and from 800 to 600, 600 to 500 and so on so as you can see the first two improvements or first two changes from one cluster to two from two to three created some huge jumps or considerable drops in the WTS going forward The WCR says drops not substantially. And this is our hint at selecting the optimum optimal number of clusters; and the method we're going to use is the elbow method, and it is very visual. All you have to do is look at your chart and look for that change, or that's kind of like it does look like an ELBOW.</p>\n<p>Look for that elbow in your chart where the drop goes from being quite substantial to being not as significant not as proven is not as great, and therefore, that point in your chart will be the optimal number of clusters.</p>\n<p>In this case, it is indeed three clusters.</p>\n<p>That is the optimal number. And as you can imagine, this method is entirely arbitrary.\nSometimes, the situations are not as pronounced as the elbow might not be as evident as in this case, and therefore, somebody might pick one number of clusters. Someone else might come along and select a different number.</p>\n<h2 id=\"code-\" style=\"position:relative;\"><a href=\"#code-\" aria-label=\"code  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CODE :</h2>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> sklearn.cluster </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> KMeans</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">wcss = []</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">for</span><span class=\"mtk1\"> i </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> </span><span class=\"mtk11\">range</span><span class=\"mtk1\">(</span><span class=\"mtk7\">1</span><span class=\"mtk1\">, </span><span class=\"mtk7\">11</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  kmeans = KMeans(</span><span class=\"mtk12\">n_clusters</span><span class=\"mtk1\"> = i, </span><span class=\"mtk12\">init</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;k-means++&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">random_state</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">42</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  kmeans.fit(X)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  wcss.append(kmeans.inertia_)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">plt.plot(</span><span class=\"mtk11\">range</span><span class=\"mtk1\">(</span><span class=\"mtk7\">1</span><span class=\"mtk1\">, </span><span class=\"mtk7\">11</span><span class=\"mtk1\">), wcss)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">plt.title(</span><span class=\"mtk8\">&#39;The Elbow Method&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">plt.xlabel(</span><span class=\"mtk8\">&#39;Number of clusters&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">plt.ylabel(</span><span class=\"mtk8\">&#39;WCSS&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">plt.show()</span></span></code></pre>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n</style>","frontmatter":{"date":"October 12, 2020","updated_date":null,"description":null,"title":"Optimal clusters for KMeans Algorithm","tags":["Machine Learning"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/225782b978d81111592f1f839c6dc1e4/58556/cover.webp","srcSet":"/static/225782b978d81111592f1f839c6dc1e4/61e93/cover.webp 200w,\n/static/225782b978d81111592f1f839c6dc1e4/1f5c5/cover.webp 400w,\n/static/225782b978d81111592f1f839c6dc1e4/58556/cover.webp 800w,\n/static/225782b978d81111592f1f839c6dc1e4/b0b9b/cover.webp 1192w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Neeraj Ap","github":"NEERAJAP2001","avatar":null}}}}]},"markdownRemark":{"excerpt":"Identity is evolving, and developers are at the forefront of this transformation. Every day brings a new learning—adapting to new standards…","fields":{"slug":"/identity/developer-first-identity-provider-loginradius/"},"html":"<p>Identity is evolving, and developers are at the forefront of this transformation. Every day brings a new learning—adapting to new standards and refining approaches to building secure, seamless experiences.</p>\n<p>We’re here to support developers on that journey. We know how important simplicity, efficiency, and well-structured documentation are when working with identity and access management solutions. That’s why we’ve redesigned the <a href=\"https://www.loginradius.com/\">LoginRadius website</a>—to be faster, more intuitive, and developer-first in every way.</p>\n<p>The goal? Having them spend less time searching and more time building.</p>\n<h2 id=\"whats-new-and-improved-on-the-loginradius-website\" style=\"position:relative;\"><a href=\"#whats-new-and-improved-on-the-loginradius-website\" aria-label=\"whats new and improved on the loginradius website permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What’s New and Improved on the LoginRadius Website?</h2>\n<p>LoginRadius’ vision is to give developers a product that simplifies identity management so they can focus on building, deploying, and scaling their applications. To enhance this experience, we’ve spent the last few months redesigning our interface— making navigation more intuitive and reassuring that essential resources are easily accessible.</p>\n<p>Here’s a closer look at what’s new and why it’s important:</p>\n<h3 id=\"a-developer-friendly-dark-theme\" style=\"position:relative;\"><a href=\"#a-developer-friendly-dark-theme\" aria-label=\"a developer friendly dark theme permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>A Developer-Friendly Dark Theme</h3>\n<p><img src=\"/f46881583c7518a93bb24e94c32320de/a-developer-friendly-dark-theme.webp\" alt=\"This image shows how LoginRadius offers several authentication methods like traditional login, social login, passwordless login, passkeys and more in a dark mode.\">    </p>\n<p>Developers spend long hours working in dark-themed IDEs and terminals, so we’ve designed the LoginRadius experience to be developer-friendly and align with that preference.</p>\n<p>The new dark mode reduces eye strain, enhances readability, and provides a seamless transition between a coding environment and our platform. Our new design features a clean, modern aesthetic with a consistent color scheme and Barlow typography, ensuring better readability. High-quality graphics and icons are thoughtfully placed to enhance the content without adding visual clutter.</p>\n<p>So, whether you’re navigating our API docs or configuring authentication into your system, our improved interface will make those extended development hours more comfortable and efficient.</p>\n<h3 id=\"clear-categorization-for-loginradius-capabilities\" style=\"position:relative;\"><a href=\"#clear-categorization-for-loginradius-capabilities\" aria-label=\"clear categorization for loginradius capabilities permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Clear Categorization for LoginRadius Capabilities</h3>\n<p><img src=\"/e5358b82be414940f3fb146013845933/capabilities.webp\" alt=\"This image shows a breakdown of all the LoginRadius CIAM capabilities, including authentication, security, UX, scalability and multi-brand management.\"></p>\n<p>We’ve restructured our website to provide a straightforward breakdown of our customer identity and access management platform capabilities, helping you quickly find what you need:</p>\n<ul>\n<li>Authentication: Easily understand <a href=\"https://www.loginradius.com/blog/identity/authentication-option-for-your-product/\">how to choose the right login method</a>, from traditional passwords and OTPs to social login, federated SSO, and passkeys with few lines of code.</li>\n<li>Security: Implement no-code security features like bot detection, IP throttling, breached password alerts, DDoS protection, and adaptive MFA to safeguard user accounts.</li>\n<li>User Experience: Leverage AI builder, hosted pages, and drag-and-drop workflows to create smooth, branded sign-up and login experiences.</li>\n<li>High Performance &#x26; Scalability: Confidently scale with sub-100ms API response times, 100% uptime, 240K+ RPS, and 28+ global data center regions.</li>\n<li>Multi-Brand Management: Efficiently manage multiple identity apps, choosing isolated or shared data stores based on your brand’s unique needs.</li>\n</ul>\n<p>This structured layout ensures you can quickly understand each capability and how it integrates into your identity ecosystem.</p>\n<h3 id=\"developer-first-navigation\" style=\"position:relative;\"><a href=\"#developer-first-navigation\" aria-label=\"developer first navigation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Developer-First Navigation</h3>\n<p><img src=\"/a8c155c2b6faf3d5f4b4de4e2b14d763/developers-menu.webp\" alt=\"This image shows the LoginRadius menu bar, highlighting the developer dropdown.\">   </p>\n<p>We’ve been analyzing developer workflows to identify how you access key resources. That’s why we redesigned our navigation with one goal in mind: to reduce clicks and make essential resources readily available.</p>\n<p>The new LoginRadius structure puts APIs, SDKs, and integration guides right at the menu bar under the Developers dropdown so you can get started faster. Our Products, Solutions, and Customer Services are also clearly categorized, helping development teams quickly find the right tools and make informed decisions.</p>\n<h3 id=\"quick-understanding-of-integration-benefits\" style=\"position:relative;\"><a href=\"#quick-understanding-of-integration-benefits\" aria-label=\"quick understanding of integration benefits permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Quick Understanding of Integration Benefits</h3>\n<p><img src=\"/b2f9a964a2da0ea83e2f8596b833bba7/we-support-your-tech-stack.webp\" alt=\"This image shows a list of popular programming languages and frameworks offered by LoginRadius.\"></p>\n<p>Developers now have a clear view of the tech stack available with LoginRadius, designed to support diverse business needs.</p>\n<p>Our platform offers pre-built SDKs for Node.js, Python, Java, and more, making CIAM integration seamless across popular programming languages and frameworks.</p>\n<h2 id=\"over-to-you-now\" style=\"position:relative;\"><a href=\"#over-to-you-now\" aria-label=\"over to you now permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Over to You Now!</h2>\n<p>Check out our <a href=\"https://www.loginradius.com/\">revamped LoginRadius website</a> and see how the improved experience makes it easier to build, scale, and secure your applications.</p>\n<p>Do not forget to explore the improved navigation and API documentation, and get started with our free trial today. We’re excited to see what you’ll build with LoginRadius!</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"February 21, 2025","updated_date":null,"description":"LoginRadius’ vision is to give developers a product that simplifies identity management so they can focus on building, deploying, and scaling their applications. To enhance this experience, we’ve redesigned our website interface, making navigation more intuitive and reassuring that essential resources are easily accessible.","title":"Revamped & Ready: Introducing the New Developer-First LoginRadius Website","tags":["Developer tools","API","Identity Management","User Authentication"],"pinned":true,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.7857142857142858,"src":"/static/80b4e4fbe176a10a327d273504607f32/58556/hero-section.webp","srcSet":"/static/80b4e4fbe176a10a327d273504607f32/61e93/hero-section.webp 200w,\n/static/80b4e4fbe176a10a327d273504607f32/1f5c5/hero-section.webp 400w,\n/static/80b4e4fbe176a10a327d273504607f32/58556/hero-section.webp 800w,\n/static/80b4e4fbe176a10a327d273504607f32/99238/hero-section.webp 1200w,\n/static/80b4e4fbe176a10a327d273504607f32/7c22d/hero-section.webp 1600w,\n/static/80b4e4fbe176a10a327d273504607f32/1258b/hero-section.webp 2732w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Rakesh Soni","github":"oyesoni","avatar":"rakesh-soni.webp"}}}},"pageContext":{"limit":6,"skip":702,"currentPage":118,"type":"///","numPages":164,"pinned":"ee8a4479-3471-53b1-bf62-d0d8dc3faaeb"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}