Auth0 blog 2017-03-24T16:35:02+00:00 https://auth0.com/blog Auth0 helo@auth0.com How To Get A 360 View of Your Customer By Managing Identity 2017-03-24T08:30:00+00:00 https://auth0.com/blog/360-view-of-customer-by-managing-identity/ Diego Poza https://twitter.com/diegopoza <hr /> <p>Having a 360 view of your customers might sound like just another marketing cliche designed to sell CRM software. But the idea—that you should have a comprehensive understanding of your customers at all stages of the lifecycle, from acquisition to referral— is essentially the holy grail of all growth marketing efforts.</p> <p>Back in the early days of apps and the internet, a 360 view was easier to acquire. User identities were simply more consolidated. You didn't have dozens of SaaS tools running off the cloud, your users' identities weren't dispersed across Google, Facebook, and every other social platform — all your users' data was stored in your own system. You were in charge.</p> <p>Those days are gone. The landscape is fragmented by all different kinds of identity providers, authentication protocols, and tools.</p> <p>What you have instead is a vast explosion of user data and tools for analyzing that data. That's made getting a 360 view of your customers more technically complicated—but it's also made it far more powerful.</p> <h2>Your Identity Management System Needs a Single Source of Truth</h2> <p>The biggest roadblock to getting a 360 view of your users is how identity is managed. The complexity begins when a user signs up for your app and it expands entropically as they use it. Your different SaaS tools and monitoring systems collect all of this information, send it back to their servers, and then you wind up fighting with their APIs and integrations to make sense of all of it.</p> <p>That's why the best analytics teams begin the process of collecting data at the root—when a user first signs up for an app.</p> <p>The easiest way to do that is to set up a classic 1:1 authentication system. You control user registration and login, you manage their passwords, and you are the only entity that is involved. Therefore, you have total access to your users' data and the data of any external APIs you might integrate with.</p> <p>What makes this tricky today is that federated identity management is such an established practice. You want to be enabling social and enterprise login if you have an app of any size, or a new app that you want people to feel comfortable using. Federated identity managers are simply not based on a centralized model—consolidating your customer view into one place will involve a ton of development time and effort.</p> <p>That's why we built Auth0, an identity provider that acts as both a classical identity provider and a federated identity manager.</p> <p><img src="https://cdn.auth0.com/blog/360-view-by-identity/venndiagram.jpg" alt="Auth0 Value Prop" /></p> <p>This allows you create the foundations on which to start building and acting upon your 360 view of your customer:</p> <ul> <li><p><strong>Classic identity management</strong>:</p> <ul> <li><strong>Auth0</strong>: <ul> <li>stores login credentials for every unique user</li> <li>provides user information on an analytics dashboard</li> <li>manages all of the users in your organization, no matter what they used to log in</li> </ul> </li> </ul> </li> <li><p><strong>Federated identity management:</strong></p> <ul> <li><strong>Social login</strong>: User and password from Facebook, Google, Twitter, etc. serve as login information for connection to the desired platform through Auth0 <img src="https://cdn.auth0.com/blog/360-view-by-identity/auth0-social-login.jpeg" alt="Auth0 Providers" /></li> <li><strong>Enterprise login</strong>: Enterprise credentials are used to access a variety of systems and platforms, where the username and login are stored in an internal identity provider but connected through Auth0</li> </ul> </li> </ul> <p>This type of data collection means that you can connect user information that would otherwise be stored in completely separate places — maybe data that isn't even collected directly by your app. Putting the missing pieces in your user profile for a 360 view gives you what you need to customize your user interaction, from onboarding to upselling.</p> <h2>Automate the Error Out of Your Data Centralization</h2> <p>Within your own system, you use a variety of tools to help you monitor and engage with users. Maybe you have an app analytics platform to gather behavioral data, an email management system to send personalized emails, a CRM, and a login platform like Auth0. These systems tend to rely on client-side analytics, which makes the perfect storm for data to slip through the cracks.</p> <p>Client-side analytics are notoriously unreliable. Because they have to be executed on the user's end when they first visit your site, they can easily be disrupted:</p> <ul> <li>Users might exit out of a page before your code runs</li> <li>They could block JavaScript (with an ad blocker, for instance)</li> <li>They might click on a link before the page has finished loading and interrupt the loading script</li> </ul> <p>Meanwhile, server-side analytics are unwieldy and difficult to implement. In order to get all of your desired server-side analytics running with your system, you'll end up running through a web of APIs and <a href="https://segment.com/blog/the-way-server-side-analytics-should-be/">writing more and more code</a> just to get everything working smoothly.</p> <p>That's where Auth0 Rules come in. Rules are snippets of server-side Javascript that run as soon as a user logs in, eliminating the client-side reliability problem while being just as easy to set up and get going.</p> <p><img src="https://cdn.auth0.com/blog/360-view-by-identity/flow.png" alt="Auth0 Identity Flow" /></p> <p>With <a href="https://auth0.com/docs/rules">Auth0 Rules</a>, your server-side automation always gets information from your user to your tools. For example, if you wanted to create a lead in Salesforce the first time a user logs in, you can [use an Auth0 Rule to instantly send] (https://github.com/auth0/rules/blob/master/rules/creates-lead-salesforce.md) the signal to Salesforce to make a new lead.</p> <p>In fact, you can connect Auth0 with pretty much any platform by creating automated actions at sign in using JavaScript. And they're just a few lines of code — not a forest of API integrations.</p> <p>You need to know that your tools are going to get the data they need to help you understand how your customers are behaving, and automating a cross-platform integration ensures that you <a href="https://auth0.com/blog/integrate-auth0-into-your-existing-saas-tools/">realize the power of all of your SaaS platforms</a>.</p> <h2>Use Your Centralized Data to Cater to Your Customers</h2> <p>A rich, 360 view of your customers is a springboard for fine-tuning your product to increase customer satisfaction. The way you interact with your users from login onwards can make or break whether or not you retain those customers, no matter how good your product is.</p> <p>When you're unable to consolidate all the information that you know about your customers, you can easily wind up asking them the same questions twice. Getting information about who your customers really are turns into a slow and error-prone process. When you have a centralized repository of knowledge about your users and a reliable infrastructure for gathering data on them, however, you can put much more effective and subtle collection practices into place.</p> <p>A great example of this is <a href="https://auth0.com/blog/progressive-profiling/">progressive profiling</a>. You want to ask your users questions about who they are and why they're using your product, but you know that slamming your users with a huge form as soon as they sign up kills your conversion rates. With Auth0, you can create a Rule that triggers every time your users log in. You can ask them questions intermittently—throughout their customer journey—rather than giving them a huge survey up-front.</p> <p><img src="https://cdn.auth0.com/blog/360-view-by-identity/progressive-profiling-2.png" alt="Progressive Profiling" /></p> <p>Auth0 helps you store all of this information through creating profile records. You can gather information from an existing identity (like a Facebook profile), an Auth0 Rule, or information the user adds to their profile. Each users' profile record will get updated as data rolls in, to keep all of that valuable information accessible.</p> <p>Capturing and centralizing log in information is a great way to make your users' experience better, especially when it is part of a larger customer profile. When the user experience is good, your customers are satisfied, and there's nothing better for business than satisfied customers.</p> <h2>To Delight, You Must First Understand</h2> <p>Creating a complete profile for your customer is one of the most important steps you can take to turn your users' actions into insights.</p> <p>Think of all the bad email marketing campaigns you've deleted from your inbox, or marked as spam. Think of all the irrelevant push notifications you've gotten. Think of all the products you've downloaded with high hopes only to see an onboarding process that seems like it wasn't designed with <em>anyone in mind.</em></p> <p>When you centralize your data collection and build up the right infrastructure around it—the kind that lets everyone on your team get on the same page—then you become capable of building truly personalized, delightful experiences across every part of your app.</p> Brute Forcing HS256 is Possible: The Importance of Using Strong Keys in Signing JWTs 2017-03-23T08:30:00+00:00 https://auth0.com/blog/brute-forcing-hs256-is-possible-the-importance-of-using-strong-keys-to-sign-jwts/ Prosper Otemuyiwa http://twitter.com/unicodeveloper?lang=en <p>JSON Web Tokens are an open, industry standard <a href="https://tools.ietf.org/html/rfc7519">RFC 7519</a> method for representing claims securely between two parties. They can be digitally signed or encrypted and there are several algorithms that can be employed in signing a JWT. In this article, we'll look at the two most common algorithms and discover how using weak keys can allow malicious parties to brute force the secret key from the JWT.</p> <h2>What is a JSON Web Token?</h2> <p>A JSON Web Token encodes a series of claims in a JSON object. Some of these claims have specific meaning, while others are left to be interpreted by the users. These claims can be verified and trusted because it is digitally signed. Examples of these claims are <code>issuer (iss)</code>, <code>subject (sub)</code>, <code>audience (aud)</code>, <code>expiration time (exp)</code>, <code>not before (nbf)</code>, and <code>issued at (iat)</code>. JWTs can be signed using a secret (with HMAC algorithm) or a public/private key pair using RSA or Elliptic-Curve.</p> <h2>Structure of a JSON Web Token</h2> <p>A signed, compact-serialized JWT consists of three main parts separated by a <code>.</code> namely:</p> <ul> <li>Header</li> <li>Payload</li> <li>Signature</li> </ul> <p>A JWT comes in this structure, <code>aaaaaa.bbbbbb.ccccc</code>. <code>aaaaaaa</code> represents the header, <code>bbbbb</code> represents the payload while <code>cccccc</code> represents the signature.</p> <h3>Header</h3> <p>The header typically consists of two parts: the type of the token, which is JWT, and the hashing algorithm such as <code>HS256</code> or <code>RS256</code>. Example:</p> <pre><code class="js"> { "alg": "HS256", "typ": "JWT" } </code></pre> <p>Then, this JSON is Base64Url encoded to form the first part of the JWT.</p> <h3>Payload</h3> <p>This part of the token carries the claims. An example of a payload can be found below:</p> <pre><code class="js"> { "sub": "1234567890", "name": "John Doe", "manager": true } </code></pre> <p>The payload is then <code>Base64Url</code> encoded to form the second part of the JWT.</p> <h3>Signature</h3> <p>The last part of the token is the signature. The signature is composed from the signing of the encoded header, encoded payload, and a secret.</p> <p>An example of a signature using the HMAC SHA256 (HS256) algorithm can be created like so:</p> <pre><code class="bash"> HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) </code></pre> <p><em>A signed JWT</em></p> <p><img src="https://cdn.auth0.com/content/jwt/encoded-jwt4.png" alt="" /></p> <h2>JWT Signing Algorithms</h2> <p>The most common algorithms for signing JWTs are:</p> <ul> <li>HMAC + SHA256 (HS256)</li> <li>RSASSA-PKCS1-v1_5 + SHA256 (RS256)</li> <li>ECDSA + P-256 + SHA256 ( ES256)</li> </ul> <h3>HS256</h3> <p>Hash-based Message Authentication Code (HMAC) is an algorithm that combines a certain payload with a secret using a cryptographic hash function like <code>SHA-256</code>. The result is a code that can be used to verify a message only if both the generating and verifying parties know the secret. In other words, HMACs allow messages to be verified through shared secrets.</p> <p>This is an example showcasing a HMAC-based signing algorithm:</p> <pre><code class="js"> const encodedHeader = base64(utf8(JSON.stringify(header))); const encodedPayload = base64(utf8(JSON.stringify(payload))); const signature = base64(hmac(`${encodedHeader}.${encodedPayload}`, secret, sha256)); const jwt = `${encodedHeader}.${encodedPayload}.${signature}`; </code></pre> <p>An example of signing a JWT with the <code>HS256</code> algorithm using the <code>jsonwebtoken</code> JavaScript library can be found below:</p> <pre><code> var jwt = require('jsonwebtoken'); const payload = { sub: "1234567890", name: "John Doe", manager: true }; const secretKey = 'secret'; const token = jwt.sign(payload, secretKey, { algorithm: 'HS256', expiresIn: '10m' // if ommited, the token will not expire }); </code></pre> <h3>RS256</h3> <p>RSA is a public-key algorithm. Public-key algorithms generate split keys: one public key and one private key.</p> <p>For public-key signing algorithms:</p> <pre><code class="js"> const encodedHeader = base64(utf8(JSON.stringify(header))); const encodedPayload = base64(utf8(JSON.stringify(payload))); const signature = base64(rsassa(`${encodedHeader}.${encodedPayload}`, privateKey, sha256)); const jwt = `${encodedHeader}.${encodedPayload}.${signature}`; </code></pre> <p>When signing and verifying JWTs signed with RS256, you deal with a public/private key pair rather than a shared secret. There are many ways to create RSA keys. OpenSSL is one of the most popular libraries for key creation and management:</p> <pre><code class="bash"> # Generate a private key openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048 # Derive the public key from the private key openssl rsa -pubout -in private_key.pem -out public_key.pem </code></pre> <p>Both <code>PEM</code> files are simple text files. Their contents can be copied and pasted into your JavaScript source files and passed to the <code>jsonwebtoken</code> library.</p> <pre><code class="js"> // You can get this from private_key.pem above. const privateRsaKey = `&lt;YOUR-PRIVATE-RSA-KEY&gt;`; const signed = jwt.sign(payload, privateRsaKey, { algorithm: 'RS256', expiresIn: '5s' }); </code></pre> <pre><code class="js"> // You can get this from public_key.pem above. const publicRsaKey = `&lt;YOUR-PUBLIC-RSA-KEY&gt;`; const decoded = jwt.verify(signed, publicRsaKey, { // Never forget to make this explicit to prevent // signature stripping attacks. algorithms: ['RS256'], }); </code></pre> <h3>ES256</h3> <p>ECDSA algorithms also make use of public keys. We can use OpenSSL to generate the key as well:</p> <pre><code class="bash"> # Generate a private key (prime256v1 is the name of the parameters used # to generate the key, this is the same as P-256 in the JWA spec). openssl ecparam -name prime256v1 -genkey -noout -out ecdsa_private_key.pem # Derive the public key from the private key openssl ec -in ecdsa_private_key.pem -pubout -out ecdsa_public_key.pem </code></pre> <p>If you open these files you will note that there is much less data in them. This is one of the benefits of ECDSA over RSA. The generated files are in PEM format as well, so simply pasting them in your source will suffice.</p> <pre><code class="js"> // You can get this from private_key.pem above. const privateEcdsaKey = `&lt;YOUR-PRIVATE-ECDSA-KEY&gt;`; const signed = jwt.sign(payload, privateEcdsaKey, { algorithm: 'ES256', expiresIn: '5s' }); </code></pre> <pre><code class="js"> // You can get this from public_key.pem above. const publicEcdsaKey = `&lt;YOUR-PUBLIC-ECDSA-KEY&gt;`; const decoded = jwt.verify(signed, publicEcdsaKey, { // Never forget to make this explicit to prevent // signature stripping attacks. algorithms: ['ES256'], }); </code></pre> <blockquote><p><strong>Note:</strong> These algorithm notes above are excerpts from the very comprehensive <a href="https://auth0.com/e-books/jwt-handbook">Auth0 JWT book</a> written by <a href="https://twitter.com/speyrott">Sebastian Peyrott</a>. Download it for more information on signing and validating JWTs using these algorithms mentioned above.</p></blockquote> <h2>Brute Forcing a HS256 JSON Web Token</h2> <p>As secure as <code>HS256</code> is, especially when implemented the right way, brute-forcing a JSON web token signed with small and medium sized shared-secrets using <strong>HS256</strong> is still very possible.</p> <p>Recently, I came across a <a href="https://github.com/brendan-rius/c-jwt-cracker">tool</a> written in C on GitHub. It is a multi-threaded JWT brute force cracker. With a huge computing power, this tool can find the secret key of a <code>HS256</code> <strong>JSON Web token</strong>.</p> <p><em>Please note the RFC7518 standard states that "A key of the same size as the hash output (for instance, 256 bits for "HS256") or larger MUST be used with this algorithm." Auth0 secret keys exceed this requirement making cracking via this or similar tools all but impossible.</em></p> <h3>Implementing a Brute Force Attack</h3> <p>I used a Mac computer to try out the brute force attack. First, make sure you have <code>openssl</code> installed. If it is not, install it with homebrew like so:</p> <pre><code class="bash"> brew install openssl </code></pre> <p>Then run this command in the terminal like so:</p> <pre><code class="bash"> make OPENSSL=/usr/local/opt/openssl/include OPENSSL_LIB=-L/usr/local/opt/openssl/lib </code></pre> <p>On Ubuntu, you can install <code>openssl</code> like so:</p> <pre><code class="bash"> apt-get install libssl-dev </code></pre> <p>The specs of my MacBook are mentioned below:</p> <ul> <li>Processor 2.7 GHz Intel Core i5</li> <li>Memory 8GB 1867 MHz DDR3</li> <li>Graphics Intel Iris Graphics 6100 1536 MB</li> </ul> <p>Go ahead and clone the <code>jwt-cracker</code> from <a href="https://github.com/brendan-rius/c-jwt-cracker">GitHub</a>.</p> <p>An example JWT signed with <code>HS256</code> and a secret, <code>Sn1f</code> is:</p> <pre><code class="bash"> eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE </code></pre> <p>Now, run the <code>jwt-cracker</code> from your terminal to crack the token like so:</p> <pre><code class="bash"> time ./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE </code></pre> <blockquote><p><strong>Note:</strong> Make sure the <code>jwtcrack</code> script is executable by running <code>chmod a+x ./jwtcrack</code></p></blockquote> <p><img src="https://cdn.auth0.com/blog/bruteforceattack/token.png" alt="Crack" /></p> <p>It took about 6.16s on my laptop to crack the secret key.</p> <p>With the help of <a href="https://jwt.io">jwt.io</a>, let's sign another token quickly, but with a secret, <em>secret</em>.</p> <p>Run the cracker again with the new JWT like so:</p> <pre><code class="bash"> time ./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ </code></pre> <p><img src="https://cdn.auth0.com/blog/bruteforceattack/anothertoken.png" alt="Crack a new token" /> <em>Crack another token</em></p> <p>From the results shown above, it cracked the token and got our secret, which is actually <em>secret</em> in about 3273.51s.</p> <h3>Security Concerns and Recommendation</h3> <p>Let's take another look at the keys we used to generate the tokens that were cracked easily. What are the key sizes? The first key, <code>Sn1f</code> is 32-bit.</p> <blockquote><p>1 character = 8 bits</p></blockquote> <p>The second key, <code>secret</code> is 48-bit. This is simply too short to be a valid key. In fact, the <a href="https://tools.ietf.org/html/rfc7518#page-7">JSON Web Algorithms RFC 7518</a> states that a key of the same size as the hash output (for instance, 256 bits for "HS256") or larger MUST be used with the HS256 algorithm.</p> <p>I therefore recommend that anyone trying to generate a JSON Web token and signing them with HS256 to use a properly sized secret key. <a href="https://auth0.com">Auth0</a> secret keys are 512 bits in length and not susceptible to this type of brute force attack. Additionally, Auth0 allows you to easily sign your JWTs with <strong>RS256</strong>.</p> <h2>Using Auth0 to sign JWT with RS256</h2> <p>With <a href="https://auth0.com">Auth0</a>, you can easily generate JWTs for authentication and authorization. By default, we use HS256 to sign the JWTs generated, but we also allow customs to use RS256 if their use case calls for it. The <a href="https://auth0.com/docs/libraries/lock">Auth0 Lock</a> library returns a signed JWT that you can store on the client side and use for future requests to your APIs.</p> <p>In the vast majority of use cases you would never need to change the signing algorithm, but on the off chance that you do, let's see how to accomplish it with Auth0.</p> <p>Create a client on the <a href="https://manage.auth0.com">dashboard</a> like so:</p> <p><img src="https://cdn.auth0.com/blog/bruteforceattack/create_app.png" alt="Create a client" /> <em>Create a client</em></p> <p>Go to settings like so:</p> <p><img src="https://cdn.auth0.com/blog/bruteforceattack/settings.png" alt="Settings Page" /> <em>Settings Page</em></p> <p>Scroll down to <em>Show Advanced Settings</em> like so:</p> <p><img src="https://cdn.auth0.com/blog/bruteforceattack/show_advanced_settings.png" alt="Show Advanced Settings" /> <em>Show Advanced settings</em></p> <p>Switching to <strong>RS256</strong> is as easy as selecting the option from the dropdown on the Auth0 dashboard like so:</p> <p><img src="https://cdn.auth0.com/blog/bruteforceattack/switch_to_rs256.png" alt="Switch to RS256" /> <em>Default is HS256, Switching to RS256 is simple</em></p> <h2>Conclusion</h2> <p>JSON Web Tokens (JWTs) are lightweight and can easily be used across platforms and languages. They are a clever way to pass signed or encrypted information between applications. There are several <a href="https://jwt.io/#libraries-io">JWT libraries</a> available for signing and verifying the tokens.</p> <p>We have also been able to show that brute forcing of HS256 JWTs is certainly possible, when used with short and weak secret keys. Unfortunately, this is a limitation of most shared-key approaches. All cryptographic constructions, including HS256, are insecure if used with short keys, so ensure that implementations satisfy the standardized requirements.</p> <p>As a rule of thumb, make sure to pick a shared-key as long as the length of the hash. For HS256 that would be a 256-bit key (or 32 bytes) minimum. Luckily, if you are an Auth0 customer you have nothing to worry about as we follow all the standards and best practices when generating secret keys.</p> How to Manage JavaScript Fatigue 2017-03-22T08:30:00+00:00 https://auth0.com/blog/how-to-manage-javascript-fatigue/ Kim Maida https://twitter.com/KimMaida <p><strong>TL;DR:</strong> Most JavaScript developers have heard of or experienced JavaScript fatigue. JS fatigue is the overwhelming sense that we need to learn most of the hottest emerging technologies in order to do our jobs well. This is unattainable and the stress we feel to achieve it is unjustified; so how do we manage and combat JavaScript fatigue?</p> <hr /> <p><a href="https://cdn.auth0.com/blog/js-fatigue/comic.png"><img src="https://cdn.auth0.com/blog/js-fatigue/comic.png" alt="JavaScript fatigue comic" /></a> <em><a href="https://cdn.auth0.com/blog/js-fatigue/comic.png">View larger</a></em></p> <h2>What is JavaScript Fatigue?</h2> <p>Putting satire aside, <em>JavaScript fatigue</em> is on a lot of developers' tongues and blogs recently, and with valid reason. But what does it mean to have JS fatigue? It's often mentioned when someone hears about a new library, framework, dependency manager, build tool, etc. Let's do a quick breakdown of what JS fatigue means.</p> <h3>JS Fatigue vs. Analysis Paralysis</h3> <p>JS fatigue is often linked with <a href="https://en.wikipedia.org/wiki/Analysis_paralysis">analysis paralysis</a> (also called <em>choice paralysis</em>). JS analysis paralysis can occur because of the huge range of options when selecting a framework, tooling, testing suites, and more for a new application. Choosing the right framework or library can be challenging and occasionally even paralyzing, but having a wealth of tools at our disposal allows us to be more selective about what's best for the job at hand. In some cases, options help us to <em>avoid</em> fatigue by supplying an ideal solution for a specific project.</p> <h3>What it Means to Have JS Fatigue</h3> <p>We get JS fatigue when the requirements (either actual or self-imposed) for learning something are so daunting that a developer becomes exhausted and overwhelmed.</p> <p>JS fatigue can refer to:</p> <ul> <li>the fear that we'll fall behind or become obsolete if we don't know and use the newest, hottest tools;</li> <li>the sense that we never become experts in anything because everything changes too quickly and the tools we're trying to learn are already being replaced;</li> <li>picking up a new framework and then becoming overwhelmed thinking we need to master everything in the toolchain in order to use it;</li> <li>the fear that we'll pick a tool that will get displaced, resulting in a lack of support and obsolete resources;</li> <li>frustration with a lack of user empathy when consulting documentation or resources while trying to learn a new framework or toolchain.</li> </ul> <h2>JavaScript's Astonishing Growth Rate</h2> <p>In a nutshell, JS fatigue has become a phenomenon because the JS landscape is ever-changing. Various build tools, transpilers, and syntax additions are considered par for the course. There are even <a href="https://github.com/jashkenas/coffeescript/wiki/list-of-languages-that-compile-to-js">dozens of <em>entire languages</em> that compile to JS</a>.</p> <p>The exponential and unslowed growth of JS has opened the doors for great tools, languages, and frameworks. However, this also promotes change so rapid it can make any developer's head spin. <a href="https://segment.com/blog/the-deep-roots-of-js-fatigue/">The Deep Roots of Javascript Fatigue</a> delves into the history of JS and its swift evolution over a short amount of time. It's a great read and highly recommended.</p> <p>Only a few years ago, most programmers considered <em>front-end development</em> to consist primarily of HTML, CSS, and UI-enhancing JavaScript (such as jQuery). Since then, JS alone has proliferated into <a href="http://isomorphic.net/javascript">isomorphic JS</a>, <a href="https://auth0.com/blog/glossary-of-modern-javascript-concepts/#functional-reactive-programming">functional reactive programming</a> <a href="https://www.sitepoint.com/functional-reactive-programming-rxjs/">in</a> <a href="https://www.infoq.com/articles/virtual-panel-reactive-javascript-and-elm-in-2016">JS</a>, <a href="https://medium.com/javascript-scene/top-javascript-frameworks-topics-to-learn-in-2017-700a397b711#.fuxwtb909">frameworks, libraries, build</a> <a href="http://stackoverflow.com/questions/35062852/npm-vs-bower-vs-browserify-vs-gulp-vs-grunt-vs-webpack">tools, package managers, and much more</a>. We used to refer to "front-end" wholistically as all client-side development, but JS has evolved to support a specialization: <em>JavaScript developers</em>.</p> <h2>How to Manage JS Fatigue</h2> <p>At this time, JS proliferation is <em>not</em> showing signs of slowing. JS fatigue doesn't have a magic bullet cure, but there are things we can do to manage and also mitigate it. <strong>The following tips are useful for overwhelmed new developers as well as experienced, fatigued JS engineers.</strong></p> <h3>Pick Your Battles</h3> <p>The first thing to focus on is picking your battles. We get easily overwhelmed trying to follow every hot new thing that emerges. <strong>It's good to be <em>aware</em> of the sea of new technologies, but not to drown in it.</strong> If something starts to come up a lot, read a little about it. You'll want to know just enough to answer the following:</p> <ol> <li>What is its primary purpose?</li> <li>Is it popular enough to have a stable, growing community and easily accessible support? (Who is behind it? Who is using it?)</li> <li>Does it <em>solve</em> a problem I frequently run into with my current tools?</li> </ol> <p>If #1 isn't practical for your use case and the answers to #2 and #3 are not both <em>yes</em>, don't expend precious time and effort learning this if you're already fatigued. <strong>It can be best to wait and see, or to take a pass on tools that don't serve your goals.</strong> <a href="https://medium.com/javascript-scene/why-im-thankful-for-js-fatigue-i-know-you-re-sick-of-those-words-but-this-is-different-296fae0c888f#.h81mamgiv">Make peace with your focus</a> and remember that <em>no</em> JS developer is an expert in every new tool that lands.</p> <blockquote class="tweet-quote"> <a href="https://twitter.com/intent/tweet?text=&quot;Pick your battles: It can be best to wait and see, or to take a pass on tools that don't serve your goals.&quot; via @auth0 http://auth0.com/blog/how-to-manage-javascript-fatigue/"> <p>"Pick your battles: It can be best to wait and see, or to take a pass on tools that don't serve your goals."</p> <p class="tweet-link">TWEET THIS <img src="https://cdn.auth0.com/blog/resources/twitter.svg"></p> </a> </blockquote> <script> $(function() { $('.tweet-quote').on('click', function() { metricsLib.track('blog:share:twitter_quote'); }); }); </script> <p>In fact, it can make us <em>better developers</em> to know when to be okay with <em>not</em> learning some new tool. You may have heard the expression "<a href="https://en.wikipedia.org/wiki/Jack_of_all_trades,_master_of_none">Jack of all trades, master of none</a>", which implies superficial knowledge in many things but expertise in none of them. Remember that <strong>you're <em>not</em> obligated to learn everything</strong> and you can excel at your craft without jumping on every bandwagon that rolls up to the curb.</p> <p>On the other hand, <strong>if a tool has gained critical mass <em>and</em> will help you solve a problem you're having, it's worth further exploration</strong>. Don't feel like you have to commit to learning it right away, but it might help to find out a little more and keep an eye on it.</p> <blockquote class="tweet-quote"> <a href="https://twitter.com/intent/tweet?text=&quot;Pick your battles: if a tool has gained critical mass and helps you solve a problem, it's worth exploration.&quot; via @auth0 http://auth0.com/blog/how-to-manage-javascript-fatigue/"> <p>"Pick your battles: if a tool has gained critical mass and helps you solve a problem, it's worth exploration."</p> <p class="tweet-link">TWEET THIS <img src="https://cdn.auth0.com/blog/resources/twitter.svg"></p> </a> </blockquote> <script> $(function() { $('.tweet-quote').on('click', function() { metricsLib.track('blog:share:twitter_quote'); }); }); </script> <h3>Make Something Interesting / Useful</h3> <p>For many developers, there are two primary ways we learn something new in a short amount of time:</p> <ol> <li>We need to learn it in order to complete a project with predefined requirements and a deadline, or:</li> <li>We build something on our own that we're interested in.</li> </ol> <p>Learning anything can be arduous and tedious if we don't have a clear view of the end result or real-world practicality. On the same token, <strong>learning is much more gratifying when we're building something interesting or useful</strong>.</p> <p>One good way to learn new tools and frameworks is to make the same thing (something useful that you like) using different tools. This <a href="https://hackernoon.com/cure-for-js-fatigue-build-something-more-interesting-afaf74b95682#.bi5mnqt96">shouldn't be the ubiquitious and tiresome TODO app</a>. It should be something that covers many common features of modern applications, such as:</p> <ul> <li>Routing</li> <li>Global header and footer</li> <li>CSS framework integration</li> <li>Responsive UI and custom styles</li> <li>Global application data</li> <li>External API</li> <li>Services and utilities</li> </ul> <p>This has several advantages for learning.</p> <ul> <li><strong>Familiarity</strong>: knowing what you're trying to achieve and not making it up as you go along makes development more straightfoward.</li> <li><strong>Comparison</strong>: rebuilding something reveals similarities and differences as well as highlights strengths and weaknesses between frameworks.</li> <li><strong>Iteration</strong>: you may find that each time you go through this exercise, you see things you can refine and improve.</li> </ul> <p>It's important to maintain a high level of interest and/or usefulness with your learning app. Creating a robust starter project can help you quickly learn the ins and outs of setup and common features while providing a practical beginning point for future apps you build.</p> <h3>Be Aware of Common Concepts</h3> <p>Even as JS grows and changes, there are always <a href="https://auth0.com/blog/glossary-of-modern-javascript-concepts">concepts shared amongst many new frameworks and libraries</a>. It's useful to keep an eye out for these tools and topics. For example, <a href="https://auth0.com/blog/a-rundown-of-es6-features">ES6</a> and <a href="https://www.typescriptlang.org/">TypeScript</a> are becoming more heavily used, as well as <a href="https://webpack.github.io/">Webpack</a>, <a href="https://vincenttunru.com/Javascript-reactive-programming/">functional reactive programming</a>, and <a href="https://auth0.com/blog/web-components-how-to-craft-your-own-custom-components/">web components</a>. <strong>Knowing about common dependencies makes different frameworks feel more similar.</strong></p> <p>When you take the plunge with a new framework and toolchain, you'll learn some of the common topics. You'll be pleased to find that other modern frameworks leverage many of the same tools and concepts and are now much easier to pick up.</p> <h3>Learn Iteratively</h3> <p>Many developers are fatigued by the fact that new frameworks have so many complex dependencies that it takes weeks to set up a new app. Don't be afraid to use tools if they help. If a CLI is available or the community offers starter projects, take advantage of them. <strong>Getting off the ground quickly allows you to focus on learning the core features and avoid getting discouraged by difficult setup.</strong></p> <p>It's ideal to know how and why something works so it's less magical, but <a href="https://medium.com/building-kwoosh/you-dont-need-more-knowledge-83c5247e8f60#.yvz0arns4">that <em>doesn't</em> mean you need to frontload that knowledge before getting started</a>. Don't worry if you find yourself picking it up along the way. When you hit a roadblock, work through it. Remember to take breaks if you get frustrated. <strong>"Learn as you go" is a legitimate, effective method for absorbing lots of new information over time.</strong> Once you've done the basics, the <em>how</em> and <em>why</em> reveal themselves, either in "Ah-ha!" moments or gradually with repeated use.</p> <blockquote class="tweet-quote"> <a href="https://twitter.com/intent/tweet?text=&quot;'Learn as you go' is a legitimate, effective way to absorb lots of new information over time.&quot; via @auth0 http://auth0.com/blog/how-to-manage-javascript-fatigue/"> <p>"'Learn as you go' is a legitimate, effective way to absorb lots of new information over time."</p> <p class="tweet-link">TWEET THIS <img src="https://cdn.auth0.com/blog/resources/twitter.svg"></p> </a> </blockquote> <script> $(function() { $('.tweet-quote').on('click', function() { metricsLib.track('blog:share:twitter_quote'); }); }); </script> <h2>Aside: Use Auth0 For Authentication in JS Apps</h2> <p>Taking advantage of knowledge, tools, and solutions from others is extremely valuable when combating JS fatigue. Authentication can be one of the most complex, time-consuming features to build for <em>any</em> application. Developers who are already learning a new toolchain, library, or framework can become even more overwhelmed building secure, complicated features like authentication.</p> <p>If you have a JS app that needs authentication, Auth0 can bear the load for any framework. Auth0's <a href="https://auth0.com/docs/quickstart/spa">Single Page Application QuickStart guides</a> and <a href="https://auth0.com/docs/libraries/auth0js">Auth0 SDK for Web</a> provide indepth documentation for robust identity and user management in JS apps. Auth0 makes authentication straightforward, greatly reducing fatigue and cognitive burden for busy developers.</p> <p>Don't be hesitant to utilize the proper tools and services that will help you do your job and do it well. We're much less fatigued by new things when we have help completing difficult tasks. If authentication is one of your primary needs, you can learn more in the <a href="https://auth0.com/docs">Auth0 docs</a> or <a href="https://auth0.com/signup">sign up for a free account here</a>.</p> <h2>Conclusion</h2> <p>We'll finish with an analogy. If JS is the world around you, there are a few ways to view and take it in.</p> <p>If you look at the JS world through a <strong>telescope</strong>, you can see <em>one thing very clearly</em>. However, you're essentially blind to everything <em>else</em> around you. It's important to be comfortable with your focus, but not to the point that you shut out awareness of any other possibilities.</p> <p>If you view the world as a panorama through a <strong>wide-angle lens</strong>, you get a vast, comprehensive picture but it's hard to know where to look. Everything in the scene competes for your attention and you can get easily distracted when trying to focus if something else catches your eye. This can be exhausting.</p> <p>Now consider a normal <strong>pair of glasses</strong>. You can see everything more clearly, but still focus your attention on one (or a few) things without losing sight of what's in your periphery.</p> <p>When viewing the modern JavaScript landscape, glasses are a good approach. Don't feel like you have to take in all your surroundings at once, but don't blind yourself to the larger world either. Focus your time and effort on what's in front of you while surveying occasionally for potential improvements. Hopefully you'll find yourself feeling more refreshed and enthusiastic about the great things JavaScript has in store for the future.</p> Why Identity Matters for Innovation Labs 2017-03-21T08:30:00+00:00 https://auth0.com/blog/why-identity-matters-for-innovation-labs/ Kim Maida https://twitter.com/KimMaida <p><strong>TL;DR:</strong> Innovation drives technology and <strong>innovation labs</strong> are critical for propelling the technology industry forward. Find out about innovative accomplishments with identity, and why identity matters for innovation labs.</p> <hr /> <h2>What are Innovation Labs?</h2> <p><strong>Innovation labs</strong> are initiatives designed to promote and grow innovative thinking, services, and products. There are many ways that businesses approach the promotion of innovation, including forming strategic units or simply providing avenues for workers to network and collaborate. Some examples of corporate innovation labs include <a href="https://research.google.com/">Research at Google</a>, <a href="https://www.microsoft.com/en-us/research/">Microsoft Research Lab</a>, <a href="https://labs.oracle.com/pls/apex/f?p=labs:15:0">Oracle Labs</a>, <a href="https://i-lab.harvard.edu/">iLab at Harvard</a>, <a href="https://www.cbinsights.com/blog/corporate-innovation-labs/">and more</a>.</p> <p>Innovation labs may have several aims, including but not limited to:</p> <ul> <li><strong>Ideation</strong>: cultivating ideas and collaboration through hackathons, internal proposals, demos, and more.</li> <li><strong>Attracting talent</strong>: companies that stay on the cusp of cutting-edge technology and foster a culture of innovation are more attractive to skilled, prospective employees.</li> <li><strong>Long-term revenue</strong>: new products, services, and other offerings can have substantial long-term returns. In addition, bringing more ideation and production in-house reduces long-term costs.</li> </ul> <h2>Identity Innovation</h2> <p>Innovations in identity technology have led us to more secure and more dynamic tools and practices. Let's examine a few examples.</p> <h3>Frictionless Authentication with Passwordless</h3> <p>The evolution of <a href="https://auth0.com/passwordless">Passwordless authentication</a> has allowed users to leave memorizing complicated passwords behind while enjoying improved security. Companies like <a href="https://slack.com">Slack</a> and <a href="https://medium.com">Medium</a> utilize Passwordless authentication to <a href="https://aws.amazon.com/blogs/startups/increase-engagement-and-enhance-security-with-passwordless-authentication/">increase engagement and enhance security</a>. <a href="https://auth0.com/learn/fingerprint-authentication/">Fingerprint Authentication</a> in mobile apps is also a form of Passwordless login that greatly improves the user experience.</p> <p>In fact, Passwordless biometric security is steadily gaining traction with identity innovations such as the <a href="http://www.hammacher.com/Product/81863">Biometric Wallet from Hammacher Schlemmer</a> and <a href="http://www.sdcexec.com/news/12214482/new-biometric-credit-card-technology-is-an-important-advance-in-fraud-prevention">biometric credit card technology</a>.</p> <h3>Personalization with Identity Data</h3> <p>Data collected from user identity is valuable for increasing ROI by providing a personalized experience to users. Retailers make use of consumer data by providing product suggestions, personalizing ads, and sending personalized emails.</p> <p>For example, <a href="http://www.qubit.com/">Qubit</a> leverages analytics and visitor behavior to tailor e-commerce experiences to each user. Utilizing identity information like the user's location along with data like purchase history, preferences, checkout speed, and more enables highly focused personalization and targeting. About <a href="http://www.marketingcharts.com/online/online-shoppers-prove-receptive-to-retailers-personalization-tactics-27413/">60% of consumers agree that "retailers who personalize their shopping experience make it easier to find the products that are most interesting"</a>.</p> <h3>Using Identity Data to Improve Security</h3> <p>Innovations with identity <em>data</em> have led to greatly enhanced security. <a href="https://auth0.com/learn/anomaly-detection/">Anomaly detection</a> is the identification of unusual data points in a set. For example, if a user normally logs into an application from New York City, USA, a login with the same credentials from Brisbane, Australia is an outlier and could potentially indicate malicious activity. Identity data can be used to detect a multitude of different anomalies, including location, time, <a href="https://en.wikipedia.org/wiki/Brute-force_attack">repeated failed login attempts</a>, authentication from new devices, and much more.</p> <p>When an identity data anomaly has been detected, steps can be taken to mitigate risk. The user can be notified of potentially malicious activity and asked to verify their identity, their account can be frozen in the case of a brute force attack, or their credentials can be reset such as in the case of <a href="https://auth0.com/breached-passwords">breached passwords</a>.</p> <h2>Why Identity Matters for Innovation Labs</h2> <p>Swift development, flexibility, and focus on ideation and growth are vital for innovation labs. When producing an innovative product or application, it's important for innovators to be able to hone their craft and not have to expend hundreds of hours worrying about managing identity and securing authentication.</p> <p>Auth0 is an Identity-as-a-Service (IDaaS) solution that works with any application built on any framework. Auth0 also supports a multitude of identity providers, including popular social platforms like Twitter and Facebook as well as enterprise providers such as Active Directory. Integration is swift and easy, and can be implemented in just a few minutes.</p> <p><img src="https://cdn.auth0.com/blog/innovation-labs/innovation-labs.png" alt="importance of identity for innovation labs" /></p> <blockquote><p><em>"I'm a big proponent of letting experts do what they do best ... I didn't want to rely on building [an identity management solution] ourselves."</em></p> <p>— <em>David Bernick, <a href="https://auth0.com/learn/harvard-medical-school-identity-secures-nih-research/">Harvard Medical School</a></em></p></blockquote> <p>Innovation labs can reap numerous benefits from utilizing Auth0 as an identity management solution, including:</p> <h3>Reduction in Engineering Time and Costs</h3> <p>Auth0 enables easy integration with any application on any framework, be it Node.js, PHP, .NET, Swift, Java, Angular, etc. <a href="https://auth0.com/docs">Extensive documentation</a> and SDKs are available to jumpstart development and reduce the engineering time and effort needed to implement a robust authentication solution. Auth0 integrates with dozens of social and enterprise providers at the flip of a switch, and also supports Single Sign-On with minimal coding.</p> <h3>Flexibility and Extensibility</h3> <p>Auth0's login functionality and fine-grained authorization permissions are easily customized with <a href="https://auth0.com/docs/rules">rules</a>. Numerous extensions are also available for additional features such as logging, GitHub Deployments, and much more. Metadata can be added to users manually or via rules. Even the Auth0 login widget, called <a href="https://auth0.com/lock">Lock</a>, can either be used out-of-the-box, or replaced with a fully customized user interface.</p> <h3>Increased Security</h3> <p>Auth0 supplies Multifactor authentication and Passwordless at the click of a button. The solution also provides highly customizable anomaly detection in addition to breached password and brute force protection. Auth0 is peer reviewed by international security experts and complies with standards such as SAML, OAuth, WS-Federation, and certifications like OpenID Connect, SOC2, HIPAA, etc.</p> <h2>Innovate Without Worrying About Identity</h2> <p>Rapidfire development, excellent flexibility, and reduced time to market are vital for innovation to blossom in the technology industry. Auth0 provides services that enable these fundamental tenets of tech innovation. With Auth0, innovation labs can focus on producing groundbreaking offerings without worrying about authentication security and identity management.</p> Anomaly Detection: Safer Login with ThisData and Auth0 2017-03-20T08:30:00+00:00 https://auth0.com/blog/anomaly-detection-safer-login-with-thisdata-and-auth0/ Nick Malcolm https://twitter.com/nickmalcolm <p><em>Guest post by <a href="https://twitter.com/nickmalcolm">Nick Malcolm</a>, CTO at <a href="https://thisdata.com">ThisData</a></em></p> <p>Anomaly Detection is the process of identifying events which are out of place or unusual. Detecting anomalies in web applications can reveal signs of malicious activity or hackers, and responding to those anomalies automatically helps keep our users safe.</p> <p>A common example is the email you might have gotten from Google or Facebook when you log in from a new computer or location. You usually log in using a MacBook from your beachfront office in Fiji, and now you're logging in from Siberia using Linux. The “was this you?” email is a result of anomaly detection, and in this post we're going to supercharge your Auth0 login process with ThisData's login intelligence to achieve the same results.</p> <p><a href="https://thisdata.com">ThisData</a> gives you real-time detection of account takeover for web and mobile apps. It identifies users based on context and notifies you or your users immediately if an account has been breached, just like Google.</p> <p>In a <a href="https://thisdata.com/blog/auth0-guest-post-adding-thisdata-to-your-auth-process-for-anomaly-detection-2/">previous guest post on the ThisData blog</a> we learned how to use ThisData's anomaly detection rules to stop attackers from logging in to your user's accounts via Auth0.</p> <p>In this post, you’ll learn how to implement <strong>Account Takeover Detection</strong> via ThisData in your Auth0 app in just 6 simple steps.</p> <h2>Let's Get Started</h2> <h3>1. Sign Up for a ThisData Account</h3> <p>Browse to <a href="https://thisdata.com">thisdata.com</a> and create a free 30 day trial account, as shown below.</p> <p><img src="https://cdn.auth0.com/blog/thisdata/1-sign-up.png" alt="Sign up for a ThisData account to implement anomaly detection" /></p> <h3>2. Get Your API Key</h3> <p>In the first step of ThisData's quickstart is your API key. Please make note of it, as you will be needing it later.</p> <p><img src="https://cdn.auth0.com/blog/thisdata/2-get-api-key.png" alt="Get ThisData API key" /></p> <h3>3. Set Up an Auth0 App</h3> <p>In the <a href="https://manage.auth0.com/">Auth0 Dashboard</a>, create a new client and choose Single Page Web Application, as shown in the following screenshot.</p> <p><img src="https://cdn.auth0.com/blog/thisdata/3-1-set-up-auth0-app.png" alt="Set up an Auth0 app client" /></p> <p>Once you’ve created a client, head over to the <strong>Settings</strong> section of the dashboard and take note of your <strong>Domain</strong>, <strong>Client ID</strong>, and <strong>Client Secret</strong> as shown below.</p> <p><img src="https://cdn.auth0.com/blog/thisdata/3-2-auth0-secrets.png" alt="Set up an Auth0 app and grab client information" /></p> <p>Clone <a href="https://github.com/thisdata/auth0-thisdata">this sample app from Github</a>, open up <code>auth0-variables.js</code>, and add your Auth0 credentials like so:</p> <pre><code class="js">var AUTH0_CLIENT_ID='xxxxxxxxxxx'; var AUTH0_DOMAIN='xxxxxxx.auth0.com'; var AUTH0_CALLBACK_URL=location.href; </code></pre> <h3>4. Integrate ThisData</h3> <p>In the Auth0 dashboard, click on the <strong>Rules</strong> section in the main navigation, then click on the <strong>"Create Rule"</strong> button located at the top right of the page.</p> <p><img src="https://cdn.auth0.com/blog/thisdata/4-1-create-rule.png" alt="Create an Auth0 rule to integrate with ThisData" /></p> <p>A list of available rule templates will be presented to you as shown in the diagram below. Choose the <strong>“Account Takeover Detection via ThisData”</strong> rule.</p> <p><img src="https://cdn.auth0.com/blog/thisdata/4-2-thisdata-rule.png" alt="Choose Account Takeover Detection via ThisData rule" /></p> <p>This rule is designed to detect phished or compromised user accounts. Even if the primary user authentication is approved, it will deny access to a user if the login appears to be highly suspicious. It relies on ThisData anomaly detection algorithms which take into account factors like:</p> <ul> <li>Devices</li> <li>Time of the day</li> <li>Tor usage</li> <li>Location &amp; Velocity</li> <li>Risky IP addresses</li> <li>Machine Learning</li> <li>...and much more.</li> </ul> <p>ThisData has a risk score that is attached to every login event. A higher risk score indicates a more significant anomaly was detected. If the risk is high, the user can still log in, but we can also send a notification to their email address to verify it was really them.</p> <blockquote><p>The <strong>"Account Takeover Prevention via ThisData"</strong> rule will <em>block</em> a login attempt if the risk is too high.</p></blockquote> <p>After clicking on the rule, the rule editor will show up. Here, you can see the code that integrates ThisData with your login process. It's nice and simple—it pushes some metadata to ThisData's API when your user logs in.</p> <p><img src="https://cdn.auth0.com/blog/thisdata/4-3-rule.png" alt="Auth0 rule editor" /></p> <p>Get your ThisData API key and paste it in the <strong>Settings</strong> section, as shown in the following screenshot. The rule will have access to it as an environment variable.</p> <p><img src="https://cdn.auth0.com/blog/thisdata/4-4-configure-variables.png" alt="Paste ThisData API key into Auth0 rule settings" /></p> <h3>5. Turn on Notifications</h3> <p>Turning on notifications is optional, but awesome! Notifications help your users take action when their account is attacked.</p> <p>Head over to your ThisData account and browse to <strong>API Settings</strong>. In the sidebar, click <strong>User Notifications</strong>. Click the checkbox next to <strong>Send email</strong> to turn on end user notifications.</p> <p><img src="https://cdn.auth0.com/blog/thisdata/5-1-notifications.png" alt="Turn on user notification emails in ThisData" /></p> <p>You can also upload your company logo here, or enable Slack notifications by clicking <strong>Integrations</strong> in the sidebar.</p> <h3>6. Run &amp; Test Your App</h3> <p>Now let's run our sample Auth0 app and see how it all works.</p> <blockquote><p>On a mac you can run the app by typing <code>python -m SimpleHTTPServer 8000</code> in the command line.</p></blockquote> <p>Open up your browser and run the app like so:</p> <p><img src="https://cdn.auth0.com/blog/thisdata/6-1-run-test-app.png" alt="Run app in browser" /></p> <p>Log into your application, and then head over to the ThisData website. You will see the recorded login event with an associated risk score, as follows:</p> <p><img src="https://cdn.auth0.com/blog/thisdata/6-2-thisdata-dashboard.png" alt="ThisData login event risk score" /></p> <p>If there is irregular activity like a sudden change in device or location, accessing the website at an unusual time, using Tor, or other anomalies, then your user will receive an email like this:</p> <p><img src="https://cdn.auth0.com/blog/thisdata/6-3-email-notification.png" alt="Email notification from anomaly detection with ThisData" /></p> <p>And your Slack channel might look like this:</p> <p><img src="https://cdn.auth0.com/blog/thisdata/6-4-slack-notification.png" alt="Slack notification from anomaly detection with ThisData" /></p> <p>In the example above, the user was immediately notified of suspicious access to their account. They then responded by clicking <strong>"No it wasn't [me]"</strong> in the email. The initial alert and the response are also visible to your ops team in Slack.</p> <p>You can configure ThisData to take automated action too—learn how by reading <a href="http://help.thisdata.com/docs/create-a-security-workflow-with-thisdatas-alert-webhooks">"Create a security workflow with Alert Webhooks"</a> in ThisData's documentation.</p> <h2>Conclusion</h2> <p>It is super simple to integrate ThisData into your authentication process when building an app that uses Auth0. ThisData allows you to detect login anomalies to better protect your users and your app from cyber-criminals.</p> <p>Cyber-attacks are on the rise, so taking these simple security precautions helps ensure that your users and apps are safe. Make your applications more secure today with ThisData and Auth0!</p> Analyzing Identity in Movies 2017-03-17T08:30:00+00:00 https://auth0.com/blog/analyzing-identity-in-movies/ Martin Gontovnikas http://twitter.com/mgonto <p><strong>TL;DR:</strong> As technology becomes more advanced, movies are predictors of how our identity will be utilized.</p> <hr /> <p>Our relationship with technology is constantly evolving. Whether it's an app to help manage our daily activities or the latest tech device, technology is changing on a day-to-day basis to adapt to our needs. These advances are making our lives easier and more productive.</p> <p>To that end, there's no shortage of movies that explore the role technology will play in the future. But when we take a minute to separate the fact from fiction, what are we left with? What do these movies tell us about what's to come?</p> <p>Even more intriguing, what do these movies tell us about how our identities will mold the future? How will our identities become even more important than they are today?</p> <p>To answer these questions, we examined three movies that explore identity in the future and examined how their assumptions might be closer to reality than we think. Let's take a closer look.</p> <h2><em>Minority Report</em>: Identity and Data Collection</h2> <p>The 2002 film <em>Minority Report</em> paints an intriguing picture of America in the 2050s. A system using a combination of biometric surveillance and psychics called “Precogs” has been developed to apprehend potential murderers. As a result of capturing criminals before they act, the crime rate plummets to zero.</p> <p>The film focuses on Captain John Anderton, a PreCrime police officer, as he attempts to outrun the law after the Precogs predict <em>he'll</em> murder someone. His attempts to elude the authorities is hampered by the fact that public spaces are brimming with retinal scanners. His only option to evade capture and hide his identity is to have his eyes surgically replaced by an underground doctor.</p> <p>What makes the use of identity in this film interesting is the use of biometric data collection to generate holographic ads for individual retail customers. When Anderton enters a Gap store, he's greeted as “Mr. Nakamura”, who we can assume was the former owner of the transplanted eyes.</p> <p><img src="https://cdn.auth0.com/blog/id-in-movies/minority-report.jpeg" alt="Minority Report and its take on identity and data collection" /> <a href="https://www.psychologytoday.com/blog/side-effects/201511/the-biological-citizen-neuropolitics-aim-and-danger">Source</a></p> <p>This extensive use of one's identity in the future will give retailers the opportunity to provide highly sophisticated and personalized advertising experiences. Only ads that cater to you as an individual—rather than to your demographic—would be presented. In the case of <em>Minority Report</em>, <a href="https://auth0.com/blog/machine-learning-for-everyone/">predictive analysis</a> based on historical purchases is used to enhance marketing and advertising strategies by singling out customers.</p> <p>How do we know identity will be used this way in the future? It's already happening. For <a href="http://mail.google.com">Gmail</a> users, inboxes have become a hotspot for ads. Based on the sites users have visited and the types of emails received, inbox ads become increasingly more targeted.</p> <p><img src="https://cdn.auth0.com/blog/id-in-movies/gmail.png" alt="Gmail" /> <a href="http://www.ppchero.com/your-guide-to-setting-up-gmail-ads/">Source</a></p> <p>Gone are the days of zero targeting, when everyone was served the same ads. Customers had no choice but to listen because there were only a handful of TV stations, newspapers, and magazines to choose from.</p> <p>If <em>Minority Report</em> is any indication of what we can expect, ads of the future will be more important for the simple fact that they'll be even more personalized and targeted to individuals. Marketers can focus on specific categories and not just general characteristics of a much broader target audience.</p> <h2><em>Her</em>: Identity and Personalized Experiences</h2> <p>In the 2013 film <em>Her</em>, Theodore Twombly is a lonely, recent divorcee. In an attempt to soothe his growing depression, he purchases an artificial intelligence personal assistant. Because of its ability to adapt based on interactions, it gives itself the name “Samantha,” and he falls in love with it. Or rather, he falls in love with the illusion of the type of relationship he desperately needs.</p> <p>The film explores how this growing relationship provides him with the support and understanding he's been unable to achieve with other people.</p> <p>While the film takes place in the future, we're shown how technology can blend seamlessly into our lives and adapt to our preferences.</p> <p><img src="https://cdn.auth0.com/blog/id-in-movies/her.jpg" alt="Her, Spike Jonze, and identity and personlized experiences" /> <a href="http://cinemavine.com/movie-stills-of-the-day-spike-jonzes-her/">Source</a></p> <p>Although the concept of developing an emotional relationship with technology seems far-fetched, we already see hints of a deepening bond as technology becomes increasingly more integrated with our day-to-day lives. There's Google Home, Amazon's Alexa, and Apple's Siri. As the Internet of Things takes off, we're going to see more of this type of integration of technology into our everyday lives. And we'll probably also see more <a href="https://www.youtube.com/watch?v=EDvnnifS858&amp;feature=player_embedded">parents using it to troll their kids</a>.</p> <p>This technology is different from anything that's preceded it because it's designed to understand our identity and utilize that understanding to reduce our need to go out and find information ourselves. Google has taken this concept and created products that enable us to seek and find the information we need faster.</p> <p>This enhanced user experience means that we're getting information before we even search for it. Take Google Now for instance. It provides users with recommendations based on usage.</p> <p>Technology is moving in this direction as it becomes less of a focal point in our lives and begins to recede into the background. With Google Home, users can simply verbalize what they're looking for, thereby reducing any friction that may prevent them from satisfying their immediate needs. Google Home optimizes user experience by relying on their identity and specific preferences.</p> <p><img src="https://cdn.auth0.com/blog/id-in-movies/google-home.png" alt="Google Home" /> <a href="https://www.engadget.com/2016/05/18/google-home-virtual-assistant/">Source</a></p> <p>Similar to the movie <em>Her</em>, users can interact with Google Home to give the illusion of a two-way conversation. With this shift, identity becomes more important as our technology learns more about us than anyone else, thereby reducing our need to go out and find information for ourselves.</p> <h2><em>Gattaca</em>: Identity and Biometric Identification</h2> <p>In the movie <em>Gattaca,</em> genetic engineering and state-sanctioned eugenics are used to determine a person's propensity to excel or fail. This approach divides society into two groups, essentially the “haves” (valids) and the “haves-not” (in-valids).</p> <p>Vincent Freeman is deemed an in-valid because he's conceived naturally without the use of genetic selection. Despite his genetic “inferiority”, he's determined to become an astronaut.</p> <p>In order to mask his true genetics, he uses the identity (blood, skin, hair, eyelashes, urine, and saliva) of a paralyzed man—a valid—by falsifying a finger-prick blood test to gain access to opportunities that would typically be out of reach.</p> <p><img src="https://cdn.auth0.com/blog/id-in-movies/gattaca.jpg" alt="Gattaca biometrics identity fingerprint and prick" /></p> <p><a href="http://biometrics.mainguet.org/movies/Gattaca_fake_blood_sample.jpg">Source</a></p> <p>Despite the obvious physical differences between Vincent and Jerome, we're shown that genetics take precedence. In other words, identity is authenticated by biometrics.</p> <p><img src="https://cdn.auth0.com/blog/id-in-movies/gattaca-test.jpg" alt="Gattaca biometrics blood test" /> <a href="http://brainknowsbetter.com/news?offset=1359840646311">Source</a></p> <p>Though <em>Gattaca</em> was based on fiction, there's now an increased reliance on the use of <a href="https://auth0.com/blog/analysis-of-passwordless-connections/">biometric identification</a> to determine what access people should have. Most cell phones come equipped with face recognition software or fingerprint encryption to unlock them.</p> <p>A sufficiently motivated hacker is going to be able to break biometrics because since it's not based on any inherent aspect of your body but rather on a digitized version of your identity, it can be misused. In other words, your fingerprint is really being stored as a digital image.</p> <p><img src="https://cdn.auth0.com/blog/id-in-movies/fingerprint.png" alt="Passwordless login with biometric fingerprint TouchID" /> <a href="https://mic.com/articles/149860/our-fingerprints-are-portals-into-our-digital-lives-but-the-laws-haven-t-caught-up">Source</a></p> <p>Every time you put your finger on the sensor, it's producing a different image. Because you always put your finger on a different part of the sensor, the digital image needs to be flexible enough to account for that fact.</p> <p>Fortunately, we keep our customers up to date on the <a href="https://hacked.com/auth0-integrates-identity-authentication-interview/">latest changes in cybersecurity</a>, thereby making sure their identity is always safe.</p> <p>As <em>Gattaca</em> demonstrates, as we move into a world that relies more on biometric identity, we have to understand that we can't be so stringent with what determines personal identity and resilience. If not managed properly, authentication procedures have the potential to create biased class systems or categories.</p> <h2>“The Future is Already Here”</h2> <p>As we continue to see advancements in technology, we should prepare ourselves for even more impressive leaps forward. With more access to our identities and with the development of progressive systems, the seeds of advancement have been sown.</p> <p>As our daily interaction with technology grows, it's important to remember that the need for identity metrics will also increase. Allowing companies to learn more about us enables more personalized experiences. With less effort on our part, service providers and retailers have clear insight into our needs and wants.</p> <p>This, in turn, allows for more technology to integrate into our lives. Technology then acts more as a companion, rather than simple tools to do our bidding. Algorithms will give our technology more indication into who we truly are at our core.</p> <p>To quote science fiction writer William Gibson, <em>“the future is already here.”</em></p> Web Components: How To Craft Your Own Custom Components 2017-03-16T08:30:00+00:00 https://auth0.com/blog/web-components-how-to-craft-your-own-custom-components/ Prosper Otemuyiwa https://twitter.com/unicodeveloper <hr /> <p><strong>TL;DR</strong> The introduction of <em>Web Components</em> have given developers super powers. With <em>Web Components</em>, web designers and developers are no longer limited to the existing HTML tags that existing browser vendors provide. Developers now have the ability to create new custom HTML tags, enhance existing HTML tags or extend components that developers around the world have created. In this article, I'll show you how to use and create custom web components for your apps.</p> <hr /> <p>Web components allow for reusability and the ability to associate JS behaviour with your markup. Developers can search for existing components created by other developers on the <a href="https://www.webcomponents.org">web components registry</a>. In the absence of suitable existing custom elements, developers can create theirs and make it available for others by publishing it to the registry.</p> <h2>What are Web Components?</h2> <p>Web components are a set of web platform APIs that allow you to create new custom, reusable, encapsulated HTML tags to use in web pages and web apps. They are reusable widgets that are built on the Web Component standards. Web Components work across modern browsers and can be used with any JavaScript library or framework that utilizes HTML.</p> <p>There are some sets of rules and specifications that you need to follow to develop web components. These specifications are classified into four categories:</p> <ul> <li>Custom Elements</li> <li>Shadow DOM</li> <li>HTML Imports</li> <li>HTML Template</li> </ul> <p>We'll talk about these specifications in the latter part of this post. But let's quickly learn how to use web components.</p> <h2>How to use Web Components</h2> <p>The first step is to browse the <a href="https://www.webcomponents.org">element registry</a>. Check for the components that you are interested in, then go through the README to know how to import it and use in your web applications.</p> <p>The web component registry has two main sections:</p> <ul> <li><a href="https://www.webcomponents.org/elements">elements</a>: These are custom elements in the registry.</li> <li><a href="https://www.webcomponents.org/collections">collections</a>: These are sets of custom elements. An example is the <a href="https://www.webcomponents.org/collection/StartPolymer/awesome-chart-elements">awesome-chart-elements collection</a> that contains eight awesome elements for working with charts in a web app.</li> </ul> <p>An example web component you can install is <a href="https://www.webcomponents.org/element/Juicy/juicy-ace-editor">juicy-ace-editor</a>. You can install it by following these processes:</p> <p>Make sure you have <a href="https://bower.io">bower</a> installed, else run:</p> <pre><code class="bash">npm install -g bower </code></pre> <p>Now install the <code>ace-editor</code> component like so:</p> <pre><code class="bash">bower install juicy-ace-editor --save </code></pre> <p>Create an <code>index.html</code> file and import the <code>juicy-ace-editor</code> component like this:</p> <pre><code class="js">&lt;link rel="import" href="bower_components/juicy-ace-editor/juicy-ace-editor.html"&gt; </code></pre> <p>and place the component on the page like this:</p> <pre><code class="js"> &lt;juicy-ace-editor theme="ace/theme/monokai" mode="ace/mode/javascript"&gt;&lt;/juicy-ace-editor&gt; </code></pre> <p>This is an example of the component in the <code>index.html</code> file.</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="cp">&lt;!DOCTYPE html&gt;</span> <span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">&quot;en&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;head&gt;</span> <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">&quot;UTF-8&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;title&gt;</span>Document<span class="nt">&lt;/title&gt;</span> <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;bower_components/webcomponentsjs/webcomponents.min.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span> <span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;import&quot;</span> <span class="na">href=</span><span class="s">&quot;bower_components/juicy-ace-editor/juicy-ace-editor.html&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;style </span><span class="na">type=</span><span class="s">&quot;text/css&quot;</span><span class="nt">&gt;</span> <span class="nf">#editor-container</span> <span class="p">{</span> <span class="k">position</span><span class="o">:</span> <span class="k">absolute</span><span class="p">;</span> <span class="k">top</span><span class="o">:</span> <span class="m">0px</span><span class="p">;</span> <span class="k">left</span><span class="o">:</span> <span class="m">280px</span><span class="p">;</span> <span class="k">bottom</span><span class="o">:</span> <span class="m">0px</span><span class="p">;</span> <span class="k">right</span><span class="o">:</span> <span class="m">0px</span><span class="p">;</span> <span class="k">background</span><span class="o">:</span> <span class="nb">white</span><span class="p">;</span> <span class="p">}</span> <span class="nt">&lt;/style&gt;</span> <span class="nt">&lt;/head&gt;</span> <span class="nt">&lt;body&gt;</span> <span class="nt">&lt;juicy-ace-editor</span> <span class="na">id=</span><span class="s">&quot;editor-container&quot;</span> <span class="na">theme=</span><span class="s">&quot;ace/theme/monokai&quot;</span> <span class="na">mode=</span><span class="s">&quot;ace/mode/javascript&quot;</span><span class="nt">&gt;</span> var User = require(&#39;./controllers/user.server.controller&#39;), Notification = require(&#39;./controllers/notification.server.controller&#39;); module.exports = function(app) { app.get(&#39;/api&#39;, User.welcome); app.post(&#39;/api/users&#39;, User.createNewUser); app.delete(&#39;/api/user/:user_id&#39;, User.deleteOneUser); app.post(&#39;/api/notify&#39;, Notification.notifyUsers); }; <span class="nt">&lt;/juicy-ace-editor&gt;</span> <span class="nt">&lt;/body&gt;</span> <span class="nt">&lt;/html&gt;</span></code></pre></div> <p>In the code above, we referenced a script:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;bower_components/webcomponentsjs/webcomponents.min.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span></code></pre></div> <p>The <code>Webcomponentjs</code> file is the Web components' polyfill for browsers that don't support web components yet.</p> <p>When you check out your browser, this is how your page will look like:</p> <p><img src="https://cdn.auth0.com/blog/webcomponent/editor.png" alt="Webcomponent Juicy Editor" /></p> <p>Follow the <a href="https://github.com/juicy/juicy-ace-editor">documentation here</a> to install and run it in your web browser.</p> <p>It is that simple. Now we have a code editor in our browser by just importing a <em>Web Component</em>. Whoop! Whoop!</p> <p>Now, let's go through the <em>Web Components</em> specifications in order to know how to create a custom component, starting from <code>Custom Elements</code>.</p> <h2>How to create Web Components</h2> <h3>Custom Elements</h3> <p>This is a web component specification that defines how to craft and use new types of DOM elements. There are some ground rules on how to name and define your custom elements. They are:</p> <ul> <li><p>The name of your custom element must contain a <strong>dash (-)</strong>. For example, <code>&lt;file-reader&gt;</code>, and <code>&lt;skype-login&gt;</code> are valid names for custom elements, while <code>&lt;skype_login&gt;</code>, and <code>&lt;skypelogin&gt;</code> are not. This is necessary in order to allow the HTML parser differentiate between a custom element and an inbuilt HTML element.</p></li> <li><p>A custom element can't be registered more than once. A <code>DOMException</code> error will be thrown if you do so.</p></li> <li>A custom element can't be self-closing. For example, you can't write a custom element like this: <code>&lt;skype-login /&gt;</code>. It should always be written like this: <code>&lt;skype-login&gt;&lt;/skype-login&gt;</code>.</li> </ul> <p>A custom element can be created using the <code>customElements.define()</code> browser API method and a class that extends <code>HTMLElement</code> in JavaScript like so:</p> <pre><code class="js"> class FileBag extends HTMLElement { // Define behavior here } window.customElements.define('file-bag', FileBag); </code></pre> <p>Another option is to use an anonymous class like so:</p> <pre><code class="js">window.customElements.define('file-bag', class extends HTMLElement { // Define behaviour here }); </code></pre> <p>With this already defined, you can now use the custom element in a web page like so:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;file-bag&gt;&lt;/file-bag&gt;</span></code></pre></div> <p>You can define properties on a customElement. For instance, let's add an attribute called <code>open</code> to our <code>&lt;file-bag&gt;</code> element. This can be achieved like so:</p> <pre><code class="js">class FileBag extends HTMLElement { // Set the "open" property set open(option) { this.setAttribute("open", option); } // Get the "open" property get open() { return this.hasAttribute("open"); } } </code></pre> <blockquote><p><strong>this</strong> refers to the DOM element itself. So in this example, <strong>this</strong> refers to <code>&lt;file-bag&gt;</code>.</p></blockquote> <p>Once you have done this, you can now use the custom element in your browser like this:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;file-bag</span> <span class="na">open=</span><span class="s">&quot;true&quot;</span><span class="nt">&gt;&lt;/file-bag&gt;</span></code></pre></div> <p><strong>Note:</strong> You can also define a constructor in the class, but you have to call the <code>super()</code> method just before adding any other piece of code.</p> <p>There are lifecycle hooks that custom elements can define during their existence. These hooks are:</p> <ul> <li><strong>constructor():</strong> Here, you can attach event listeners and initialize state.</li> <li><strong>connectedCallback():</strong> Called whenever the custom element is inserted into the DOM.</li> <li><strong>disconnectedCallback():</strong> Called whenever the custom element is removed from the DOM.</li> <li><strong>attributeChangedCallback(attrName, oldVal, newVal):</strong> Called whenever an attribute is added, removed or updated. Only attributes listed in the <strong>observedAttributes</strong> property are affected.</li> <li><strong>adoptedCallback():</strong> Called whenever the custom element has been moved into a new document.</li> </ul> <p>You can reference the <a href="https://w3c.github.io/webcomponents/spec/custom">custom element specification</a> for a lot more information.</p> <h3>Shadow DOM</h3> <p>This is a powerful API to combine with custom elements. It provides encapsulation by hiding DOM subtrees under shadow roots. You can use <strong>Shadow DOM</strong> in a custom element like so:</p> <pre><code class="js">window.customElements.define('file-bag', class extends HTMLElement { constructor() { super(); var shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.innerHTML = `&lt;strong&gt;Shadow dom super powers for the win!&lt;/strong&gt;`; } }); </code></pre> <p>So when you call <code>&lt;file-bag&gt;&lt;p&gt;This is a file bag &lt;/p&gt;&lt;/file-bag&gt;</code> in the browser, it will be rendered like so:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;file-bag&gt;</span> <span class="nt">&lt;strong&gt;</span>Shadow dom super powers for the win!<span class="nt">&lt;/strong&gt;</span> <span class="nt">&lt;/file-bag&gt;</span></code></pre></div> <p>The main idea behind <em>Shadow DOM</em> is to mask all of the markup behind a custom element in the shadows. If you inspect the element in the browser, you won't see any of the markup apart from the attributes of the element. They are hidden under shadow roots. Browser vendors have been using <em>Shadow DOM</em> for years to natively implement elements such as <code>&lt;input&gt;</code>, <code>&lt;audio&gt;</code>, <code>&lt;video&gt;</code> and many others. Another benefit is that all the styling and scripts inside the custom element won't accidentally leak out and affect anything else on the page.</p> <p>You can reference the <a href="https://w3c.github.io/webcomponents/spec/shadow/">shadow DOM specification</a> for a lot more information.</p> <h3>HTML Imports</h3> <p>HTML Imports are a way to include and reuse HTML documents in other HTML documents. The <code>import</code> keyword is assigned to the <code>rel</code> attribute of the <code>link</code> element like so:</p> <pre><code class="js">&lt;link rel="import" href="/imports/file-reader.html"&gt; </code></pre> <p>You can reference the <a href="https://w3c.github.io/webcomponents/spec/imports">HTML Imports</a> for a lot more information.</p> <h3>HTML Template</h3> <p>This is a web component specification that defines how to declare pieces of markup at page load.</p> <p>The <code>&lt;template&gt;</code> tag is placed within the web component. You can write HTML and CSS code within this tag to define how you want the component to be presented in the browser.</p> <p>You can reference the <a href="https://html.spec.whatwg.org/multipage/webappapis.html#scripting">HTML Template</a> specification for a very detailed information on templating.</p> <h2>Build a Vimeo Embed Web Component</h2> <p>We'll build a web component that will allow users embed vimeo videos into their apps easily. Let's get started.</p> <p>Create a new HTML file, <code>video-embed.html</code>. Define the HTML Template markup like so:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- Defines element markup --&gt;</span> <span class="nt">&lt;template&gt;</span> <span class="nt">&lt;style&gt;</span> <span class="nc">.vimeo</span> <span class="p">{</span> <span class="k">background-color</span><span class="o">:</span> <span class="m">#000</span><span class="p">;</span> <span class="k">margin-bottom</span><span class="o">:</span> <span class="m">30px</span><span class="p">;</span> <span class="k">position</span><span class="o">:</span> <span class="k">relative</span><span class="p">;</span> <span class="k">padding-top</span><span class="o">:</span> <span class="m">56.25%</span><span class="p">;</span> <span class="k">overflow</span><span class="o">:</span> <span class="k">hidden</span><span class="p">;</span> <span class="k">cursor</span><span class="o">:</span> <span class="k">pointer</span><span class="p">;</span> <span class="p">}</span> <span class="nc">.vimeo</span> <span class="nt">img</span> <span class="p">{</span> <span class="k">width</span><span class="o">:</span> <span class="m">100%</span><span class="p">;</span> <span class="k">top</span><span class="o">:</span> <span class="m">-16.82%</span><span class="p">;</span> <span class="k">left</span><span class="o">:</span> <span class="m">0</span><span class="p">;</span> <span class="k">opacity</span><span class="o">:</span> <span class="m">0</span><span class="o">.</span><span class="m">7</span><span class="p">;</span> <span class="p">}</span> <span class="nc">.vimeo</span> <span class="nc">.play-button</span> <span class="p">{</span> <span class="k">width</span><span class="o">:</span> <span class="m">90px</span><span class="p">;</span> <span class="k">height</span><span class="o">:</span> <span class="m">60px</span><span class="p">;</span> <span class="k">background-color</span><span class="o">:</span> <span class="m">#333</span><span class="p">;</span> <span class="n">box</span><span class="o">-</span><span class="n">shadow</span><span class="o">:</span> <span class="m">0</span> <span class="m">0</span> <span class="m">30px</span> <span class="n">rgba</span><span class="p">(</span> <span class="m">0</span><span class="o">,</span><span class="m">0</span><span class="o">,</span><span class="m">0</span><span class="o">,</span><span class="m">0</span><span class="o">.</span><span class="m">6</span> <span class="p">);</span> <span class="k">z-index</span><span class="o">:</span> <span class="m">1</span><span class="p">;</span> <span class="k">opacity</span><span class="o">:</span> <span class="m">0</span><span class="o">.</span><span class="m">8</span><span class="p">;</span> <span class="k">border</span><span class="o">-</span><span class="n">radius</span><span class="o">:</span> <span class="m">6px</span><span class="p">;</span> <span class="p">}</span> <span class="nc">.vimeo</span> <span class="nc">.play-button</span><span class="nd">:before</span> <span class="p">{</span> <span class="k">content</span><span class="o">:</span> <span class="s2">&quot;&quot;</span><span class="p">;</span> <span class="k">border-style</span><span class="o">:</span> <span class="k">solid</span><span class="p">;</span> <span class="k">border-width</span><span class="o">:</span> <span class="m">15px</span> <span class="m">0</span> <span class="m">15px</span> <span class="m">26.0px</span><span class="p">;</span> <span class="k">border-color</span><span class="o">:</span> <span class="k">transparent</span> <span class="k">transparent</span> <span class="k">transparent</span> <span class="m">#fff</span><span class="p">;</span> <span class="p">}</span> <span class="nc">.vimeo</span> <span class="nt">img</span><span class="o">,</span> <span class="nc">.vimeo</span> <span class="nc">.play-button</span> <span class="p">{</span> <span class="k">cursor</span><span class="o">:</span> <span class="k">pointer</span><span class="p">;</span> <span class="p">}</span> <span class="nc">.vimeo</span> <span class="nt">img</span><span class="o">,</span> <span class="nc">.vimeo</span> <span class="nt">iframe</span><span class="o">,</span> <span class="nc">.vimeo</span> <span class="nc">.play-button</span><span class="o">,</span> <span class="nc">.vimeo</span> <span class="nc">.play-button</span><span class="nd">:before</span> <span class="p">{</span> <span class="k">position</span><span class="o">:</span> <span class="k">absolute</span><span class="p">;</span> <span class="p">}</span> <span class="nc">.vimeo</span> <span class="nc">.play-button</span><span class="o">,</span> <span class="nc">.vimeo</span> <span class="nc">.play-button</span><span class="nd">:before</span> <span class="p">{</span> <span class="k">top</span><span class="o">:</span> <span class="m">50%</span><span class="p">;</span> <span class="k">left</span><span class="o">:</span> <span class="m">50%</span><span class="p">;</span> <span class="n">transform</span><span class="o">:</span> <span class="n">translate3d</span><span class="p">(</span> <span class="m">-50%</span><span class="o">,</span> <span class="m">-50%</span><span class="o">,</span> <span class="m">0</span> <span class="p">);</span> <span class="p">}</span> <span class="nc">.vimeo</span> <span class="nt">iframe</span> <span class="p">{</span> <span class="k">height</span><span class="o">:</span> <span class="m">100%</span><span class="p">;</span> <span class="k">width</span><span class="o">:</span> <span class="m">100%</span><span class="p">;</span> <span class="k">top</span><span class="o">:</span> <span class="m">0</span><span class="p">;</span> <span class="k">left</span><span class="o">:</span> <span class="m">0</span><span class="p">;</span> <span class="p">}</span> <span class="nt">&lt;/style&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;vimeo&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;play-button&quot;</span><span class="nt">&gt;&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/template&gt;</span></code></pre></div> <p>We have also added CSS style to the <code>template</code> tag to define the styling of the <code>vimeo-embed</code> component.</p> <p>The next step is to actually create the custom element. Now add a <code>&lt;script&gt;</code> tag just after the <code>&lt;template&gt;</code> tag and create it like so:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;script&gt;</span> <span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nb">window</span><span class="p">,</span> <span class="nb">document</span><span class="p">,</span> <span class="kc">undefined</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Refers to the &quot;importer&quot;, which is index.html</span> <span class="kd">var</span> <span class="nx">thatDoc</span> <span class="o">=</span> <span class="nb">document</span><span class="p">;</span> <span class="c1">// Refers to the &quot;importee&quot;, which is vimeo-embed.html</span> <span class="kd">var</span> <span class="nx">thisDoc</span> <span class="o">=</span> <span class="p">(</span><span class="nx">thatDoc</span><span class="p">.</span><span class="nx">_currentScript</span> <span class="o">||</span> <span class="nx">thatDoc</span><span class="p">.</span><span class="nx">currentScript</span><span class="p">).</span><span class="nx">ownerDocument</span><span class="p">;</span> <span class="c1">// Gets content from &lt;template&gt;.</span> <span class="kd">var</span> <span class="nx">template</span> <span class="o">=</span> <span class="nx">thisDoc</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span> <span class="s1">&#39;template&#39;</span> <span class="p">).</span><span class="nx">content</span><span class="p">;</span> <span class="c1">// Shim Shadow DOM styles if needed</span> <span class="k">if</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">ShadowDOMPolyfill</span><span class="p">)</span> <span class="p">{</span> <span class="nx">WebComponents</span><span class="p">.</span><span class="nx">ShadowCSS</span><span class="p">.</span><span class="nx">shimStyling</span><span class="p">(</span><span class="nx">template</span><span class="p">,</span> <span class="s1">&#39;vimeo&#39;</span><span class="p">);</span> <span class="p">}</span> <span class="kr">class</span> <span class="nx">VimeoEmbed</span> <span class="kr">extends</span> <span class="nx">HTMLElement</span> <span class="p">{</span> <span class="nx">constructor</span><span class="p">()</span> <span class="p">{</span> <span class="kr">super</span><span class="p">();</span> <span class="kd">var</span> <span class="nx">shadowRoot</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">attachShadow</span><span class="p">({</span><span class="nx">mode</span><span class="o">:</span><span class="s1">&#39;open&#39;</span><span class="p">});</span> <span class="c1">// Adds a template clone into shadow root.</span> <span class="kd">var</span> <span class="nx">clone</span> <span class="o">=</span> <span class="nx">thatDoc</span><span class="p">.</span><span class="nx">importNode</span><span class="p">(</span> <span class="nx">template</span><span class="p">,</span> <span class="kc">true</span> <span class="p">);</span> <span class="nx">shadowRoot</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span> <span class="nx">clone</span> <span class="p">);</span> <span class="kd">var</span> <span class="nx">embed</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span> <span class="s2">&quot;embed&quot;</span> <span class="p">);</span> <span class="kd">var</span> <span class="nx">video</span> <span class="o">=</span> <span class="nx">shadowRoot</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span> <span class="s2">&quot;.vimeo&quot;</span> <span class="p">);</span> <span class="k">this</span><span class="p">.</span><span class="nx">createAndPlay</span><span class="p">(</span> <span class="nx">embed</span><span class="p">,</span> <span class="nx">video</span> <span class="p">);</span> <span class="p">}</span> <span class="nx">createAndPlay</span><span class="p">(</span><span class="nx">embedID</span><span class="p">,</span> <span class="nx">videoElem</span><span class="p">)</span> <span class="p">{</span> <span class="nx">videoElem</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span> <span class="s2">&quot;click&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="kd">var</span> <span class="nx">iframe</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span> <span class="s2">&quot;iframe&quot;</span> <span class="p">);</span> <span class="nx">iframe</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span> <span class="s2">&quot;frameborder&quot;</span><span class="p">,</span> <span class="s2">&quot;0&quot;</span> <span class="p">);</span> <span class="nx">iframe</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span> <span class="s2">&quot;allowfullscreen&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span> <span class="p">);</span> <span class="nx">iframe</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span> <span class="s2">&quot;webkitallowfullscreen&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span> <span class="p">);</span> <span class="nx">iframe</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span> <span class="s2">&quot;mozallowfullscreen&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span> <span class="p">);</span> <span class="nx">iframe</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span> <span class="s2">&quot;src&quot;</span><span class="p">,</span> <span class="s2">&quot;https://player.vimeo.com/video/&quot;</span> <span class="o">+</span> <span class="nx">embedID</span> <span class="o">+</span> <span class="s2">&quot;?autoplay=1&quot;</span> <span class="p">);</span> <span class="nx">iframe</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span> <span class="s2">&quot;width&quot;</span><span class="p">,</span> <span class="s2">&quot;640&quot;</span><span class="p">);</span> <span class="nx">iframe</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span> <span class="s2">&quot;height&quot;</span><span class="p">,</span> <span class="s2">&quot;360&quot;</span><span class="p">);</span> <span class="k">this</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span><span class="p">;</span> <span class="k">this</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span> <span class="nx">iframe</span> <span class="p">);</span> <span class="p">});</span> <span class="p">}</span> <span class="p">}</span> <span class="nb">window</span><span class="p">.</span><span class="nx">customElements</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="s1">&#39;vimeo-embed&#39;</span><span class="p">,</span> <span class="nx">VimeoEmbed</span><span class="p">);</span> <span class="p">})(</span><span class="nb">window</span><span class="p">,</span> <span class="nb">document</span><span class="p">);</span> <span class="nt">&lt;/script&gt;</span></code></pre></div> <p>We have the <code>constructor</code> and <code>createAndPlay</code> method. As I mentioned earlier, the constructor initializes state in the custom element. So, we implemented the <em>Shadow DOM</em> and called the <code>createAndPlay</code> method in the constructor.</p> <p>In the <code>createAndPlay</code> method, we simply added a <code>click</code> eventlistener and used JavaScript to create an iframe and set the required attributes.</p> <p>Finally we called <code>window.customElements.define('vimeo-embed', VimeoEmbed);</code> to attach the <code>VimeoEmbed</code> class to <code>vimeo-embed</code> custom tag.</p> <h3>HTML Import</h3> <p>Create an <code>index.html</code> file. Go ahead and import the <code>vimeo-embed.html</code> file in it like so:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="cp">&lt;!doctype html&gt;</span> <span class="nt">&lt;html&gt;</span> <span class="nt">&lt;head&gt;</span> <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">&quot;utf-8&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;title&gt;</span>Vimeo Embed<span class="nt">&lt;/title&gt;</span> <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;./bower_components/webcomponentsjs/webcomponents.min.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span> <span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;import&quot;</span> <span class="na">href=</span><span class="s">&quot;vimeo-embed.html&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;style </span><span class="na">type=</span><span class="s">&quot;text/css&quot;</span><span class="nt">&gt;</span> <span class="nc">.wrapper</span> <span class="p">{</span> <span class="k">max-width</span><span class="o">:</span> <span class="m">680px</span><span class="p">;</span> <span class="k">margin</span><span class="o">:</span> <span class="m">60px</span> <span class="k">auto</span> <span class="m">100px</span><span class="p">;</span> <span class="p">}</span> <span class="nt">&lt;/style&gt;</span> <span class="nt">&lt;/head&gt;</span> <span class="nt">&lt;body&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;wrapper&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;vimeo-embed</span> <span class="na">embed=</span><span class="s">&quot;203909195&quot;</span><span class="nt">&gt;&lt;/vimeo-embed&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/body&gt;</span> <span class="nt">&lt;/html&gt;</span></code></pre></div> <p>Oh, you can see the <code>webcomponentsjs</code> polyfill referenced in the <em>script</em> tag. How did we get that?</p> <p>Install it via bower like this:</p> <pre><code class="bash">bower install webcomponentsjs --save </code></pre> <h3>Browser View</h3> <p>From your terminal, run a local server, e.g <a href="https://www.npmjs.com/package/http-server">http-server</a> to serve up the web page.</p> <p>Your web page should display the component like so:</p> <p><img src="https://cdn.auth0.com/blog/webcomponent/load.png" alt="Loading the Web Component" /> <em>Load Web Component</em></p> <p>Once you click the play button, the video should autoplay:</p> <p><img src="https://cdn.auth0.com/blog/webcomponent/click.png" alt="Click and Play Video" /> <em>Video should autoplay</em></p> <p>Inspect the page with Chrome DevTools, check out the <code>&lt;video-embed&gt;</code> tag:</p> <p><img src="https://cdn.auth0.com/blog/webcomponent/videoembed.png" alt="Video embed tag" /> <em>video embed tag</em></p> <p>Check out the Shadow DOM below:</p> <p><img src="https://cdn.auth0.com/blog/webcomponent/shadowroot.png" alt="Shadow Dom" /> <em>Shadow Dom</em></p> <p>Now that we have a fully functional vimeo embed web component, let's package it and submit to the registry.</p> <h2>Submit To The Web Component Registry</h2> <p>There is a list of <a href="https://www.webcomponents.org/publish">requirements</a> to adhere to before submitting your component to the registry. Follow the instructions below:</p> <ul> <li>Add an open source <a href="https://github.com/auth0-blog/vimeo-embed/blob/master/LICENSE">license</a>.</li> <li>Add a <a href="https://github.com/auth0-blog/vimeo-embed/blob/master/README.md">README</a> and include a <a href="https://github.com/auth0-blog/vimeo-embed/tree/master/demo">demo</a>.</li> <li>Tag a release.</li> </ul> <p>Go ahead and <a href="https://www.webcomponents.org/publish">publish</a></p> <p><img src="https://cdn.auth0.com/blog/webcomponent/publish.png" alt="Publish the Web Component" /></p> <p>Now, your component should be visible in the registry.</p> <p><img src="https://cdn.auth0.com/blog/webcomponent/latestpublished.png" alt="Visible in the component registry" /></p> <p>Yaay!</p> <h2>Browser Support for Web Components</h2> <p>Google Chrome is leading the pack of browsers with stable support for Web Components in their web and mobile browsers. Take a look at the browser support matrix below:</p> <p><img src="https://cdn.auth0.com/blog/webcomponent/browsersupport.png" alt="Web component browser support" /> <em>Source: webcomponentjs</em></p> <p>To be safe, it is recommended to use <a href="https://github.com/webcomponents/webcomponentsjs">webcomponentsjs</a>, to provide support for many browsers.</p> <p>We used <code>webcomponentsjs</code> during the course of building our own custom element. <a href="https://github.com/webcomponents/webcomponentsjs">webcomponentsjs</a> is a suite of polyfills supporting the <a href="http://webcomponents.org">Web Components</a>. These polyfills are intended to work in the latest version of browsers.</p> <p><strong>Note:</strong> Web Components capabilities are disabled by default in Firefox. To enable them, go to the <code>about:config</code> page and dismiss any warning that appears. Then search for the preference called <strong>dom.webcomponents.enabled</strong>, and set it to true.</p> <h2>Tools for Building Web Components</h2> <p>There are libraries available that make it easier to build web components. Some of these libaries are:</p> <ul> <li><a href="https://bosonic.github.io">Bosonic</a></li> <li><a href="https://www.polymer-project.org">Polymer</a></li> <li><a href="https://github.com/skatejs/skatejs">SkateJS</a></li> <li><a href="https://x-tag.github.io">X-Tag</a></li> </ul> <p> All the libraries highlighted here offer tools to cut down boilerplate code and make creating new components easier. <strong>Polymer</strong> and <strong>Bosonic</strong> also offer a library of ready made Web Components, but Polymer remains the most widely used amongst developers. Check out this <a href="https://auth0.com/blog/build-your-first-app-with-polymer-and-web-components">awesome tutorial on building apps with Polymer and Web components</a>.</p> <h2>Aside: Easy Authentication with Auth0</h2> <p>You can use <a href="https://auth0.com/docs/libraries/lock">Auth0 Lock</a> for authentication in your web apps. With Lock, showing a login screen is as simple as including the <strong>auth0-lock</strong> library and then calling it in your app like so:</p> <pre><code class="js"> // Initiating our Auth0Lock var lock = new Auth0Lock( 'YOUR_CLIENT_ID', 'YOUR_AUTH0_DOMAIN' ); // Listening for the authenticated event lock.on("authenticated", function(authResult) { // Use the token in authResult to getProfile() and save it to localStorage lock.getProfile(authResult.idToken, function(error, profile) { if (error) { // Handle error return; } localStorage.setItem('idToken', authResult.idToken); localStorage.setItem('profile', JSON.stringify(profile)); }); }); </code></pre> <p><em>Implementing Lock</em></p> <pre><code class="js"> document.getElementById('btn-login').addEventListener('click', function() { lock.show(); }); </code></pre> <p><em>Showing Lock</em></p> <p><img src="https://cdn.auth0.com/blog/nexthrone-auth0lock.png" alt="Auth0 Lock Screen" /></p> <p><em>Auth0 Lock Screen</em></p> <p>You can also use the <a href="https://github.com/epilith/auth0-lock">custom auth0-lock polymer web component</a> for login like so:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;auth0-lock</span> <span class="na">autoLogin=</span><span class="s">&quot;true&quot;</span> <span class="na">domain=</span><span class="s">&quot;AUTH0_DOMAIN&quot;</span> <span class="na">clientId=</span><span class="s">&quot;AUTH0_CLIENTID&quot;</span> <span class="na">profile=</span><span class="s">&quot;&quot;</span><span class="nt">&gt;&lt;/auth0-lock&gt;</span> <span class="nt">&lt;script&gt;</span> <span class="kd">var</span> <span class="nx">firebaseRequest</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">api</span><span class="o">:</span> <span class="s2">&quot;api&quot;</span><span class="p">,</span> <span class="c1">// This defaults to the first active addon if any or you can specify this</span> <span class="nx">scope</span><span class="o">:</span> <span class="s2">&quot;openid profile&quot;</span> <span class="c1">// default: openid</span> <span class="p">};</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;auth0-lock&#39;</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;logged-in&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">profile</span><span class="p">)</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">profile</span><span class="p">);</span> <span class="c1">// try to get delegated access to Firebase</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;auth0-lock&#39;</span><span class="p">).</span><span class="nx">delegate</span><span class="p">(</span><span class="nx">firebaseRequest</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">});</span> <span class="p">});</span> <span class="nt">&lt;/script&gt;</span></code></pre></div> <h2>Conclusion</h2> <p>Web components have a lot more benefits than meets the eye. Web Components allow for less code, modular code and more reuse in our apps.</p> <p>In my opinion, the major selling point of <strong>Web components</strong> is reusability and simplicity of use. The more high quality components developers submit to the <a href="https://www.webcomponents.org">registry</a>, the more a plethora of better tools will be available to the community for building better and beautiful web apps in less time!</p> <p>Have you been using <em>Web Components</em> for a while? Do you think <strong>Web Components</strong> are the future for web app development? Are they just another hipster technology? I'll like to know your thoughts in the comment section.</p> 5 Reasons Your Company Needs Identity and Access Management 2017-03-15T08:30:00+00:00 https://auth0.com/blog/5-reasons-your-company-needs-identity-and-access-management/ Martin Gontovnikas http://twitter.com/mgonto <hr /> <p>Identity management seems like just a small piece of the puzzle that keeps your business running smoothly. If there's basic functionality for your system that gets people where they need to be, you should be all set, right?</p> <p>Unfortunately, it isn't that simple.</p> <p>Identity management is more than just being able to stick a username and password into a login box. It's very difficult to do right, and login will throw a wrench in the works if it's done wrong. But when you're committed to the best practices for login management, your business can benefit in ways you might not have realized.</p> <p>And that's where outsourcing your identity management comes in. There are many reasons why your company needs identity and access management, but these five are a good place to start.</p> <h2>1. Attracting more users</h2> <p>If your business is B2B or B2C, you're always thinking about attracting new users. Maybe you:</p> <ul> <li>Step up your game to craft some killer <a href="https://adespresso.com/">ads for social media</a> and A/B test your ads with a platform like AdEspresso to get the best results from your ad budget.</li> <li>Reconfigure your onboarding process to help people realize the value of your product from their first session.</li> <li>Run extensive <a href="https://amplitude.com/mobile-analytics">mobile analytics</a> for your new app to figure out exactly what you need to tweak to make it better.</li> </ul> <p>But eventually just going through traditional channels like ads and analytics isn't enough.</p> <p>One of the most effective, but oft-forgotten ways to drive conversions is simply to change login. User-friendly options like <a href="https://auth0.com/docs/sso?utm_source=twitter&amp;utm_medium=vc&amp;utm_campaign=social_media_vids">single sign-on</a> and social login can make a big difference in how many people actually sign up — to the tune of a <a href="https://auth0.com/blog/how-to-use-social-login-to-drive-your-apps-growth/">20% increase in conversions</a>.</p> <p>But then there's the daunting prospect of configuring across platforms for SSO and potential security concerns for social login. To create a <a href="https://auth0.com/blog/bad-login-experiences/?utm_source=twitter&amp;utm_medium=sc&amp;utm_campaign=bad_login">great login experience</a> that converts users, you need a good identity and access management system (IAM).</p> <p>With Auth0, you can implement frictionless sign-up options like social login almost instantly. Using an IAM system to implement a secure, user-friendly login is one of the most compelling changes you can make to convert a user.</p> <h2>2. Securing your data</h2> <p>Unfortunately, we can't even go a few months without hearing about <a href="http://www.telegraph.co.uk/news/2016/11/17/three-mobile-cyber-hack--six-million-customers-private-data-at-r/">breaches of login information</a>. As more companies implement an online or app presence and more consumers sign up for those accounts, the stakes of a security compromise only grow with each passing year.</p> <p>The thought of having a problem with login security should strike fear into every business's heart, but it can be daunting to find the best way to implement a watertight login system.</p> <p>Your business can't budget in an entire, 24/7 security detail, right?</p> <p><img src="https://cdn.auth0.com/blog/flow/protected.png" alt="Protected" /></p> <p>Well, no, you probably can't. However, when you outsource your identity management, you can get all the strength and expertise of your own security detail without keeping an army of engineers in your office.</p> <p>From <a href="https://auth0.com/security">encryption</a> to <a href="https://auth0.com/blog/announcing-password-breach-detection/">password breach detection</a>, your login will be as secure as possible when you outsource your identity management. <em>You </em>can't spend every second of every day making sure that your login is the most secure, but that is precisely what an IAM company does. That way, you can sleep at night knowing that you and your customer's data is safe and sound.</p> <h2>3. Supercharging your marketing</h2> <p>Selling and upselling your product means having a clear picture of your customers' interests, behaviors, and desires to <a href="https://auth0.com/blog/5-killer-email-strategies-for-lifecycle-marketing/">make marketing materials that really hook them in</a>.</p> <p>The problem is that, more often than not, a customer's information is spread out over different platforms. You might have one platform for analytics, one for email messaging, one place where you store login information. Ultimately, the more you utilize customer information, the more platforms you'll have.</p> <p>What you need is the ability to consolidate this information to create a powerful, information-rich profile. With Auth0, you can streamline the process of creating a profile by automating the transfer of information at login.</p> <p>The easiest way to do this is with <a href="https://auth0.com/docs/rules">Auth0 Rules</a>: snippets of code that trigger at login with Auth0.</p> <p>For example, you grab someone's profile information from their social login when they sign up. Then, you use a Rule to automatically enter that information into your platform of choice, say your email messaging platform. Easy as that, you've nailed that next happy birthday discount message.</p> <p><img src="https://cdn.auth0.com/blog/flow/flow.png" alt="Flow" /></p> <h2>4. Keeping up with the trends</h2> <p>Whether it's the latest social login or the latest security protocol, it's paramount that you keep up to date on the best login practices. You've got to be able to transition to the latest, greatest versions of login (<a href="https://auth0.com/blog/analysis-of-passwordless-connections/">passwordless login</a>, for example).</p> <p>There's a lot of new technology, and much of it could radically change the way that we log in to everyday accounts and devices. Embracing the future of login means being prepared to use biometric data and increasingly integrated devices in a rapidly growing Internet of Things.</p> <p><img src="https://cdn.auth0.com/blog/flow/passwordless-authentication.png" alt="Passwordless Authentication" /></p> <p>Staying on top of these shifting technologies is a <a href="https://auth0.com/blog/why-staying-agile-is-key-to-startup-success/">key to business (especially startup) success</a> — unfortunately, it's also not usually your first priority when the bread and butter of your business isn't login.</p> <p>This is why outsourcing your identity management can continue to return value to you in the long run. An IAM solution will be able to keep up with changes in social login, add relevant and novel features as they are adopted, and keep security on the cutting edge.</p> <p>That means you can continuously update your login with almost no work on your end. You'll always be ahead of the login curve, giving customers confidence in your security and the newest, most convenient logins.</p> <h2>5. Making life easier for your company</h2> <p>Identity management can make a huge difference in the lives of your employees. When you have disparate systems that you need to connect to conduct your business, login can become a hassle.</p> <p>If you're a smaller business, taking the time to sync up all of your systems to an easy login can be a difficult thing to do with limited time and resources. If you're a larger company, the number of employees you have to sync and the permissions you have to manage can be overwhelming.</p> <p>And that's without even getting into <a href="https://auth0.com/blog/how-real-state-companies-can-implement-open-id-connect-with-auth0/">industry requirements</a>.</p> <p>With Auth0, you can streamline your internal systems with a <a href="https://auth0.com/learn/single-sign-on-in-3-steps/">single sign-on</a>. This will allow your employees to get into all the systems they need with just one login and password, and to stay logged in across platforms throughout the day. That streamlines the process of getting work done.</p> <p><img src="https://cdn.auth0.com/blog/flow/bg-login.png" alt="Single Sign On" /></p> <p>A robust IAM system will also allow you to implement the correct permissions and add new accounts without having to think twice. Oh, and any industry requirements that crop up? Using an IAM solution takes the headaches out of adopting new protocols for your login if ever they come your way.</p> <h2>Leave your login to the professionals</h2> <p>The best way to take full advantage of all that an IAM solution can offer you is to outsource your identity management. Unless you decide to sink your resources into building a full-scale identity management team, you simply won't be able to tap into the benefits that a robust IAM solution can offer you.</p> <p>Identity management is more than a simple login. It can offer a real value to your business, for everything from employee quality of life to revenue generation, and it has the potential to be an integral component of your success.</p> User Provisioning and Access Request with Auth0 and Webtask 2017-03-14T19:11:00+00:00 https://auth0.com/blog/automating-access-requests-and-provisioning/ Alex Stanciu https://twitter.com/alecks <h2>Automating Access Requests &amp; Provisioning</h2> <p><em>A deep look at how we automated our employee access request system</em></p> <blockquote><p>“Give me access to vpn”</p></blockquote> <p>This is all you need to tell our Slack bot; a request is created and your manager receives an approval request.</p> <h3>Some Background</h3> <p>Granting users access to various resources is a challenge that many (if not most) organizations face. Unfortunately, many small/medium-sized companies find the cost of purchasing and operating monolithic provisioning systems prohibitive. User access often becomes a highly manual and messy process. Here at Auth0 we started out with a Google Form: employees would fill it out checking off various resources/apps they wanted access to. The form saved into a Google Sheet where a script would take each entry and create an Issue in a GitHub repository. Our IT team would then use the repo’s issues as a request tracking system and manually fulfill them. There are a few problems with this approach:</p> <ul> <li>No approval mechanism</li> <li>No tracking, and no easy way to show what an employee has access to</li> <li>Very hard to automate</li> <li>Pretty bad UX</li> </ul> <p>… so we decided to build something</p> <h2>Goals</h2> <p>For our internal MVP, we wanted to at least address the above points, but also set ourselves up so this tool could grow:</p> <ul> <li>Provide an easy way to define resources (the things that people can request, for example: email distribution lists, building badges, access to AWS, GitHub, laptop, and VPNs, as well as work orders like “restore a backup” or “reset MFA”)</li> <li>Customizable, multi-step, dynamic approval workflows </li> <li>Tracking/reporting to help our SOC2 audits</li> <li>Mechanism to setup automated fulfillment for things that can be automated (for ex, via APIs, automatically add a user to our GitHub organization)</li> <li>Frictionless UX: we are Slack bot junkies, so we knew this was a critical integration</li> <li>Architecture that will allow expansion</li> <li>Extendable: if someone wants to convert a resource from manual to automated fulfillment, it shouldn’t require changes to the app or redeployment</li> <li>Use this opportunity to explore any new technologies we’ve been watching/itching to play with</li> </ul> <h2>End Result</h2> <p>After three months of on-the-side development, we launched our tool, code-named “Phenix” (no, it’s not misspelled). <img src="https://cdn.auth0.com/blog/access-requests/phenix.png" alt="Phenix" /></p> <p>Let’s do a quick walkthrough of the basic flow. In this sample use case we’ll set up a resource to allow employees to request to be added to our Auth0 GitHub organization.</p> <p>We first create the resource and specify a few options: <img src="https://cdn.auth0.com/blog/access-requests/resource.png" alt="Resource" /></p> <p>For the rest of the resource, we configure a two-step serial approval workflow that includes Manager Approval and Security Team approval. </p> <p>For fulfillment, we’ll keep it manual for now and assign it to the Dev Ops group.</p> <p>Resources also allow the creation of a custom form to capture data from the user at the time of request. We will use this to capture the user’s GitHub userid and a comment. <img src="https://cdn.auth0.com/blog/access-requests/resource-fillout2.gif" alt="Resource Tabs" /></p> <p>Now that the resource is configured, let’s request it: <img src="https://cdn.auth0.com/blog/access-requests/create-request.gif" alt="Create Request" /></p> <h2>Approvals</h2> <p>The above request will step through each stage of the approval process; if all stages are approved, the request will switch to fulfillment mode. If any stage is rejected, the approval process stops and the request is finished.</p> <p>We configured an approval stage called Dynamic Approval for the Manager because each requester could have a different manager. We need to determine who the approver is at run-time, when the request is processing. We do this using the webtask platform. Setting the approval type as dynamic allows the creation of a webtask where the end user (the Administrator) can write custom code that figures out who the manager is. <img src="https://cdn.auth0.com/blog/access-requests/dynamic-approval.png" alt="Dynamic Approval" /></p> <p>Clicking Edit opens the webtask editor where we have simple code to retrieve the manager userid from the request beneficiary’s profile: <img src="https://cdn.auth0.com/blog/access-requests/get-manager-wt.png" alt="Get Manager Webtask" /></p> <p>The manager info is saved in the Auth0 user’s <code>app_metadata</code> attribute; this is currently populated via an existing outside script that syncs our HR system with Auth0 profiles. If we didn’t have this data already in Auth0, this code would instead make an API call to our HR system (BambooHR) to get the user’s manager.</p> <p>When the request is submitted, the approvers receive a ticket in their inbox representing a pending approval task. For the above request, since I am an admin, I will be able to see both approval tickets (for both the manager and security stages). I will approve both and then reject the fulfillment request. Normally these three steps would be performed by separate people <img src="https://cdn.auth0.com/blog/access-requests/inbox-approve.gif" alt="Inbox - Approve Requests" /></p> <p>We can see the final status of this request as: <img src="https://cdn.auth0.com/blog/access-requests/final-request.png" alt="Final Request" /></p> <p>As you can see, for each stage it correctly shows who the intended approver/fulfiller was and who actually took the action. Great for our audit history!</p> <h2>Slack</h2> <p><img src="https://cdn.auth0.com/blog/access-requests/slack-approval.png" alt="Slack Approval" /></p> <p>When the approval tickets are created, the approvers also receive a message in Slack that they can approve or reject. If the approval is set to a group, we can create mappings of groups to Slack channels so only one message is posted in the group’s channel. The system ensures that only designated approvers are allowed to click the buttons (not everyone in the #devops channel is in the DevOps Group). </p> <p>We also wanted the ability to create requests from Slack. This proved to be a bit more challenging in the end, but a ton of fun. </p> <p>This is what it looks like: <img src="https://cdn.auth0.com/blog/access-requests/create-request-slack.gif" alt="Slack Request" /></p> <p>It may not be immediately evident but there is a lot going on here.</p> <p>First, the bot needs to keep track of different conversations, with different users, across different Slack teams. This is easy enough, but it also needs to keep track of <em>where</em> in the conversation it is.</p> <p>It accepts some built-in commands, like <code>help</code>, <code>list</code>, etc., but if someone says something like, “I need access to vpn”, this is not a built-in command. To make sense of this, we use <a href="https://api.ai">api.ai</a>’s NLP services to process these kinds of phrases and detect if the user said something that matches making a request:</p> <blockquote><p>“give [<em>user</em>] [<em>resource</em>]”</p> <p>“request [<em>resource</em>] for [<em>user</em>]”</p> <p>“I want access to [<em>resource</em>]”</p> <p>etc…</p></blockquote> <p>Once it detects that the user wants a resource and for whom (you can request things for other people, too), it then looks to see if that resource has a form defined. If so, we start a “conversation” with the user, progressively asking for the data in the form. </p> <p>The hard part here was keeping track of it all. With Slack bots, there is no inherent concept of a session, so we had to build this. The bot could receive a message like “jdoe35” and it would need to figure out that user X, on team Y, is making a request for resource Z which has five form fields and this is the response to the third field, which we must have previously asked for (ex: “Enter your GitHub user id”). </p> <h2>Automating The Fulfillment</h2> <p>In the above example request for GitHub, the resource was configured for manual fulfillment. It means the designated fulfiller received a ticket representing the to-do item. They would manually do the work (add the user to our GitHub organization), and mark it as done.</p> <p>To automate this, you can configure automated provisioning via a webtask. This is a very simple and straight-forward way to quickly call an API and get something done. In the Fulfillment tab of the resource, we can select “Webtask Auto Fulfillment”: <img src="https://cdn.auth0.com/blog/access-requests/auto-fulfillment.png" alt="Auto Fulfillment" /></p> <p>In the webtask code, we can grab the user’s GitHub userid from the form submitted with the request and make the API call: <img src="https://cdn.auth0.com/blog/access-requests/auto-fulfill-wt.png" alt="Auto Fulfill Webtask" /></p> <p>Using the <a href="https://webtask.io">webtask platform</a> for extensibility was a huge saver. We can let the administrators and end users customize the tool without burdening the development team. I wish every SaaS/Webapp had something like this, where, for example, you might be given a configuration choice between A or B, but maybe you want that to change depending on certain factors. The webtask platform allowed us to add this third option C to figure it out at runtime by running your own custom code. </p> <h2>Tracking</h2> <p>Now that a whole system is in place, it’s very easy to keep track of who has what and why. Below is a very crude interface that shows the basics, but the data is there and generating compliance reports is now trivial.</p> <p>Building a lightweight certification mechanism on top of this would also be fairly straight-forward. (Certification is the process of periodically asking someone, usually a manager, if a user should still have access to X, thereby catching sensitive access that was only temporarily needed.) <img src="https://cdn.auth0.com/blog/access-requests/user-resource-list.png" alt="User Resource List" /></p> <h2>Engineering</h2> <p>From the start we wanted to design and engineer this application as if it might some-day become a product. This meant building it from the ground up with scaling, multi-tenancy, security and performance in mind. We also wanted to try out some new technologies and patterns.</p> <p>The front end is a React, Single Page App. Nothing too fancy going on here beyond current modern standards and recommendations (code splitting, lazy loading, etc…)</p> <p>We decided to try out GraphQL as the API interface. The data model fits pretty well for the use case. There are lots of joins happening in the data model and with GraphQL the client can get everything in one shot. </p> <p>To keep the API as light as possible, we split out the request processing and notification services into separate workers and handed them tasks via a queue.</p> <p>The bot also follows this convention. We decided to not use Slack’s RTM API since it uses WebSockets, which come with different types of scaling problems. Instead, we use Slack’s Event API which functions like a webhook; we subscribe to chat messages and Slack does a POST to us with those messages. The trick here is that there could be many teams, with many channels, and if the bot is invited to very chatty channels, it will result in LOTS of POSTed messages from Slack.</p> <p><em>If the bot is in a channel (versus Direct Message), it only responds if called by name and it responds in a thread. This minimizes “bot-spam” in public channels.</em></p> <p>To handle this, we have an extremely light-weight HTTP server that receives the POSTed message, replies back to Slack with a 200, and puts the data in a queue. A separate bot worker processes the messages and replies to the user. We use Redis to store the conversation sessions, so while making a request and answering questions, there could be many bot workers actually replying.</p> <p>Speaking of Redis, we also have a fairly standard caching layer for things that don’t change that often (resources, groups, users, tenant settings, API tokens, etc…) we proxy those through a layer of Local Cache -> Redis -> Mongo. A solid caching strategy is especially important when using GraphQL. <img src="https://cdn.auth0.com/blog/access-request/diagram.png" alt="Component Architecture" /></p> <h2>Going Forward</h2> <p>In its current state, Phenix is a fairly solid access request platform with some light provisioning. We are planning to keep building on top of this to create a robust provisioning engine with full connector support that handles all types of CRUD operations against target systems. We are also building a reconciliation engine to sync data into the system from other sources. </p> <p>While Phenix is an internal tool for now, we are aware that it could be beneficial to others and we may decide to open it later. If you think something like this would be useful to your organization, or if you have any other thoughts or questions on this topic, please leave us a comment.</p> Critical Vulnerability in JSON Web Encryption 2017-03-13T10:30:00+00:00 https://auth0.com/blog/critical-vulnerability-in-json-web-encryption/ Antonio Sanso https://twitter.com/asanso <hr /> <p><strong>TL;DR</strong> If you are using <a href="https://github.com/square/go-jose">go-jose</a>, <a href="https://github.com/cisco/node-jose">node-jose</a>, <a href="https://github.com/dvsekhvalnov/jose2go">jose2go</a>, <a href="https://bitbucket.org/connect2id/nimbus-jose-jwt/wiki/Home">Nimbus JOSE+JWT</a> or <a href="https://bitbucket.org/b_c/jose4j/wiki/Home">jose4</a> with <a href="https://tools.ietf.org/html/rfc7518">ECDH-ES</a> please update to the latest version. <a href="https://tools.ietf.org/html/rfc7516">RFC 7516 aka JSON Web Encryption (JWE)</a> and software libraries implementing this specification used to suffer from a classic <a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.107.3920&amp;rep=rep1&amp;type=pdf">Invalid Curve Attack</a>. This can allow an attacker to recover the secret key of a party using JWE with <a href="https://tools.ietf.org/html/rfc7518">Key Agreement with Elliptic Curve Diffie-Hellman Ephemeral Static (ECDH-ES)</a>, where the sender could extract receiver’s private key.</p> <hr /> <h2>Premise</h2> <p>In this blog post I assume you are already knowledgeable about elliptic curves and their use in cryptography. If not <a href="https://twitter.com/grittygrease">Nick Sullivan</a>'s <a href="https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/">A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography</a> or Andrea Corbellini's series <a href="andrea.corbellini.name/2015/05/23/elliptic-curve-cryptography-finite-fields-and-discrete-logarithms/">Elliptic Curve Cryptography: finite fields and discrete logarithms</a> are great starting points. Then if you further want to <a href="https://moderncrypto.org/mail-archive/curves/2016/000784.html">climb the elliptic learning curve</a> including the related attacks you might also want to visit <a href="https://safecurves.cr.yp.to/">https://safecurves.cr.yp.to/</a>. Also the <a href="https://www.youtube.com/watch?v=y_YxRUTI-xU">DJB and Tanja talk at 31c3</a> comes with an explanation of this very attack (see minute 43) or  <a href="web-in-security.blogspot.ch/2015/09/practical-invalid-curve-attacks.html">Juraj Somorovsky et al's research</a> can become handy for learners.</p> <p>Note that this research was started and inspired by <a href="https://research.google.com/pubs/pub45790.html">Quan Nguyen from Google</a> and then refined by <a href="https://twitter.com/asanso">Antonio Sanso from Adobe</a>.</p> <h2>Introduction</h2> <p>JSON Web Token (JWT) is a JSON-based open standard (<a href="https://tools.ietf.org/html/rfc7519">RFC 7519</a>) defined in the <a href="https://tools.ietf.org/wg/oauth/">OAuth specification family</a> used for creating access tokens. The <a href="https://tools.ietf.org/wg/jose/">Javascript Object Signing and Encryption (JOSE) IETF expert group</a> was then formed to formalize a set of signing and encryption methods for JWT that led to the release of  <a href="https://tools.ietf.org/html/rfc7515">RFC 7515 aka JSON Web Signature (JWS)</a> and <a href="https://tools.ietf.org/html/rfc7516">RFC 7516 aka JSON Web Encryption (JWE)</a>. In this post we are going to focus on JWE.</p> <p>A typical JWE is dot separated string that contains five parts:</p> <ul> <li>The JWE Protected Header</li> <li>The JWE Encrypted Key</li> <li>The JWE Initialization Vector</li> <li>The JWE Ciphertext</li> <li>The JWE Authentication Tag</li> </ul> <p>An example of a JWE taken from the <a href="https://tools.ietf.org/html/rfc7516">specification</a> would look like:</p> <pre><code>eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGeipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDbSv04uVuxIp5Zms1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaVmqgfwX7XWRxv2322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je81860ppamavo35UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi6UklfCpIMfIjf7iGdXKHzg. 48V1_ALb6US04U3b.5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6ji
     SdiwkIr3ajwQzaBtQD_A.XFBoMYUZodetZdvTiFvSkQ </code></pre> <p>This JWE employs RSA-OAEP for key encryption and A256GCM for content encryption :</p> <p><img src="https://cdn.auth0.com/blog/jwe-vulnerability/header0.png" alt="JWE Token" /></p> <p>This is only one of the many possibilities JWE provides. A separate specification called <a href="https://tools.ietf.org/html/rfc7518">RFC 7518 aka JSON Web Algorithms (JWA)</a> lists all the possible available algorithms that can be used. The one we are discussing today is the <a href="https://tools.ietf.org/html/rfc7518">Key Agreement with Elliptic Curve Diffie-Hellman Ephemeral Static (ECDH-ES)</a>.  This algorithm allows deriving an ephemeral shared secret (<a href="https://neilmadden.wordpress.com/2016/05/20/ephemeral-elliptic-curve-diffie-hellman-key-agreement-in-java/">this blog post from Neil Madden</a> shows a concrete example on how to do ephemeral key agreement).</p> <p>In this case the <em>JWE Protected Header</em> lists as well the used elliptic curve used for  the key agreement:</p> <p><img src="https://cdn.auth0.com/blog/jwe-vulnerability/header.png" alt="JWE Decoded" /></p> <p>Once the shared secret is calculated the key agreement result can be used in one of two ways:</p> <ol> <li><p>Directly as the Content Encryption Key (CEK) for the "enc" algorithm, in the Direct Key Agreement mode, or</p></li> <li><p>As a symmetric key used to wrap the CEK with the A128KW, A192KW, or A256KW algorithms, in the Key Agreement with Key Wrapping mode.</p></li> </ol> <p>This is out of scope for this post but as for the other algorithms the <a href="https://tools.ietf.org/html/rfc7520">JOSE Cookbook</a> contains example of usage for ECDH-ES in combination with AES-GCM or AES-CBC plus HMAC.</p> <h2>Observation</h2> <p>As highlighted by Quan during his talk at <a href="https://www.realworldcrypto.com/rwc2017">RWC 2017</a>:</p> <blockquote><p>Decryption/Signature verification input is always under attacker’s control</p></blockquote> <p>As we will see thorough this post this simple observation will be enough to recover the receiver’s private key. But first we need to dig a bit into elliptic curve bits and pieces.</p> <h2>Elliptic Curves</h2> <p>An elliptic curve is the set of solutions defined by an equation of the form:</p> <p><strong>y<sup>2</sup> = x<sup>3</sup> + ax + b</strong></p> <p>Equations of this type are called <em>Weierstrass equations</em>. An elliptic curve would look like:</p> <p><img src="https://cdn.auth0.com/blog/jwe-vulnerability/EC.png" alt="Elliptic Curve" /></p> <p><strong>y<sup>2</sup> = x<sup>3</sup> + 4x + 20</strong></p> <p>In order to apply the theory of elliptic curves to cryptography we need to look at elliptic curves whose points have coordinates in a finite field Fq. The same curve will then look like below over Finite Field of size 191:</p> <p><img src="https://cdn.auth0.com/blog/jwe-vulnerability/ECFP.png" alt="Field Size" /></p> <p><strong>y<sup>2</sup> = x<sup>3</sup> + 4x + 20 over Finite Field of size 191</strong></p> <p>For JWE the elliptic curves in scope are the one defined in <a href="https://www.nsa.gov/ia/programs/suiteb_cryptography/index.shtml">Suite B</a> and (<a href="https://www.rfc-editor.org/rfc/rfc8037.txt">only recently</a>) <a href="https://cr.yp.to/djb.html">DJB</a>'s curve. Between those, the curve that so far has reached the higher amount of usage is the famous P-256.</p> <p>Time to open <a href="www.sagemath.org/">Sage</a>. Let's define P-256:</p> <p><img src="https://cdn.auth0.com/blog/jwe-vulnerability/p256.png" alt="P-256" /></p> <p>The order of the curve is a really huge number hence there isn't much an attacker can do with this curve (if the software implements ECDH correctly) in order to guess the private key used in the agreement. This brings us to the next section:</p> <h2>The Attack</h2> <p>The attack described here is really the classical <a href="citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.107.3920&amp;rep=rep1&amp;type=pdf">Invalid Curve Attack</a>. The attack is simple and powerful and takes advantage from the mere fact that Weierstrass's formula for scalar multiplication does not take in consideration the coefficient b of the curve equation:</p> <p><strong>y<sup>2</sup> = ax<sup>3</sup> + ax + b</strong>.</p> <p>The original's P-256 equation is:</p> <p><img src="https://cdn.auth0.com/blog/jwe-vulnerability/p256.png" alt="P-256" /></p> <p>As we mention above, the order of this curve is really big. So we need now to find a more convenient curve for the attacker. Easy peasy with Sage:</p> <p><img src="https://cdn.auth0.com/blog/jwe-vulnerability/lift.png" alt="Sage" /></p> <p>As you can see from the image above we just found a nicer curve (from the attacker point of view) that has an order with many small factors. Then we found a point P on the curve that has a really small order (2447 in this example).</p> <p>Now we can build malicious JWEs (see the <strong>Demo Time section</strong> below) and extract the value of the secret key modulo 2447 with complexity in constant time.</p> <p>A crucial part for the attack to succeed is to have the victim to repeat his own contribution to the resulting shared key. In other words this means that the victim should have his private key to be the same for each key agreement. Conveniently enough this is how the <a href="https://tools.ietf.org/html/rfc7518">Key Agreement with Elliptic Curve Diffie-Hellman Ephemeral Static (ECDH-ES)</a> works. Indeed ES stands for Ephemeral-Static were Static is the contribution of the victim!</p> <p>At this stage we can repeat these operations (find a new curve, craft malicious JWEs, recover the secret key modulo the small order) many many times and collecting information about the secret key modulo many many small orders.</p> <p>And finally <a href="https://en.wikipedia.org/wiki/Chinese_remainder_theorem">Chinese Remainder Theorem</a> for the win!</p> <p>At the end of the day the issue here is that the specification and consequently all the libraries I checked missed validating that the received public key (contained in the JWE Protected Header is on the curve), You can see the Vulnerable Libraries section below to check how the various libraries fixed the issue.</p> <p>Again you can find details of the attack in the <a href="citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.107.3920&amp;rep=rep1&amp;type=pdf">original paper</a>.</p> <h2>Demo Time</h2> <p><strong><a href="https://afternoon-fortress-81941.herokuapp.com/">INSTANT DEMO CLICK HERE</a></strong></p> <p><img src="https://cdn.auth0.com/blog/jwe-vulnerability/attacker.png" alt="Demo" /></p> <h3>Explanation</h3> <p>In order to show how the attack would work in practice I set up a live demo in Heroku. In <a href="https://obscure-everglades-31759.herokuapp.com/">https://obscure-everglades-31759.herokuapp.com/</a> is up and running one Node.js server app that will act as a victim in this case. The assumption is this: in order to communicate with this web application you need to encrypt a token using the <a href="https://tools.ietf.org/html/rfc7518">Key Agreement with Elliptic Curve Diffie-Hellman Ephemeral Static (ECDH-ES)</a>. The static public key from the server needed for the key agreement is in <a href="https://obscure-everglades-31759.herokuapp.com/ecdh-es-public.json">https://obscure-everglades-31759.herokuapp.com/ecdh-es-public.json</a>:</p> <p><img src="https://cdn.auth0.com/blog/jwe-vulnerability/ecdh.png" alt="Demo explanation" /></p> <p>An application that wants to POST data to this server needs first to do a key agreement using the server's public key above and then encrypt the payload using the derived shared key using the JWE format. Once the JWE is in place this can be posted to <a href="https://obscure-everglades-31759.herokuapp.com/secret">https://obscure-everglades-31759.herokuapp.com/secret</a>. The web app will respond with a response status 200 if all went well (namely if it can decrypt the payload content) and with a response status 400 if for some reason the received token is missing or invalid. This will act as an oracle for any potential attacker in the way shown in the previous The Attack section.</p> <p>I set up an attacker application in <a href="https://afternoon-fortress-81941.herokuapp.com/">https://afternoon-fortress-81941.herokuapp.com/</a>.</p> <p>You can visit it and click the 'Recover Key' button and observe how the attacker is able to recover the secret key from the server piece by piece. Note that this is only a demo application so the recovered secret key is really small in order to reduce the waiting time. In practice the secret key will be significantly larger (hence it will take a bit more to recover the key).</p> <p>In case you experience problem with the live demo, or simply if  want to see the code under the hood, you can find the demo code in Github:</p> <ul> <li><a href="https://github.com/asanso/jwe-receiver">https://github.com/asanso/jwe-receiver</a> contains the code of the vulnerable server.</li> <li><a href="https://github.com/asanso/jwe-sender">https://github.com/asanso/jwe-sender</a> contains the code of the attacker.</li> </ul> <h2>Vulnerable Libraries</h2> <p>Here you can find a list of libraries that were vulnerable to this particular attack so far:</p> <ul> <li><a href="https://github.com/cisco/node-jose">node-jose</a> v0.9.3 include the fixes necessary, which was <a href="https://github.com/cisco/node-jose/blob/master/CHANGELOG.md">published few weeks ago</a>. Here the <a href="https://gist.github.com/asanso/fa25685348051ef6a28d49aa0f27a4ae">Gist</a> of the original proof of concept.*</li> <li><a href="https://github.com/dvsekhvalnov/jose2go">jose2go</a>'s fix landed in <a href="https://groups.google.com/forum/">version 1.3</a>.</li> <li><a href="https://bitbucket.org/connect2id/nimbus-jose-jwt/wiki/Home">Nimbus JOSE+JWT</a> pushed out a fixed artifact to Maven central as v4.34.2. Here the <a href="https://gist.github.com/asanso/5b8cabb862e6f730e00a97d8565dc325">Gist</a> of the original proof of concept.**</li> <li><a href="https://bitbucket.org/b_c/jose4j/wiki/Home">jose4</a> now comes with a <a href="https://bitbucket.org/b_c/jose4j/commits/0517896170af8d5c057407c70a7b08dae454829e">fix</a> for this problem since v0.5.5. Here the <a href="https://gist.github.com/asanso/350e3ce993e44d0509c6023aa77fc6af">Gist</a> of the original proof of concept.**</li> <li><a href="https://github.com/square/go-jose">go-jose</a> (this is the original library found vulnerable by <a href="https://research.google.com/pubs/pub45790.html">Quan Nguyen</a>)</li> </ul> <p>Some of the libraries were implemented in a programming language that already protects against this attack checking that the result of the scalar multiplication is on the curve:</p> <p>* Latest version of Node.js appears to be immune to this attack. It was still possible to be vulnerable when using browsers without web crypto support.</p> <p>** Affected was the default Java SUN JCA provider that comes with Java prior to version 1.8.0_51. Later Java versions and the BouncyCastle JCA provider do not seem to be affected.</p> <h2>Improving the JWE Standard</h2> <p>I reported this issue to the JOSE working group via <a href="https://www.ietf.org/mail-archive/web/jose/current/msg05612.html">mail to the appropriate mailing list</a>. We all seem to agree that an errata where the problem is listed is at least welcomed. This post is a direct attempt to raise awareness about this specific problem.</p> <h2>Acknowledgement</h2> <p>The author would like to thanks the maintainers of <a href="https://github.com/square/go-jose">go-jose</a>, <a href="https://github.com/cisco/node-jose">node-jose</a>,<a href="https://github.com/dvsekhvalnov/jose2go">jose2go</a>, <a href="https://bitbucket.org/connect2id/nimbus-jose-jwt/wiki/Home">Nimbus JOSE+JWT</a> and <a href="https://bitbucket.org/b_c/jose4j/wiki/Home">jose4</a> for the responsiveness on fixing the issue. <a href="https://twitter.com/francescomari">Francesco Mari</a> for helping out with the development of the demo application. Tommaso Teofili and Simone Tripodi for troubleshooting. Finally as mentioned above I would like to thank <a href="https://research.google.com/pubs/pub45790.html">Quan Nguyen from Google</a>, indeed this research could not be possible without his initial incipit.</p> <p>That's all folks. For more crypto goodies, follow me on <a href="https://twitter.com/asanso/">Twitter</a>.</p> <div class="alert alert-info"> <strong>About Antonio Sanso:</strong><br /> Antonio works as Senior Software Engineer at Adobe Research Switzerland where he is part of the Adobe Experience Manager security team. Antonio is co-author of "OAuth 2 in Action" book. He found vulnerabilities in popular software such as OpenSSL, Google Chrome, Apple Safari and is included in the Google, Facebook, Microsoft, Paypal and Github security hall of fame. He is an avid open source contributor, being the Vice President (chair) for Apache Oltu and PMC member for Apache Sling. His working interests span from web application security to cryptography. Antonio is also the author of more than a dozen computer security patents and applied cryptography academic papers. He holds an MSc in Computer Science. </div> <p></p> Using Serverless Azure Functions with Auth0 and Google APIs 2017-03-10T08:30:00+00:00 https://auth0.com/blog/using-serverless-azure-functions-with-auth0-and-google-apis/ Steve Lee https://twitter.com/SteveALee <p><em>Guest post by <a href="https://twitter.com/@SteveALee">@SteveALee</a> of <a href="http://opendirective.com">OpenDirective.com</a></em></p> <p><strong>TL;DR:</strong> Learn how Node.js backend code via Azure Functions can access a Google API once a user logs in with Google via the Auth0 Lock widget.</p> <hr /> <p>Without a doubt, authentication for web apps is one of the most complex features to implement correctly. If you’re not careful, it will eat a large chunk of your development time. Worse, if you don't get it exactly right you're left vulnerable to being hacked, which will take even more of your precious time, not to mention damaging your reputation. Therefore, it's nice to have Auth0 around to help mitigate this problem with their flexible service along with some of the best documents and support in the business. I picked a complex case as my first attempt at auth for a Single Page App (SPA) Software as a Service (SaaS) product.</p> <p>This post is the story of my experience along with some working JavaScript code for <a href="https://azure.microsoft.com/en-us/services/functions/">Azure Functions</a> with <a href="https://www.auth0.com">Auth0</a>.</p> <h2>Serverless Architecture</h2> <p>Azure Functions are part of Microsoft’s offering in the relatively new Serverless Architecture space. Sometime referred to as Functions as a Service (FaaS), Serverless Architecture allows you to concentrate your development offerts on you ‘Business Logic’ or backend application code. In this extension of Platform As a Service (PaaS), Microsoft manage all the lower layers of the hardware and software stack for you. For example: servers, operating systems, web servers and even platforms such as Node.js. Note that serverless code is event driven and triggers may be HTTP requests but can also be from other sources such as a database update. This <a href="https://www.martinfowler.com/bliki/Serverless.html">introductory article</a> on MartinFlower.com explains a web app use of Serverless Architecture and also links to a very thorough post by Mike Roberts.</p> <h2>The Problem</h2> <p>I'm developing a set of open source components used in a commercial SaaS designed to support the needs of people with cognitive disabilities or low digital literacy. The initial components and product will provide simplified access to shared photographs and email. Given this, Google Picasa and Gmail seemed like natural choices for the initial underlying services. Unfortunately, the Picasa API has been feature stripped recently when Google moved over to Google Photos.</p> <p>My initial requirement for the user experience is that they can easily authenticate by signing into their existing Google account. The code should then be able to access their photos and emails, using the Picasa and Gmail APIs. This will require authorized access based on the user credentials provided when they sign in. The initial user story that we cover in this post is:</p> <blockquote><p>As a user, I want to log into the app with my Google account so I get a list of my Google Photos albums.</p></blockquote> <p>That all seemed fairly straightforward after spending some time learning the basics of OAuth and OpenID flows from a mixture of Auth0 and OpenID documentation. Then I read the various Google API and auth docs and ended up confused. Google spreads the documentation around several places and it is not always consistent or precise. In addition, Google’s docs are often unclear on whether they are describing access from a client or backend and which specific authentication flows they are talking about. Finally, they often use their own SDKs (or libraries), which obscures the details and is largely irrelevant. This also adds another large download for client users.</p> <h2>Getting Nowhere Very Slowly</h2> <p>After exploring the Google APIs with some experimental code accessing them directly from the SPA I wanted to pull my hair out. The Picasa API in particular is very flaky in how it handles CORS and authentication. Plan B was to use Auth0 to do all the heavy lifting. My hope was their Lock widget would solve the technical issues relatively easily. For example, Lock handles the <code>nonce</code> and <code>state</code> attributes used to stop hacking. Lock is also flexible in user experience options, for example it easily allows the addition of extra services. However, I soon found out the <code>access_token</code> that Lock provides to a SPA is not usable in Google APIs and it was hard to find any answers.</p> <p>At this point, I started to think that backend access was going to be the solution. In addition to reliable access there's also the question of what to do when tokens expire. We need to avoid having the user keep logging in, so refresh tokens will be required which must be stored securely in the backend, as they effectively allow endless access. Several other design requirements pointed to backend access, and using Azure Functions meant a rapid development and relatively low DevOps requirements. Win - win.</p> <p>I found after more experimental code that this did eventually work out, but only after I stumbled across a highly relevant Auth0 document and requested help from the awesome Nico, a Customer Success Engineer at Auth0. As Nico pointed out, if you use Auth0 as the identity provider then even when proxying other third party identity providers, the <code>access_token</code>s you get are from Auth0. They can be used with Auth0 APIs or your own, but are not what third party APIs require. Auth0 does provide a mechanism for backend code to get the <code>access_token</code> from third party identity providers. However, the token is hidden in the Auth0 UI for security purposes.</p> <h2>Auth0 and Azure Functions: Making Life Easy</h2> <p>Without further delay, here's the low-down on what you need to do to let a user sign in with Google via the Auth0 Lock and then access a Google API with their credentials, using the Google <code>access_token</code>. I'll also present some links to important docs. Here's the complete flow we use:</p> <ol> <li>SPA displays the Auth0 Lock passing suitable options</li> <li>User logs in with Google, approving access to requested scopes (eg read photos, read emails)</li> <li>If required, Auth0 creates a new Auth0 user linked to the Google user</li> <li>SPA gets the Auth0 user <code>id_token</code> and <code>access_token</code></li> <li>SPA calls the backend HTTP endpoint to get a list of photos, etc., and passes the <code>access_token</code> with this request</li> <li>Backend Azure Functions validates the JWT and optionally checks the user is allowed access</li> <li>Backend uses the userid in the <code>access_token</code> to find the user profile using the Auth0 admin API</li> <li>Backend extracts the Google <code>access_token</code> from the user’s profile.</li> <li>Backend calls the Google Picasa API and processes the results, returning them to the SPA in the HTTP response</li> </ol> <p>In order for this to work, you need to have the following configured:</p> <ul> <li>A Google Photos account with some photos, preferably in several albums</li> <li>Auth0 web Client for the SPA - <a href="https://auth0.com/docs/client-auth/client-side-web">Authentication for Client-side Web Apps</a></li> <li>Google OAuth client for backend access to APIs - <a href="https://auth0.com/docs/connections/social/google">Connect Your Client to Google</a></li> <li>Auth0 API definition for the API - <a href="https://auth0.com/docs/api-auth/grant/implicit">Call APIs from Client-side Web Apps</a></li> <li>Auth0 non-interactive client for backend access to Auth0 management API - <a href="Call%20an%20Identity%20Provider%20API">Call an Identity Provider API</a></li> <li>Azure account and an <a href="https://azure.microsoft.com/en-us/services/functions/">Azure Functions App</a></li> </ul> <p>You should also read:</p> <ul> <li><a href="https://auth0.com/docs/overview">Auth0 Overview</a></li> <li><a href="https://auth0.com/docs/tokens/idp">Identity Provider Access Tokens</a></li> <li><a href="https://auth0.com/docs/libraries/lock">Lock for Web</a></li> <li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function">Create your first Azure Function</a></li> </ul> <p>Here is a simple vanilla HTML and JavaScript example that allows the user to sign in with the Auth0 Lock and then calls the Azure Functions backend to get a list of Google Photos albums:</p> <pre><code class="html">&lt;!doctype html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt; &lt;title&gt;Auth0 and Google APIs&lt;/title&gt; &lt;script src="https://cdn.auth0.com/js/lock/10.9.1/lock.min.js"&gt;&lt;/script&gt; &lt;/head&gt; &lt;body&gt; &lt;button id="btn-login"&gt;Login&lt;/button&gt; &lt;button id="btn-get"&gt;Get Albums&lt;/button&gt; &lt;pre id="profile"/&gt; &lt;script&gt; function getGoogleAlbums(accessToken) { var AZUREFUNCTION = 'AZURE FUNCTION URL HERE' var xmlhttp = new XMLHttpRequest() xmlhttp.onreadystatechange = function() { if (this.readyState == 4 /*&amp;&amp; this.status == 200*/) { alert(this.status+'\r\n'+this.responseText.replace(/\\"/g,'')) } } xmlhttp.open("GET", AZUREFUNCTION, true); xmlhttp.setRequestHeader('Authorization', `Bearer ${accessToken}`) xmlhttp.send(); } var lock = new Auth0Lock( 'THIS CLIENTS ID HERE', 'DOMAIN.eu.auth0.com', { allowedConnections: ['google-oauth2'], allowForgotPassword: false, allowSignUp: false, closable: false, auth: { connection_scopes: { 'google-oauth2': ['https://picasaweb.google.com/data/'] }, params: { scope: 'openid profile photos', audience: 'https://API_ID HERE' }, responseType: "id_token token" }, languageDictionary: { title: "Sign into Google" } } ); // Listening for the Lock authenticated event lock.on("authenticated", function(authResult) { localStorage.setItem('accessToken', authResult.accessToken); localStorage.setItem('idToken', authResult.idToken); lock.getUserInfo(authResult.accessToken, function(error, profile) { if (error) { // Handle error return; } localStorage.setItem('profile', JSON.stringify(profile)); }); }); document.getElementById('btn-login').addEventListener('click', function() { lock.show(); }) document.getElementById('btn-get').addEventListener('click', function() { var accessToken = localStorage.getItem('accessToken') var idToken = localStorage.getItem('idToken') getGoogleAlbums(accessToken) }) function view() { // Verify that there's a token in localStorage var token = localStorage.getItem('accessToken'); if (token) { showProfile(); } } function showProfile() { var profile = JSON.stringify(JSON.parse(localStorage.getItem('profile')),null,2); document.getElementById('profile').textContent = profile; } view() &lt;/script&gt; &lt;/body&gt; &lt;/html&gt; </code></pre> <p>Now for the Azure Functions backend code. This is a JavaScript HTTP Azure Function with the method set to <code>GET</code>. Tokens are passed from the frontend code above in a URL parameter.</p> <p>Note, this initial block of constants should not normally be included in the main code (if only to stop you accidently checking your secrets into GitHub). Rather it’s good practice to place them in the Function App Service’s Settings and reference them from the code.</p> <pre><code class="js">// constants const AUTH0_DOMAIN_URL = 'https://DOMAIN.auth0.com' const AUTH0_API_ID = 'https://API_ID' const AUTH0_SIGNING_CERTIFICATE = `-----BEGIN CERTIFICATE----- &lt;Get this from the Auth0 client Advanced settings -&gt; certificates&gt; -----END CERTIFICATE-----` const AUTH0_ADMIN_CLIENT_ID = 'YOUR ADMIN CLIENT APP ID' const AUTH0_ADMIN_CLIENT_SECRET = 'YOUR ADMIN APP CLIENT SECRET' </code></pre> <p>This main body of the code can be added via the Azure Functions console:</p> <pre><code class="js">// Create decorator that checks the JWT signature and specified fields const jwtValidateDecorator = require('./azure-functions-auth0')({ clientId: AUTH0_API_ID, clientSecret: AUTH0_SIGNING_CERTIFICATE, algorithms: ['RS256'], domain: `${AUTH0_DOMAIN_URL}/` }) // The main Functions Function module.exports = jwtValidateDecorator((context, req) =&gt; { if (req.user) { // Get a token to access the admin API getAdminAccessToken() .then(({object: {access_token}}) =&gt; { const userId = req.user.sub // has been added to the req by the decorator return getUserProfile(access_token, userId) }) // Get the album list from google .then(({object}) =&gt; { const google_access_token = object.identities[0].access_token // hidden from the Auth0 console return getAlbums(google_access_token) }) // Get the album titles .then(({object: {feed: {entry}}}) =&gt; { const titles = entry.map(ent =&gt; ent.title.$t) return { status: 200, body: JSON.stringify(titles), headers: {'Content-Type': 'application/json'} } }) .catch(err =&gt; { return { status: 400, body: err.message } }) .then(res =&gt; { context.done(null, res) }) } else { const res = { status: 400, body: 'Something is wrong with the Authorization token' } context.done(null, res) } }) </code></pre> <p>Here are the supporting functions called from the main code block above. They can be placed in the same Function for simplicity. An alternative is to place them in a separate module file and “require” them as usual with Node.js. Azure Functions allows you to provide several Functions and supporting code in a single Functions App. const request = require('request')</p> <pre><code class="js">// Call a remote HTTP endpoint and return a JSON object function requestObject(options) { return new Promise((resolve, reject) =&gt; { request(options, function (error, response, body) { if (error) { reject(error); } else if ((200 &gt; response.statusCode) || (299 &lt; response.statusCode)) { reject(new Error(`Remote resource ${options.url} returned status code: ${response.statusCode}: ${body}`)) } else { const object = (typeof body === 'string') ? JSON.parse(body) : body // FIXME throws resolve({code: response.statusCode, object}) } }) }) } // Get an access token for the Auth0 Admin API function getAdminAccessToken() { const options = { method: 'POST', url: `${AUTH0_DOMAIN_URL}/oauth/token`, headers: { 'content-type': 'application/json' }, body: { client_id: AUTH0_ADMIN_CLIENT_ID, client_secret: AUTH0_ADMIN_CLIENT_SECRET, audience: `${AUTH0_DOMAIN_URL}/api/v2/`, grant_type: 'client_credentials' }, json: true } return requestObject(options) } // Get the user's profile from the Admin API function getUserProfile(accessToken, userID) { const options = { method: 'GET', url: `${AUTH0_DOMAIN_URL}/api/v2/users/${userID}`, headers: { 'Authorization': `Bearer ${accessToken}` } } return requestObject(options) } // Get user Google Photos album list function getAlbums(accessToken) { const options = { method: 'GET', //url: `https://www.googleapis.com/gmail/v1/users/me/labels`, url: 'https://picasaweb.google.com/data/feed/api/user/default?alt=json', headers: { 'Authorization': `Bearer ${accessToken}` } } return requestObject(options) } </code></pre> <p>We need to check the Auth0 <code>access_token</code> is valid before allowing the API code to be executed. This is done by a decorator (or wrapper) function based on the <code>npm azure_functions_auth0</code> module but modified to work correctly with an Auth0 API <code>access_token</code>.</p> <pre><code class="js">// azure_functions_auth0.js // based on the npm package azure-functions-auth0 // But modified to handle the Auth0 API accessToken const jwt = require('express-jwt'); //import ArgumentError from './errors/ArgumentError'; const ArgumentError = Error module.exports = (options) =&gt; { if (!options || !(options instanceof Object)) { throw new ArgumentError('The options must be an object.'); } if (!options.clientId || options.clientId.length === 0) { throw new ArgumentError('The Auth0 Client or API ID has to be provided.'); } if (!options.clientSecret || options.clientSecret.length === 0) { throw new ArgumentError('The Auth0 Client or API Secret has to be provided.'); } if (!options.domain || options.domain.length === 0) { throw new ArgumentError('The Auth0 Domain has to be provided.'); } const middleware = jwt({ secret: options.clientSecret, audience: options.clientId, issuer: options.domain, algorithms: options.algorithms }) return (next) =&gt; { return (context, req) =&gt; { middleware(req, null, (err) =&gt; { if (err) { const res = { status: err.status || 500, body: { message: err.message } }; return context.done(null, res); } return next(context, req); }); }; }; }; </code></pre> <h2>Running the Code</h2> <p>For a local client development server, I simply installed npm package <a href="https://www.npmjs.com/package/lite-server">'lite-server'</a> configured to port 8000 with a ‘bs-config.json’ file.</p> <p>For the backend, you'll need to create an HTTP Azure Function with the method set to GET. You'll also need to install the two npm dependencies of <code>express-jwt</code> and <code>request</code>. In the Azure Functions control panel go to "Functions App Settings" -> "Console" to open up a console. Then <code>cd</code> to the folder for your function and enter the following command:</p> <pre><code class="bash">npm install express-jwt request </code></pre> <p>You'll also need to set up CORS by adding your client URL - eg. localhost:8000. This is found in the Azure Functions console panel and click on "Function app settings" -> "Configure CORS". Finally, copy the Function’s URL into the SPA code constants block.</p> <h2>Observations</h2> <p>As this is a Serverless backend with no local state storage, the same authorization code will run for every similar endpoint. We can tidy up the code to be more DRY (Don’t Repeat Yourself) by moving the code to get the Auth0 Admin and Google <code>access_token</code>s into a module shared by all your Functions in the Function App.</p> <h2>Conclusion</h2> <p>Auth0 provides all the features needed to access Google APIs with a user’s credentials. When a user signs in through Auth0 you get an Auth0 access token. You then need to obtain the third party access token for Google’s APIs. This is done with backend code for security. The code accesses the user’s profile via the Auth0 Admin API and can then obtain the access token provided when the user signed in with Google.</p> <p>Azure Functions provides an ideal way to create the backend code in Node.js without the need to create and configure servers or Node itself. An HTTP function is easy to create and configure via the Azure Functions control panel, or everything can be done locally and then deployed to Azure.</p> <p>Best of all, both Auth0 and Azure Functions provide free subscriptions that allow you to explore them in detail. Have fun!</p> Serverless development reimagined with the new Webtask Editor 2017-03-09T16:02:00+00:00 https://auth0.com/blog/serverless-development-reimagined-with-the-new-webtask-editor/ Javier Centurion https://twitter.com/jcenturion86 <h2>Serverless Development Reimagined with the New Webtask Editor</h2> <p>If you are building serverless applications, then you want to get from zero to code in seconds. We've just shipped a brand new editor for Webtask which makes this desire a reality!</p> <p>The Webtask Editor is a rich online environment for creating, editing and testing your Webtasks. In addition, it allows you to manage secrets, configure github two-way sync, view realtime logs, and more. It makes serverless development a breeze and you <em>never have to leave the browser or install anything to use it</em>. And with our out-of-the-box support for over 1000+ <a href="https://webtask.io/docs/modules?utm_source=auth0.com&amp;utm_medium=blog&amp;utm_campaign=webtask_editor_launch">Node modules</a>, you can get a lot of work done.</p> <p>Let’s take a quick walkthrough of the experience.</p> <h2>Creating a New Webtask</h2> <p>With the new editor, getting started can't get any easier. Just head to <a href="https://webtask.io/make?utm_source=auth0.com&amp;utm_medium=blog&amp;utm_campaign=webtask_editor_launch">webtask.io/make</a>, log in with your preferred credentials, and you'll be on your way.</p> <p><img src="https://cdn.auth0.com/webtask/assets/images/screenshot.png" alt="Webtask Editor" /></p> <p>From the popup dialog, you will see a few options:</p> <ul> <li><em>Webtask</em>: this creates an empty webtask.</li> <li><em>Cron</em>: this creates an empty scheduled webtask.</li> <li><em>Pick a template</em>: start coding based on selecting from a library of templates.</li> <li><em>Import from GitHub</em>: import your code from a Github repo to a webtask.</li> </ul> <h3>Webtask</h3> <p>Selecting "Webtask" will put you right into the editor where you can start authoring a new task.</p> <p><img src="https://cdn.auth0.com/webtask/assets/images/new-webtask.gif" alt="Create a Webtask" /></p> <h3>Cron</h3> <p>Cron tasks are great for executing a task on a schedule, such as checking a Twitter feed for mentions. When you create a new cron task, you will see two panes. The left pane is the scheduler where you specify the schedule for your task and the right pane is where you put the code for your task.</p> <p><img src="https://cdn.auth0.com/webtask/assets/images/new-cron.gif" alt="Create a Cron with Auth0 Webtask" /></p> <p>For more info about cron, check <a href="https://webtask.io/docs/cron">this document</a>.</p> <h3>Templates</h3> <p>Templates let you choose from a selection of starter code that you can use for building your tasks. We've included templates for integrating Webtask with common services like <a href="https://stripe.com">Stripe</a>, <a href="https://slack.com">Slack</a>, <a href="https://sendgrid.com">Sendgrid</a>, <a href="https://github.com">Github</a>, <a href="https://twilio.com">Twilio</a>, <a href="https://facebook.com">Facebook</a>, and many more.</p> <p><img src="https://cdn.auth0.com/webtask/assets/images/templates.gif" alt="Webtask Templates" /></p> <h3>Importing from GitHub</h3> <p>If you have existing Webtasks in a repo, you can import them directly into Webtask by pointing to the repo.</p> <h2>Editor Features</h2> <p>Now let's take a look at some of the awesome editor features.</p> <h3>Runner and Logs</h3> <p>We've designed the new editor to streamline your development and allow you to iterate fast. To help with testing, the editor comes with an intergrated runner. In the runner you can set different HTTP methods, parameters, headers, etc. To help with debugging, we've added a realtime logs viewer that lets you view you tasks console output while it is executing.</p> <p><img src="https://cdn.auth0.com/webtask/assets/images/runner.gif" alt="Webtask runner and logs" /></p> <h3>Secrets Management</h3> <p>If your tasks are talking to other authenticated services, you don't want to store credentials in the code. You can define new secure secrets right in the editor, which are then accessible from the code via the <code>context</code> object.</p> <p><img src="https://cdn.auth0.com/webtask/assets/images/secrets.gif" alt="Secrets management" /></p> <h3>GitHub Integration</h3> <p>To take your experience up a notch, we've baked in Github integration support. This allows you to sync your webtask with a file in a Github repo. You can enable this to work bi-directionally, such that commits and pull requests to the repo result in the task automatically being deployed and any changes in the editor result in commits to the repo. You can also bind multiple tasks to different branches of the same repo, thus having dev, test, and prod versions of your tasks. It's super powerful!</p> <p><img src="https://cdn.auth0.com/webtask/assets/images/github-integration.gif" alt="GitHub integration with Webtask" /></p> <h3>Task Management</h3> <p>Press <code>CMD + P</code> or click on the list or on the "Webtasks" icon and you'll see a list of all your tasks. From the list, you can switch to a different task, open a task in a different window, or even delete tasks. You can type into the search bar to filter the list of displayed tasks.</p> <p><img src="https://cdn.auth0.com/webtask/assets/images/quicksearch.gif" alt="Webtask Quicksearch" /></p> <h3>Shortcuts</h3> <p>The new editor has tons of shortcuts for common actions within the editor as well as additional features like beautifying your code. You can see the list of shortcuts by clicking on the Shortcuts icon in the upper right corner.</p> <p><img src="https://cdn.auth0.com/webtask/assets/images/shortcuts.gif" alt="Webtask shortcuts" /></p> <h3>CLI Support</h3> <p>If you like using our <a href="https://webtask.io/cli?utm_source=auth0.com&amp;utm_medium=blog&amp;utm_campaign=webtask_editor_launch">CLI</a>, we've got you covered. You can go right from the shell to the editor with the <code>edit</code> command, i.e. <code>wt edit mytask</code>.</p> <p><img src="https://cdn.auth0.com/webtask/assets/images/from-cli.gif" alt="Webtask CLI support" /></p> <h2>Go Try It!</h2> <p>The new Webtask Editor is an amazing tool for serverless development. It will let you instantly go from idea => code => running. Not only do you get a rich browser-based authoring experience, but you get a tool to secure, test, and debug your code. Go get started playing with the Webtask editor now: <a href="https://webtask.io/make?utm_source=auth0.com&amp;utm_medium=blog&amp;utm_campaign=webtask_editor_launch">webtask.io/make</a>. Also check out our documentation at <a href="https://webtask.io/docs/editor?utm_source=auth0.com&amp;utm_medium=blog&amp;utm_campaign=webtask_editor_launch">webtask.io/docs/editor</a>.</p> 3 Easy Practical Steps You Can Take To Drive More Users To Convert 2017-03-08T08:30:00+00:00 https://auth0.com/blog/three-easy-practical-steps-you-can-take-to-drive-more-users-to-convert/ Diego Poza https://twitter.com/diegopoza <hr /> <p>After users sign-up, they get into your fantastic app. You show them the basic features, and you've even done some <a href="https://amplitude.com/mobile-analytics">data analysis</a> to figure out what users need to do to increase their chances of sticking around. When they're in, they're hooked.</p> <p>But your conversion rate still isn't great. Something is stopping people from taking the plunge and starting to use your app, which is constraining your growth.</p> <p>If this has you nodding along, you might be suffering from a problem at login. Even if you have a great product, you're not going to succeed unless you actually get users to join. It's time to make a change to the way you're getting users to sign-up, and we have some tips.</p> <h2>1. Use Social Login</h2> <p>One of the best ways to improve your conversion rates is to use social login. Why? Because it's one of the easiest ways for people to sign-up. The benefits of social sign-up are clear — anywhere from a <a href="https://www.quora.com/What-impact-does-social-login-have-on-conversion-rates">20-60% increase</a> in conversion — and it works for users because they don't have yet another name and password to remember. One click and they're in.</p> <p><img src="https://cdn.auth0.com/blog/login/Auth0Widget.png" alt="Auth0 Widget" /></p> <p>This means that, when a user finds your app, they can sign-up almost without thinking about it — there's nothing to make them stop and consider whether or not it's worth the effort to sign-up before they've even seen what you can really do.</p> <p>In the same vein, you can setup your login with a smart sign-up form. With this, your users don't have to fill in a whole form during sign-up, because you've filled it in for them. An example of this is <a href="https://segment.com/blog/frictionless-signup-forms-by-clearbit-segment/">frictionless sign-up</a>, an integration by <a href="http://segment.com/">Segment</a> that you can use with your login. A user puts in their email, to get their sign-up started. Then, the Segment integration retrieves and fills in their name and job information filled out, speeding up the sign-up process.</p> <p>Taking the hassle out of your users' sign-up experience is a no brainer, and with the broad range of social login options available, there's no reason you can't add a few networks and tricks to your login or sign-up form.</p> <h2>2. Show Them Their Friends</h2> <p>FOMO isn't just a trend — it's an actual, <a href="http://www.slate.com/blogs/quora/2015/09/30/fomo_what_s_the_psychology_behind_the_fear_of_missing_out.html">psychologically rooted phenomenon</a>. People want to know what their friends are doing, and feel anxious when they're left out. And if you can tap into that psychology by showing people their friends using your app, you're going to be more likely to get them past your login. Check out how Facebook pulls your list of friends from your Facebook profile to encourage you to use Messenger:</p> <p><img src="https://cdn.auth0.com/blog/fomo/messenger.png" alt="Messenger" /> <em>Source: https://blogs.adobe.com/creativecloud/xd-essentials-user-onboarding-and-empty-states-in-mobile-apps/</em></p> <p>The easiest way to tap into this is by making it a breeze for your users to invite their friends to your app. Ensuring that your product is convenient to share with friends, such as configuring <a href="https://developers.facebook.com/products/sharing/app-invites">App Invites</a> on Facebook, can be especially effective. If someone gets your app recommended via an invitation from a friend, that exposure will help you convert that person into a user.</p> <p>For example, if you and your buddy are really into soccer, you might be much more tempted to sign-up for World Cup Challenge if you see that they've invited you to play with them.</p> <p><img src="https://cdn.auth0.com/blog/app/wwc_invite_receipt.jpg" alt="Invite" /> <em>Source: https://blog.branch.io/how-to-deep-link-on-facebook</em></p> <p>Showing people their friends as soon as they get past the login page is also a great motivator to stay on social apps. The trick is to configure your social login to acquire their friends from their profile.</p> <p><img src="https://cdn.auth0.com/blog/config/facebook-setup.png" alt="Facebook setup" /></p> <p>Immediately seeing their friends will make people feel like your app is a natural extension of their network. Showing potential users right at sign-up that they know people who are active on your app will drive them to convert because they have a natural desire to see what their friends are up to — and what they've missed out on.</p> <h2>3. Personalize Their First Experience</h2> <p>Just as showing people their friends when they sign-up is a good way to demonstrate the value of your app, personalizing a user's first experience can help you get people from signing up and onboarding to being a dedicated user.</p> <p>One easy way to connect from the very first login is to use geography to your advantage. Whether you're showing them recommendations in the area, getting regional news on their feed, or sampling a rainy day playlist to match the weather, using their location to customize what they see at sign-up will help them feel welcomed, and let them know that they can personalize their own experience.</p> <p>For example, Foursquare asks for a user's location during sign-up. Then, when they enter the app, new users immediately see suggestions near them. This demonstrates the value and relevance of their app immediately.</p> <p><img src="https://cdn.auth0.com/blog/personalize/foursquare.png" alt="Personalize" /> <em>Source: https://www.useronboard.com/how-foursquare-onboards-new-users/?slide=66</em></p> <p>Another way you can hook users into your app is by connecting them to their interests. No matter the focus of your app, there's a way to connect users with what's relevant to their life. If you know a user likes the NBA, you could suggest they follower players or teams. If they're a film buff, have them save the location of their favorite theatre.</p> <p>This is another place where configuring social login can help you — just as you pulled their friends from their profile, you can also look at pages they've liked or followed. This will help you curate options to show your new users as they work through sign-up and onboarding — which will encourage them to actually get into your app.</p> <h2>Give New Users What They Want</h2> <p>The consistent factor between all three methods to improve retention that we've discussed is simply giving users what they want. Social login reduces friction by eliminating the need for users to remember another username and password. Showing users their friends at sign-up plays into our desire to connect with our friends, while personalizing from the first login connects users directly with their interests.</p> <p>The old saying <em>there's no second chance at a first impression </em>is never more true than when configuring your login. Driving conversions means catering to your users from your very first interaction. Setting up your login with your users' wants in mind is a great way to raise your conversion rate.</p> Managing State in Angular with ngrx/store 2017-03-07T08:30:00+00:00 https://auth0.com/blog/managing-state-in-angular-with-ngrx-store/ Kim Maida https://twitter.com/KimMaida <div class="alert alert-info alert-icon"> <i class="icon-budicon-664"></i> <strong>Get the "Migrating an AngularJS App to Angular book" for Free.</strong> Spread the word and <a href="https://auth0.com/e-books/migrating-to-angular2">download it now!</a> </div> <p><strong>TL;DR:</strong> In this article, we'll explore managing state with an immutable data store in an <a href="http://angular.io">Angular</a> application using <a href="https://github.com/ngrx/store">ngrx/store</a>: reactive Redux for Angular. We'll also authenticate our app with <a href="https://auth0.com">Auth0</a> and implement route authorization with route guards. The final code can be cloned from <a href="https://github.com/auth0-blog/pet-tags-ngrx">this GitHub repository</a>.</p> <hr /> <h2>Managing State in Angular Apps</h2> <p>State management in large, complex applications has been a headache plaguing AngularJS / Angular developers over the last few years. In <a href="https://angularjs.org/">AngularJS (version 1.x)</a>, state management is often addressed using a confusing mixture of services, events, and <code>$rootScope</code>. In <a href="https://angular.io">Angular (versions 2+)</a>, <a href="https://angular.io/docs/ts/latest/cookbook/component-communication.html">component interaction</a> is cleaner but can still be quite involved, <a href="https://scotch.io/tutorials/get-angular-1-features-in-angular-2">encompassing many different approaches</a> depending on the desired direction of the flow of data.</p> <blockquote><p><strong>Note:</strong> In this article, <em>AngularJS</em> refers specifically to version 1.x of the framework while <em>Angular</em> refers to versions 2.x and up, as per the <a href="http://angularjs.blogspot.com/2017/01/branding-guidelines-for-angular-and.html">Branding Guidelines for Angular</a>.</p></blockquote> <p>Some developers are using <a href="https://github.com/reactjs/redux">Redux</a> with AngularJS or Angular. <a href="http://redux.js.org">Redux is a "predictable state container for JavaScript apps"</a> and supports a single, immutable data store. Redux is best-known for its use with <a href="https://github.com/reactjs">React</a>, but it can be utilized with any view library. <a href="http://egghead.io">Egghead.io</a> hosts an excellent <a href="https://egghead.io/series/getting-started-with-redux">free video series on Redux from its creator, Dan Abramov</a>.</p> <h2>Introducing ngrx/store</h2> <p>For our Angular application, we're going to use <a href="https://github.com/ngrx/store">ngrx/store</a> rather than Redux. What is the relationship between Redux and ngrx/store and why would we prefer one over the other?</p> <h3>Relationship to Redux</h3> <p>Ngrx/store is an "RxJS powered state management library for Angular applications, inspired by Redux", authored by <a href="https://twitter.com/robwormald">Rob Wormald, an Angular Developer Advocate</a>. It shares Redux's core fundamentals but uses <a href="http://reactivex.io/rxjs/">RxJS</a>, which implements the observer pattern in JS and comes packaged with Angular. It follows the core principles of Redux and is specifically designed for Angular.</p> <h3>Fundamental Tenets of ngrx/store</h3> <ul> <li><em>State</em> is a single, immutable data structure</li> <li><em>Actions</em> describe state changes</li> <li>Pure functions called <em>reducers</em> take the previous state and the next action to compute the new state</li> <li>State accessed with the <code>Store</code>, an observable of state and an observer of actions</li> </ul> <p>Let's break this down. The following is a quick (but important) overview of the basics. We'll go more indepth as we build our application.</p> <h3>Actions</h3> <p><strong>Actions</strong> are information payloads that send data from the application to the <em>reducer</em>, which updates the <em>store</em>. <a href="https://egghead.io/lessons/javascript-redux-describing-state-changes-with-actions">Actions</a> are the only way the store receives data.</p> <p>In ngrx/store, the <code>Action</code> <a href="https://www.typescriptlang.org/docs/handbook/interfaces.html">interface</a> looks like this:</p> <pre><code class="js">// actions consist of type and data payload export interface Action { type: string; payload?: any; } </code></pre> <p>The <code>type</code> should describe the kind of state change we want. For example, this might be something like <code>'ADD_TODO'</code> or <code>'DECREMENT'</code>, etc. The <code>payload</code> is the data being sent to the store in order to update it. Actions are <em>dispatched</em> to the store like so:</p> <pre><code class="js">// dispatch action to update store store.dispatch({ type: 'ADD_TODO', payload: 'Buy milk' }); </code></pre> <h3>Reducers</h3> <p><strong>Reducers</strong> specify how the state changes in response to <em>actions</em>. A <a href="https://egghead.io/lessons/javascript-redux-the-reducer-function">reducer</a> is a <em>pure</em> function that describes state mutations in the app by taking the previous state and the dispatched action and returning the next state as a <em>new</em> object, generally using <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign"><code>Object.assign</code></a> and/or <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator"><code>spread syntax</code></a>:</p> <pre><code class="js">// reducer function specifies how the state // changes when an action is dispatched export const todoReducer = (state = [], action) =&gt; { switch(action.type) { case 'ADD_TODO': return [...state, action.payload]; default: return state; } } </code></pre> <p>It's important to be mindful of purity when writing reducers. <strong>Pure functions</strong>:</p> <ul> <li>do <em>not</em> mutate state outside their scope</li> <li>have return values that depend only on their inputs</li> <li>given the same input, always return the same output</li> </ul> <p>You can <a href="https://auth0.com/blog/glossary-of-modern-javascript-concepts/#purity">read more about purity here</a>. It is the responsibility of the developer to ensure purity and state <a href="https://auth0.com/blog/glossary-of-modern-javascript-concepts/#immutable-mutable">immutability</a> in JavaScript, so make sure to be mindful when writing your reducers.</p> <h3>Store</h3> <p>The <strong>store</strong> holds the entire immutable state of the application. The store in ngrx/store is an RxJS <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md"><em>observable</em></a> of state and an <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observer.md"><em>observer</em></a> of actions.</p> <p>We can use <code>Store</code> to <em>dispatch</em> actions. We can also <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/subscribe.md"><em>subscribe</em></a> to observe and react to state changes over time with <code>Store</code>'s <code>select()</code> method, which returns an observable.</p> <h2>Angular with ngrx/store: Custom Pet Tags App</h2> <p>Now that we're familiar with the basics of how ngrx/store works, we're going to build an Angular app that allows users to customize a name tag for their pet. Our app will have the following features:</p> <ul> <li>Users can choose tag shape, font style, text, and optional extras.</li> <li>Users will need to authenticate before creating a tag.</li> <li>Users can see a simple preview of their tag as they build it.</li> <li>When finished, users can create another tag or log out.</li> </ul> <p>We'll create several components to compose a tag builder and a tag preview. We'll create components and routes for logging in, creating a tag, and finishing up. The state of our tag builder app will be managed with ngrx/store. We'll also use <a href="https://auth0.com">Auth0</a> and route guards to protect our application.</p> <p>When finished, our custom pet tags app will look like this:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-app.jpg" alt="Angular app with ngrx/store Redux for Angular" /></p> <p>Let's get started!</p> <h2>Angular App Setup</h2> <h3>Install Dependencies</h3> <p>Make sure you have <a href="https://nodejs.org/en/">Node.js with npm</a> installed (LTS download recommended).</p> <p>Next, we'll install the <a href="https://cli.angular.io/">Angular CLI</a> for scaffolding and serving our app. Run the following command to install <a href="https://github.com/angular/angular-cli">angular-cli</a> globally:</p> <pre><code class="bash">$ npm install -g @angular/cli </code></pre> <p>This will install the latest version of the Angular CLI tool. Keep in mind that the Angular CLI just came out of beta and is now into release candidates at the time of writing. Updates are still to be expected. If you need to update your Angular CLI installation at any time, refer to the <a href="https://github.com/angular/angular-cli">Angular CLI GitHub README here</a>.</p> <h3>Create an Angular App</h3> <p>In a directory of your choosing, open a command prompt and create a new Angular app project:</p> <pre><code class="bash">$ ng new pet-tags-ngrx </code></pre> <p>Navigate into your new <code>/pet-tags-ngrx</code> folder and install the necessary packages to support ngrx/store, like so:</p> <pre><code class="bash">$ cd pet-tags-ngrx $ npm install @ngrx/core @ngrx/store --save </code></pre> <p>We now have everything we need to get started on our app.</p> <h2>Customize App Boilerplate</h2> <p>Let's customize the generated Angular boilerplate to better suit the application we want to build.</p> <h3>Create <code>src/app/core</code> Folder</h3> <p>First, create the following folder: <code>src/app/core</code>. Our app's root component and core files will live here. Move the <code>app.component.*</code> files into this folder.</p> <blockquote><p><strong>Note:</strong> For brevity, this tutorial will not cover testing. We will ignore all <code>*.spec.ts</code> files. If you'd like to write tests, please do so. Otherwise, these files will not be mentioned again in this article and they have been removed from the source code in the GitHub repository for simplicity.</p></blockquote> <h3>Update App Module</h3> <p>Next, open the <code>src/app/app.module.ts</code> file. We need to update the path to our <code>app.component</code> file since we just moved it into the <code>src/app/core</code> folder:</p> <pre><code class="typescript">// src/app/app.module.ts ... import { AppComponent } from './core/app.component'; ... </code></pre> <h3>Organize Assets</h3> <p>Navigate to the <code>src/assets</code> folder.</p> <p>Inside <code>assets</code>, add a new folder called <code>images</code>. Leave this empty for now; we'll add some images later. Next, move the <code>src/styles.css</code> file from the root folder into <code>src/assets</code>.</p> <p>Moving <code>styles.css</code> requires us to make a change to <code>.angular-cli.json</code>. Open this file and change the <code>styles</code> array as follows:</p> <pre><code class="js">// .angular-cli.json ... "styles": [ "assets/styles.css" ], ... </code></pre> <h3>Add Bootstrap CSS to Angular App</h3> <p>Finally, we'll add <a href="https://v4-alpha.getbootstrap.com/">Bootstrap CSS</a> to the <code>index.html</code> file in our app. This <code>&lt;link&gt;</code> tag was copied from the <a href="https://v4-alpha.getbootstrap.com/getting-started/download/#bootstrap-cdn">Bootstrap CDN</a>. We'll only use the compiled CSS and not JS. While we're at it, let's update our app's <code>&lt;title&gt;</code> to "Custom Pet Tags":</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- index.html --&gt;</span> ... <span class="nt">&lt;title&gt;</span>Custom Pet Tags<span class="nt">&lt;/title&gt;</span> ... <span class="c">&lt;!-- Bootstrap CDN --&gt;</span> <span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span> <span class="na">href=</span><span class="s">&quot;https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css&quot;</span> <span class="na">integrity=</span><span class="s">&quot;sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ&quot;</span> <span class="na">crossorigin=</span><span class="s">&quot;anonymous&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;/head&gt;</span> ...</code></pre></div> <h2>Serve the App</h2> <p>We can serve our app on <code>localhost</code> and watch for changes with the following command:</p> <pre><code class="bash">$ ng serve </code></pre> <p>Start the server and navigate to <a href="http://localhost:4200">http://localhost:4200</a>. The app should look like this:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-boilerplate.jpg" alt="Angular app generated with angular-cli" /></p> <h2>App Component</h2> <p>Now we're ready to start building out the features of our Custom Pet Tags Angular application. We'll start with the <code>app.component.*</code> files. This is our root component. Changes here will be minimal.</p> <h3>Delete App Component CSS</h3> <p>Let's delete the <code>app.component.css</code> file. We won't need it since we'll only use Bootstrap for styling this component.</p> <h3>App Component TypeScript</h3> <p>We also need to remove the reference to the deleted CSS file in the <code>app.component.ts</code> file. We can also delete the boilerplate <code>title</code> property from the <code>AppComponent</code> class. Our file should look like this:</p> <pre><code class="typescript">// src/app/core/app.component.ts import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent { } </code></pre> <h3>App Component Template HTML</h3> <p>Now let's add some HTML to the <code>app.component.html</code> template. Replace the current contents of this file with the following:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/core/app.component.html --&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;container&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;col-sm-12&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;h1</span> <span class="na">class=</span><span class="s">&quot;text-center&quot;</span><span class="nt">&gt;</span>Custom Pet Tags<span class="nt">&lt;/h1&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;router-outlet&gt;&lt;/router-outlet&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>We'll use Bootstrap styles to add a grid and a heading. Then we'll add the <a href="https://angular.io/docs/ts/latest/api/router/index/RouterOutlet-directive.html"><code>&lt;router-outlet&gt;</code></a> directive. This is where our views will render when we change routes in our single page app. At this point, the app will throw an error until we establish routing and page components. Let's do that next.</p> <h2>Create Page Components</h2> <p>As mentioned before, our app will have three routes: a homepage with login, a page where the user can create and preview a new pet tag, and a completion page where the user can view their finished tag and log out.</p> <p>Let's create these page components so we can set up routing. Then we'll come back to each of them to build them out.</p> <p>Execute the following commands from the root your <code>pet-tags-ngrx</code> project folder to generate the components:</p> <pre><code class="bash">$ ng g component pages/home $ ng g component pages/create $ ng g component pages/complete </code></pre> <p>The <a href="https://github.com/angular/angular-cli/#generating-components-directives-pipes-and-services"><code>ng g</code> command (or its longform, <code>ng generate</code>)</a> creates the necessary files and folders for Angular components, directives, pipes, and services. It also imports components in <code>app.module.ts</code>. We now have the scaffolding for our three page components, so let's set up routing.</p> <h2>Create a Routing Module</h2> <p>Let's build a separate <a href="https://auth0.com/blog/angular-2-ngmodules/"><code>NgModule</code></a> to support routing. Create a new file in the <code>src/app/core</code> folder called <code>app-routing.module.ts</code>:</p> <pre><code class="typescript">// src/app/core/routing-module.ts import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { HomeComponent } from '../pages/home/home.component'; import { CreateComponent } from './../pages/create/create.component'; import { CompleteComponent } from './../pages/complete/complete.component'; @NgModule({ imports: [ RouterModule.forRoot([ { path: '', component: HomeComponent }, { path: 'create', component: CreateComponent }, { path: 'complete', component: CompleteComponent }, { path: '**', redirectTo: '', pathMatch: 'full' } ]) ], providers: [], exports: [ RouterModule ] }) export class AppRoutingModule {} </code></pre> <p>We now have our three routes: <code>/</code>, <code>/create</code>, and <code>/complete</code>. Page not found errors will redirect back to the homepage.</p> <p>Next let's open our main app module file (<code>app.module.ts</code>) and add the new <code>AppRoutingModule</code> to <code>imports</code> like so:</p> <pre><code class="typescript">// src/app/app.module.ts ... import { AppRoutingModule } from './core/app-routing.module'; @NgModule({ ..., imports: [ ..., AppRoutingModule ], ... </code></pre> <p>We now have routing set up. We should be able to navigate in the browser by entering the URLs defined in the <code>AppRoutingModule</code>. Our <code>HomeComponent</code> now renders in the <code>&lt;router-outlet&gt;</code> when we're on the homepage:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-routing.jpg" alt="Angular app with routing" /></p> <h2>"Home" Page Component</h2> <p>The <code>HomeComponent</code> will simply have a message and a login button for unauthenticated visitors. If a user is already logged in, they'll be sent to the <code>/create</code> route instead.</p> <blockquote><p><strong>Note:</strong> Initially, we'll set up our components without authentication. After the primary features of our ngrx/store app are built, we'll add <a href="https://auth0.com">Auth0</a> authentication and a route guard.</p></blockquote> <p>For now, let's add a message and a placeholder button that takes the user to the <code>/create</code> page. Open the <code>home.component.html</code> template and replace the boilerplate content with the following markup:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/home/home.component.html --&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 text-center&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;lead&quot;</span><span class="nt">&gt;</span> Please sign up or log in to create a custom name tag for your beloved pet! <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;p&gt;</span> <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">&quot;btn btn-lg btn-primary&quot;</span> <span class="na">routerLink=</span><span class="s">&quot;/create&quot;</span><span class="nt">&gt;</span>Log In<span class="nt">&lt;/button&gt;</span> <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>At the moment, the "Log In" button simply navigates to <a href="http://localhost:4200/create">http://localhost:4200/create</a>. Later, we'll update it to authenticate the user before going to the Create page.</p> <p>Our homepage now looks like this:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-home.jpg" alt="Angular app with login" /></p> <h2>Pet Tag Model</h2> <p>Now it's time to start implementing our custom tag builder and state management. The first thing we'll do is create a <em>model</em> for our state. We want this model to represent the current custom pet tag.</p> <p>Create a new file: <code>src/app/core/pet-tag.model.ts</code>.</p> <pre><code class="typescript">// src/app/core/pet-tag.model.ts export class PetTag { constructor( public shape: string, public font: string, public text: string, public clip: boolean, public gems: boolean, public complete: boolean ) { } } export const initialTag: PetTag = { shape: '', font: 'sans-serif', text: '', clip: false, gems: false, complete: false }; </code></pre> <p>The class declares the <em>shape</em> of the <code>PetTag</code> type. These are the required properties and type annotations for our application's custom pet tag state object.</p> <p>Next we want to export a constant called <code>initialTag</code>. This constant declares the values in the default state object. We'll use this to initialize state as well as reset it.</p> <h2>Pet Tag Actions</h2> <p>Now we're ready to build an <em>actions creator</em> for our action types. Recall that actions are dispatched to a <em>reducer</em> to update the <em>store</em>. We'll declare an action for each kind of modification we want to make to the store.</p> <p>Create the following file: <code>src/app/core/pet-tag.actions.ts</code>.</p> <pre><code class="typescript">// src/app/core/pet-tag.actions.ts export const SELECT_SHAPE = 'SELECT_SHAPE'; export const SELECT_FONT = 'SELECT_FONT'; export const ADD_TEXT = 'ADD_TEXT'; export const TOGGLE_CLIP = 'TOGGLE_CLIP'; export const TOGGLE_GEMS = 'TOGGLE_GEMS'; export const COMPLETE = 'COMPLETE'; export const RESET = 'RESET'; </code></pre> <p>We're defining actions as constants. Alternatively, we could construct injectable action classes as done in the <a href="https://github.com/ngrx/example-app/tree/master/src/app/actions">ngrx/example-app</a>. For our small demo app, this can contribute to indirection, so we'll keep it simple.</p> <h2>Pet Tag Reducer</h2> <p>Now let's build our <em>reducer</em> function that will take <em>actions</em> and update the <em>store</em>. Create a new file: <code>src/app/core/pet-tag.reducer.ts</code>.</p> <pre><code class="typescript">// src/app/core/pet-tag.reducer.ts import { Action } from '@ngrx/store'; import { PetTag, initialTag } from './../core/pet-tag.model'; import { SELECT_SHAPE, SELECT_FONT, ADD_TEXT, TOGGLE_CLIP, TOGGLE_GEMS, COMPLETE, RESET } from './pet-tag.actions'; export function petTagReducer(state: PetTag = initialTag, action: Action) { switch (action.type) { case SELECT_SHAPE: return Object.assign({}, state, { shape: action.payload }); case SELECT_FONT: return Object.assign({}, state, { font: action.payload }); case ADD_TEXT: return Object.assign({}, state, { text: action.payload }); case TOGGLE_CLIP: return Object.assign({}, state, { clip: !state.clip }); case TOGGLE_GEMS: return Object.assign({}, state, { gems: !state.gems }); case COMPLETE: return Object.assign({}, state, { complete: action.payload }); case RESET: return Object.assign({}, state, initialTag); default: return state; } } </code></pre> <p>First we import <code>Action</code> from ngrx/store. Then we need the <code>PetTag</code> model and its default state, <code>initialTag</code>. We also need to import the actions we created in the previous step.</p> <p>Now we'll create our <code>petTagReducer()</code> function. The reducer accepts previous <code>state</code> and the dispatched <code>action</code> as arguments. Remember that this is a <em>pure</em> function: inputs determine outputs and the function does not modify global state. This means that when we return anything from the reducer, it either needs to be a new object or it can output an unmodified input (such as in the <code>default</code> case).</p> <p>We'll use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign"><code>Object.assign()</code></a> to return new objects containing the values from source objects in most cases. The sources will be the <em>previous state</em> and objects containing the action <em>payload</em>.</p> <p>The <code>TOGGLE_CLIP</code> and <code>TOGGLE_GEMS</code> actions toggle booleans that are assigned in the <code>initialTag</code> state. Therefore, we don't need a payload when we dispatch these actions; we can simply set the value to its opposite in these cases.</p> <p>We're sending a payload with the <code>COMPLETE</code> action because we want to explicitly set it to <code>true</code>, and only do so once for each tag created. We could use a toggle for this as well, but for clarity, we'll dispatch a specific value as a payload instead.</p> <blockquote><p><strong>Note:</strong> Notice that the <code>RESET</code> case uses the imported <code>initialTag</code> object. Because <code>initialTag</code> is a <em>constant</em>, using it here does not interfere with the reducer's purity.</p></blockquote> <h3>Import Store in App Module</h3> <p>We now have actions and a reducer function. We need to tell our application to use the store and reducer. Open the <code>app.module.ts</code> file and update the following:</p> <pre><code class="js">// src/app/app.module.ts ... import { StoreModule } from '@ngrx/store'; import { petTagReducer } from './core/pet-tag.reducer'; @NgModule({ ..., imports: [ ..., StoreModule.provideStore({ petTag: petTagReducer }) ], ... </code></pre> <p>We can now implement state management with <code>Store</code> updates in our application.</p> <h2>Building the "Create" Page</h2> <p>Our <code>CreateComponent</code>, which we initialized earlier for routing, is going to be a <em>smart</em> component. It will have several <em>dumb</em> child components.</p> <h3>Smart and Dumb Components</h3> <p><strong>Smart components</strong>, also known as <em>container</em> components, are generally root level components. They contain business logic, manage state and subscriptions, and handle events. In our application, they are the routable page components. <code>CreateComponent</code> is a smart component and will implement the logic for our custom tag builder. It will handle events emitted by several dumb child components that make up the tag builder.</p> <p><strong>Dumb components</strong>, also known as <em>presentational</em> components, rely only on the data they are given by parent components. They can emit events that are then handled in the parent, but they do not utilize subscriptions or stores directly. Dumb components are modular and reusable. For example, we will use a tag preview dumb component on both the Create page and the Complete page (<code>CreateComponent</code> and <code>CompleteComponent</code> will be smart components).</p> <h3>"Create" Page Features</h3> <p>Our Create page will have the following features:</p> <ul> <li>Tag shape selector</li> <li>Tag font style selector and tag text field</li> <li>Options to include a clip and add gems</li> <li>Preview of the tag's shape and text</li> <li>A "Done" button that finalizes the custom tag</li> </ul> <h3>"Create" Component TypeScript</h3> <p>Let's start with the <code>CreateComponent</code> class. Open the <code>create.component.ts</code> file:</p> <pre><code class="typescript">// src/app/pages/create/create.component.ts import { Component, OnInit, OnDestroy } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { Subscription } from 'rxjs/Subscription'; import { Store } from '@ngrx/store'; import { SELECT_SHAPE, SELECT_FONT, ADD_TEXT, TOGGLE_CLIP, TOGGLE_GEMS, COMPLETE } from './../../core/pet-tag.actions'; import { PetTag } from './../../core/pet-tag.model'; @Component({ selector: 'app-create', templateUrl: './create.component.html' }) export class CreateComponent implements OnInit, OnDestroy { tagState$: Observable&lt;PetTag&gt;; private tagStateSubscription: Subscription; petTag: PetTag; done = false; constructor(private store: Store&lt;PetTag&gt;) { this.tagState$ = store.select('petTag'); } ngOnInit() { this.tagStateSubscription = this.tagState$.subscribe((state) =&gt; { this.petTag = state; this.done = !!(this.petTag.shape &amp;&amp; this.petTag.text); }); } ngOnDestroy() { this.tagStateSubscription.unsubscribe(); } selectShapeHandler(shape: string) { this.store.dispatch({ type: SELECT_SHAPE, payload: shape }); } selectFontHandler(fontType: string) { this.store.dispatch({ type: SELECT_FONT, payload: fontType }); } addTextHandler(text: string) { this.store.dispatch({ type: ADD_TEXT, payload: text }); } toggleClipHandler() { this.store.dispatch({ type: TOGGLE_CLIP }); } toggleGemsHandler() { this.store.dispatch({ type: TOGGLE_GEMS }); } submit() { this.store.dispatch({ type: COMPLETE, payload: true }); } } </code></pre> <p>This smart component contains the logic for customizing a pet tag.</p> <p>We'll import <code>OnInit</code> and <code>OnDestroy</code>, which will initialize and clean up our store subscription. We'll also need <code>Observable</code> and <code>Subscription</code> from RxJS and <code>Store</code> from ngrx/store. Our actions will be dispatched from this component, so we'll need to import most actions from the actions creator, with the exception of <code>RESET</code>. Finally, we'll import our <code>PetTag</code> model.</p> <p>We won't be needing any CSS for this component, so I've removed the CSS file and reference to it.</p> <p>In the <code>CreateComponent</code> class, <code>tagState$</code> is a <code>PetTag</code>-shaped observable. In the constructor, we'll use the ngrx/store method <code>select()</code> to set <code>this.tagState$</code> to the state observable.</p> <p>Our <code>ngOnInit()</code> lifecycle hook will set up the <em>subscription</em> to the <code>tagState$</code> observable. This will set the <code>petTag</code> property to the <code>state</code> returned by the observable stream each time a new state is pushed. The <code>done</code> property will check for a selected <code>shape</code> and <code>text</code>. These are the two properties of a pet tag that <em>must</em> have truthy values in order for the tag to be "fully customized". The <code>ngOnDestroy()</code> lifecycle hook then cleans up the subscription when the component is destroyed.</p> <p>Finally, we'll create the event handler functions that dispatch actions to the store. These handlers will be executed when the child dumb components emit events to update the custom tag state. Each handler uses the <code>store.dispatch()</code> method to send the desired action <code>type</code> and <code>payload</code> to our reducer.</p> <blockquote><p><strong>Note:</strong> In a more complex app, you may wish to dispatch actions in an <em>actions creator</em> service that can be injected into your components. However, for our small app and for learning purposes, this is unnecessary, so we will dispatch actions directly from our smart components using constants from our actions creator, <code>pet-tag.actions.ts</code>.</p></blockquote> <h3>Aside: Code Linting</h3> <p>Angular's CLI comes with code linting in the form of the <a href="https://github.com/mgechev/codelyzer">codelyzer</a> package. You can lint your project at any time by running the following command:</p> <pre><code class="bash">$ ng lint </code></pre> <p>Let's take the opportunity to lint our pet tags app now. If any errors are found, correct them before proceeding. It's good practice to lint periodically throughout development to maintain clean code. The linting configuration can be found at <code>tslint.json</code> in your project.</p> <h2>Tag Shape Component</h2> <p>Now we'll build our first presentational component: <code>TagShapeComponent</code>. When we're finished with this component, the Create page should look like this:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-tagShape.jpg" alt="Angular app with ngrx/store - &quot;Create&quot; page with smart and dumb components" /></p> <p>Let's generate the scaffolding for this child component with the following Angular CLI command:</p> <pre><code class="bash">$ ng g component pages/create/tag-shape </code></pre> <p>The tag shape component will display four different images with possible shapes: a bone, a rectangle, a circle, and a heart. The user can select which shape they'd like for their custom pet tag.</p> <p>Download all four <code>.svg</code> images from the GitHub repository here: <a href="https://github.com/auth0-blog/pet-tags-ngrx/tree/master/src/assets/images"><code>pet-tags-ngrx/src/assets/images/</code></a>. Place them in your local <code>pet-tags-ngrx/src/assets/images</code> folder.</p> <h3>Tag Shape Component TypeScript</h3> <p>Next, open the <code>tag-shape.component.ts</code> file:</p> <pre><code class="typescript">// src/app/pages/create/tag-shape/tag-shape.component.ts import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-tag-shape', templateUrl: './tag-shape.component.html', styleUrls: ['./tag-shape.component.css'] }) export class TagShapeComponent { tagShape: string; @Output() selectShapeEvent = new EventEmitter(); constructor() { } selectShape(shape: string) { this.selectShapeEvent.emit(shape); } } </code></pre> <p>Add <code>Output</code> and <code>EventEmitter</code> to the <code>@angular/core</code> imports.</p> <p>Our tag shape selector will use radio buttons, so we'll need a property to store the shape <code>ngModel</code>. The shape name options are strings, so we'll set <code>tagShape</code>'s type annotation to <code>string</code>.</p> <p>Next we need an <a href="https://angular.io/docs/ts/latest/guide/template-syntax.html#!#inputs-outputs"><code>@Output()</code> decorator</a> to <a href="https://angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html">emit an event</a> when the user selects a shape. This will send the information to the parent <code>CreateComponent</code>. The <code>selectShape(shape)</code> method will <em>emit</em> the event with shape information. The parent can then <em>handle</em> this event with the <code>selectShapeHandler()</code> method we created earlier in <code>CreateComponent</code>. We'll hook this up to the parent shortly.</p> <h3>Tag Shape Component Template</h3> <p>Before that, we'll add the necessary template markup for our <code>TagShapeComponent</code>. Modify the <code>tag-shape.component.html</code> file as shown:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/create/tag-shape/tag-shape.component.html --&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 text-center&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;h3&gt;</span>Shape<span class="nt">&lt;/h3&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;form-text text-muted&quot;</span><span class="nt">&gt;</span>Choose a tag shape to get started!<span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;label</span> <span class="na">class=</span><span class="s">&quot;tagShape col-sm-3&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;/assets/images/bone.svg&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;radio&quot;</span> <span class="na">name=</span><span class="s">&quot;shape&quot;</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&quot;</span><span class="na">tagShape</span><span class="err">&quot;</span> <span class="err">(</span><span class="na">change</span><span class="err">)=&quot;</span><span class="na">selectShape</span><span class="err">(</span><span class="na">tagShape</span><span class="err">)&quot;</span> <span class="na">value=</span><span class="s">&quot;bone&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;/label&gt;</span> <span class="nt">&lt;label</span> <span class="na">class=</span><span class="s">&quot;tagShape col-sm-3&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;/assets/images/rectangle.svg&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;radio&quot;</span> <span class="na">name=</span><span class="s">&quot;shape&quot;</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&quot;</span><span class="na">tagShape</span><span class="err">&quot;</span> <span class="err">(</span><span class="na">change</span><span class="err">)=&quot;</span><span class="na">selectShape</span><span class="err">(</span><span class="na">tagShape</span><span class="err">)&quot;</span> <span class="na">value=</span><span class="s">&quot;rectangle&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;/label&gt;</span> <span class="nt">&lt;label</span> <span class="na">class=</span><span class="s">&quot;tagShape col-sm-3&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;/assets/images/circle.svg&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;radio&quot;</span> <span class="na">name=</span><span class="s">&quot;shape&quot;</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&quot;</span><span class="na">tagShape</span><span class="err">&quot;</span> <span class="err">(</span><span class="na">change</span><span class="err">)=&quot;</span><span class="na">selectShape</span><span class="err">(</span><span class="na">tagShape</span><span class="err">)&quot;</span> <span class="na">value=</span><span class="s">&quot;circle&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;/label&gt;</span> <span class="nt">&lt;label</span> <span class="na">class=</span><span class="s">&quot;tagShape col-sm-3&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;/assets/images/heart.svg&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;radio&quot;</span> <span class="na">name=</span><span class="s">&quot;shape&quot;</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&quot;</span><span class="na">tagShape</span><span class="err">&quot;</span> <span class="err">(</span><span class="na">change</span><span class="err">)=&quot;</span><span class="na">selectShape</span><span class="err">(</span><span class="na">tagShape</span><span class="err">)&quot;</span> <span class="na">value=</span><span class="s">&quot;heart&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;/label&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>We'll create radio options for each of our four shapes along with their images. When any input is selected, we'll use the <code>(change)</code> event to fire our method emitting the <code>selectShapeEvent</code> with the <code>tagShape</code> as its argument.</p> <h3>Tag Shape Component Styles</h3> <p>This component could use a little bit of styling beyond Bootstrap, so add the following to the <code>tag-shape.component.css</code> file:</p> <pre><code class="css">/* src/app/pages/create/tag-shape/tag-shape.component.css */ :host { display: block; margin: 20px 0; } .tagShape { padding: 10px; text-align: center; } img { display: block; height: auto; margin: 0 auto; max-height: 50px; max-width: 100%; width: auto; } </code></pre> <blockquote><p><strong>Note:</strong> The <a href="https://angular.io/docs/ts/latest/guide/component-styles.html#!#special-selectors"><code>:host</code> pseudo-class selector</a> targets the component's <em>host</em> element, <code>&lt;app-tag-shape&gt;</code> in this case.</p></blockquote> <h3>Add Tag Shape Component to the Create Page</h3> <p>Finally, we'll implement our <code>TagShapeComponent</code> by adding it to the our smart <code>CreateComponent</code> template. Open the <code>create.component.html</code> file and replace the boilerplate markup with the following:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/create/create.component.html --&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 text-center lead&quot;</span><span class="nt">&gt;</span> Hello! Create a customized tag for your pet. <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;app-tag-shape</span> <span class="err">(</span><span class="na">selectShapeEvent</span><span class="err">)=&quot;</span><span class="na">selectShapeHandler</span><span class="err">($</span><span class="na">event</span><span class="err">)&quot;</span><span class="nt">&gt;&lt;/app-tag-shape&gt;</span></code></pre></div> <p>Our parent component is now listening for the <code>selectShapeEvent</code> from the tag shape child and handling it by executing the <code>selectShapeHandler()</code> method we created in our <code>CreateComponent</code> class earlier. If you recall, that method dispatches the <code>SELECT_SHAPE</code> action to the store and looks like this:</p> <pre><code class="typescript">selectShapeHandler(shape: string) { this.store.dispatch({ type: SELECT_SHAPE, payload: shape }); } </code></pre> <p>Our app now updates state when the user selects a shape for their custom pet tag!</p> <h2>Tag Text Component</h2> <p>Next we'll create a child component that lets the user choose a font style and enter the text they'd like on their pet tag. Our Create page will look like this once we've added our tag text component:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-text.jpg" alt="Angular app with ngrx/store dumb component tag text" /></p> <p>Generate the component scaffolding with the following command:</p> <pre><code class="bash">$ ng g component pages/create/tag-text </code></pre> <h3>Tag Text Component TypeScript</h3> <p>Now open the <code>tag-text.component.ts</code> file:</p> <pre><code class="typescript">// src/app/pages/create/tag-text/tag-text.component.ts import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-tag-text', templateUrl: './tag-text.component.html', styleUrls: ['./tag-text.component.css'] }) export class TagTextComponent { tagTextInput = ''; fontType = 'sans-serif'; @Output() selectFontEvent = new EventEmitter; @Output() addTextEvent = new EventEmitter; constructor() { } selectFont(fontType: string) { this.selectFontEvent.emit(fontType); } addText(text: string) { this.addTextEvent.emit(text); } } </code></pre> <p>This component works the same way as our <code>TagShapeComponent</code>, so it looks very similar. We'll import <code>Output</code> and <code>EventEmitter</code> and create properties for the <code>tagTextInput</code> and <code>fontType</code> based on user inputs.</p> <blockquote><p><strong>Note:</strong> We aren't adding <code>string</code> type annotations to our properties because declaring initial values allows types to be <em>inferred</em> automatically.</p></blockquote> <p>We'll emit events when the user updates the tag text or changes the font style selection.</p> <h3>Tag Text Component Template</h3> <p>Our tag text component template, <code>tag-text.component.html</code>, should look like this:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/create/tag-text/tag-text.component.html --&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 text-center&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;h3&gt;</span>Text<span class="nt">&lt;/h3&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;form-text text-muted&quot;</span><span class="nt">&gt;</span> Select your desired font style and enter your pet&#39;s name.<span class="nt">&lt;br&gt;</span> You can see what your tag will look like in the preview below. <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;form-group row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;label</span> <span class="na">for=</span><span class="s">&quot;font&quot;</span> <span class="na">class=</span><span class="s">&quot;col-sm-2 offset-sm-2 col-form-label&quot;</span><span class="nt">&gt;</span>Font:<span class="nt">&lt;/label&gt;</span> <span class="nt">&lt;select</span> <span class="na">id=</span><span class="s">&quot;font&quot;</span> <span class="na">name=</span><span class="s">&quot;font&quot;</span> <span class="na">class=</span><span class="s">&quot;form-control col-sm-6&quot;</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&quot;</span><span class="na">fontType</span><span class="err">&quot;</span> <span class="err">(</span><span class="na">change</span><span class="err">)=&quot;</span><span class="na">selectFont</span><span class="err">(</span><span class="na">fontType</span><span class="err">)&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">&quot;sans-serif&quot;</span><span class="nt">&gt;</span>Sans-serif<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">&quot;serif&quot;</span><span class="nt">&gt;</span>Serif<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;/select&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;form-group row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;label</span> <span class="na">for=</span><span class="s">&quot;tagText&quot;</span> <span class="na">class=</span><span class="s">&quot;col-sm-2 offset-sm-2 col-form-label&quot;</span><span class="nt">&gt;</span>Text:<span class="nt">&lt;/label&gt;</span> <span class="nt">&lt;input</span> <span class="na">id=</span><span class="s">&quot;tagText&quot;</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span> <span class="na">class=</span><span class="s">&quot;form-control col-sm-6&quot;</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&quot;</span><span class="na">tagTextInput</span><span class="err">&quot;</span> <span class="err">(</span><span class="na">input</span><span class="err">)=&quot;</span><span class="na">addText</span><span class="err">(</span><span class="na">tagTextInput</span><span class="err">)&quot;</span> <span class="na">maxlength=</span><span class="s">&quot;8&quot;</span> <span class="nt">/&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>We're using a <code>&lt;select&gt;</code> element and a text input field to let the user choose options for their custom pet tag. The <code>ngModel</code>s are updated on user input and events are emitted to the parent component.</p> <h3>Tag Text Component Styles</h3> <p>We'll add just one ruleset to <code>tag-text.component.css</code>:</p> <pre><code class="css">/* src/app/pages/create/tag-text/tag-text.component.css */ :host { display: block; margin: 20px 0; } </code></pre> <h3>Add Tag Text Component to the Create Page</h3> <p>Finally, we need to add the <code>TagTextComponent</code> to the Create page:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/create/create.component.html --&gt;</span> ... <span class="nt">&lt;app-tag-text</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;petTag.shape&quot;</span> <span class="err">(</span><span class="na">selectFontEvent</span><span class="err">)=&quot;</span><span class="na">selectFontHandler</span><span class="err">($</span><span class="na">event</span><span class="err">)&quot;</span> <span class="err">(</span><span class="na">addTextEvent</span><span class="err">)=&quot;</span><span class="na">addTextHandler</span><span class="err">($</span><span class="na">event</span><span class="err">)&quot;</span><span class="nt">&gt;&lt;/app-tag-text&gt;</span></code></pre></div> <p>Notice that we're adding an <a href="https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngIf"><code>*ngIf</code> structural directive</a> to the <code>&lt;app-tag-text&gt;</code> element. We only want this component to appear once the user has selected a shape. This is because we're going to create a preview of the tag soon, and it doesn't make sense to show a preview unless a shape has already been selected. This prevents users from entering text or extra tag options <em>before</em> choosing a shape.</p> <p>We'll listen for <code>TagTextComponent</code> to emit the <code>selectFontEvent</code> and <code>addTextEvent</code> events and handle them with the methods we added to <code>CreateComponent</code> earlier, which dispatch the <code>SELECT_FONT</code> and <code>ADD_TEXT</code> actions and payloads to the reducer:</p> <pre><code class="typescript">selectFontHandler(fontType: string) { this.store.dispatch({ type: SELECT_FONT, payload: fontType }); } addTextHandler(text: string) { this.store.dispatch({ type: ADD_TEXT, payload: text }); } </code></pre> <h2>Tag Extras Component</h2> <p>Now we'll let the user choose whether they want a few extras for their custom pet tag. Once we've implemented the tag extras component, our Create page will look like this:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-tagExtras.jpg" alt="Angular app with ngrx/store dumb component tag extras" /></p> <p>Create the scaffolding for <code>TagExtrasComponent</code> with this command:</p> <pre><code class="bash">$ ng g component pages/create/tag-extras </code></pre> <h3>Tag Extras Component TypeScript</h3> <p>Open <code>tag-extras.component.ts</code>:</p> <pre><code class="typescript">// src/app/pages/create/tag-extras/tag-extras.component.ts import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-tag-extras', templateUrl: './tag-extras.component.html', styleUrls: ['./tag-extras.component.css'] }) export class TagExtrasComponent { tagClip: boolean; gems: boolean; @Output() toggleClipEvent = new EventEmitter; @Output() toggleGemsEvent = new EventEmitter; constructor() { } toggleClip() { this.toggleClipEvent.emit(); } toggleGems() { this.toggleGemsEvent.emit(); } } </code></pre> <p>This should look very familiar by now. "Extras" are options to include a tag clip or gems with our pet tag, so they are <code>boolean</code> values serving as <code>ngModel</code>s for checkboxes.</p> <h3>Tag Extras Component Template</h3> <p>Add the necessary markup to the <code>tag-extras.component.html</code> template:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/create/tag-extras/tag-extras.component.html --&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 text-center&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;h3&gt;</span>Extras<span class="nt">&lt;/h3&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;form-text text-muted&quot;</span><span class="nt">&gt;</span>Select any extras you would like to add.<span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;col-sm-4 offset-sm-2&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;label&gt;</span> <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;checkbox&quot;</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&quot;</span><span class="na">tagClip</span><span class="err">&quot;</span> <span class="err">(</span><span class="na">change</span><span class="err">)=&quot;</span><span class="na">toggleClip</span><span class="err">()&quot;</span><span class="nt">&gt;</span> Include tag clip <span class="nt">&lt;/label&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;col-sm-4&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;label&gt;</span> <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;checkbox&quot;</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&quot;</span><span class="na">gems</span><span class="err">&quot;</span> <span class="err">(</span><span class="na">change</span><span class="err">)=&quot;</span><span class="na">toggleGems</span><span class="err">()&quot;</span><span class="nt">&gt;</span> Add gems <span class="nt">&lt;/label&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>We'll use checkboxes to let the user choose whether they'd like to add extras.</p> <h3>Tag Extras Component Styles</h3> <p>We want to add a bottom border to our host element since this is the last component before we'll show the customized tag preview. Add the following to the <code>tag-extras.component.css</code> file:</p> <pre><code class="css">/* src/app/pages/create/tag-extras/tag-extras.component.css */ :host { border-bottom: 1px solid #ccc; display: block; margin: 20px 0; padding-bottom: 20px; } </code></pre> <h3>Add Tag Extras Component to the Create Page</h3> <p>Let's add the tag extras component to <code>create.component.html</code> like so:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/create/create.component.html --&gt;</span> ... <span class="nt">&lt;app-tag-extras</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;petTag.shape&quot;</span> <span class="err">(</span><span class="na">toggleClipEvent</span><span class="err">)=&quot;</span><span class="na">toggleClipHandler</span><span class="err">()&quot;</span> <span class="err">(</span><span class="na">toggleGemsEvent</span><span class="err">)=&quot;</span><span class="na">toggleGemsHandler</span><span class="err">()&quot;</span><span class="nt">&gt;&lt;/app-tag-extras&gt;</span></code></pre></div> <p>Like the tag text component, we'll only display the extras if the user has already selected a shape. The <code>toggleClipEvent</code> and <code>toggleGemsEvent</code> events are handled by the <code>CreateComponent</code> methods we created earlier to dispatch the <code>TOGGLE_CLIP</code> and <code>TOGGLE_GEMS</code> actions to the reducer:</p> <pre><code class="typescript">toggleClipHandler() { this.store.dispatch({ type: TOGGLE_CLIP }); } toggleGemsHandler() { this.store.dispatch({ type: TOGGLE_GEMS }); } </code></pre> <p>Since these are boolean toggles, no payloads are necessary. Recall that we set up the reducer to use the <em>previous</em> state to determine the <em>next</em> state in these cases.</p> <h2>Tag Preview Component</h2> <p>Now let's create a component that shows a simple preview of the pet tag as it's being created. After we've implemented the tag preview presentational component, we'll be able to view the tag like so:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-preview.jpg" alt="Angular app with ngrx/store dumb component preview" /></p> <p>Let's scaffold the <code>TagPreviewComponent</code>. This component will be a child of both the Create and Complete pages, so let's create it in the root of the <code>app</code> folder like so:</p> <pre><code class="bash">$ ng g component tag-preview </code></pre> <h3>Tag Preview Component TypeScript</h3> <p>Open <code>tag-preview.component.ts</code> and add this code:</p> <pre><code class="typescript">// src/app/tag-preview/tag-preview.component.ts import { Component, OnChanges, Input } from '@angular/core'; import { PetTag } from './../core/pet-tag.model'; @Component({ selector: 'app-tag-preview', templateUrl: './tag-preview.component.html', styleUrls: ['./tag-preview.component.css'] }) export class TagPreviewComponent implements OnChanges { @Input() petTag: PetTag; imgSrc = ''; tagClipText: string; gemsText: string; constructor() { } ngOnChanges() { this.imgSrc = `/assets/images/${this.petTag.shape}.svg`; this.tagClipText = this.boolToText(this.petTag.clip); this.gemsText = this.boolToText(this.petTag.gems); } private boolToText(bool: boolean) { return bool ? 'Yes' : 'No'; } } </code></pre> <p><code>TagPreviewComponent</code> is a dumb component that takes input from the <code>CreateComponent</code> parent and displays it, but does not produce any outputs. Import the <code>Input</code> decorator and the <code>OnChanges</code> lifecycle hook. We also need the <code>PetTag</code> model so we know what shape to expect from the input.</p> <p>The <code>TagPreviewComponent</code> class needs to implement <a href="https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges"><code>OnChanges</code></a> so we can take advantage of the <code>ngOnChanges()</code> method. <code>ngOnChanges()</code> executes each time changes to the component's <em>inputs</em> are detected. We'll need this in order to update our preview whenever the user modifies their custom pet tag.</p> <p>The <code>@Input() petTag</code> that we'll be receiving from the parent component is the state object, which has the shape declared by the <code>PetTag</code> model we defined at the beginning. For example, it might look something like this:</p> <pre><code class="js">{ shape: 'bone', font: 'serif', text: 'Fawkes', clip: true, gems: false, complete: false } </code></pre> <p>We want to display this data in a user-friendly, visual way. We'll do this by showing an image of the tag with user-inputted text and notes about whether the user has chosen to include a clip or gems.</p> <p>We'll set the image source as well as the tag clip and gems option text ("Yes" or "No") when changes to the input are detected. The input is provided by <code>CreateComponent</code>'s subscription to its <code>tagState$</code> store observable.</p> <h3>Tag Preview Component Template</h3> <p>Open the <code>tag-preview.component.html</code> file and add:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/tag-preview/tag-preview.component.html --&gt;</span> <span class="nt">&lt;div</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;petTag.shape&quot;</span> <span class="na">class=</span><span class="s">&quot;row tagView-wrapper&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;col-sm-12&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;tagView {{petTag.shape}}&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;img</span> <span class="err">[</span><span class="na">src</span><span class="err">]=&quot;</span><span class="na">imgSrc</span><span class="err">&quot;</span> <span class="nt">/&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;text {{petTag.font}}&quot;</span><span class="nt">&gt;</span> {{petTag.text}} <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;text-center&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;strong&gt;</span>Tag clip:<span class="nt">&lt;/strong&gt;</span> {{tagClipText}}<span class="nt">&lt;br&gt;</span> <span class="nt">&lt;strong&gt;</span>Gems:<span class="nt">&lt;/strong&gt;</span> {{gemsText}} <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>The preview will show if there is a shape. We'll display the appropriate shape SVG image and a <code>shape</code> class. We'll also display the pet tag text in the appropriate font using a class with the <code>font</code> value. Finally, we'll print out whether the user has chosen to include a tag clip or gems.</p> <h3>Tag Preview Component Styles</h3> <p>Recall that there are four possible tag shapes: a bone, rectangle, circle, and heart. In order to display a nice preview with any of these shapes, we'll need some additional styling. Open the <code>tag-preview.component.css</code> file:</p> <pre><code class="css">/* src/app/tag-preview/tag-preview.component.css */ .tagView-wrapper { padding-top: 20px; } .tagView { height: 284px; position: relative; width: 100%; } img { display: block; height: 100%; margin: 0 auto; width: auto; } .text { font-size: 48px; position: absolute; text-align: center; text-shadow: 1px 1px 0 rgba(255,255,255,.8); top: 99px; width: 100%; } .bone .text, .rectangle .text { font-size: 74px; top: 85px; } .sans-serif { font-family: Arial, Helvetica, sans-serif; } .serif { font-family: Georgia, 'Times New Roman', Times, serif; } </code></pre> <p>After some basic styling to position the preview elements, we'll set the font sizes based on shape and the font families based on the user's selected font style.</p> <p>Now our <code>&lt;app-tag-preview&gt;</code> is ready to be added to the container component templates.</p> <h3>Add Tag Preview Component to the Create Page</h3> <p>Open <code>create.component.html</code> and let's add the tag preview child component at the bottom:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/create/create.component.html --&gt;</span> ... <span class="nt">&lt;app-tag-preview</span> <span class="err">[</span><span class="na">petTag</span><span class="err">]=&quot;</span><span class="na">petTag</span><span class="err">&quot;</span><span class="nt">&gt;&lt;/app-tag-preview&gt;</span></code></pre></div> <p>Square brackets (<code>[...]</code>) denote one-way <a href="https://angular.io/docs/ts/latest/guide/template-syntax.html#!#binding-syntax">binding syntax</a>. We already established our local <code>petTag</code> property in the <code>CreateComponent</code>'s <code>tagStateSubscription</code>, and we're passing this to the tag preview component.</p> <p>Now we should be able to see live changes in the tag preview as we customize our tag:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-preview-animated.gif" alt="Angular with ngrx/store preview changing live" /></p> <h2>Submit Completed Tag</h2> <p>Now that we have our tag builder and preview built, let's add a "Done" button to submit the finished tag to the Complete page. When implemented, our Create page should look like the following:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-tagDone.jpg" alt="Angular app with ngrx/store and submit button" /></p> <p>We've already created a <code>submit()</code> method in <code>CreateComponent</code> that dispatches the <code>COMPLETE</code> action and payload to the reducer. All we need to do is create a button that calls this method in our <code>create.component.html</code> template:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/create/create.component.html --&gt;</span> ... <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 text-center&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;form-text text-muted&quot;</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;petTag.shape&quot;</span><span class="nt">&gt;</span> Preview your customized tag above.<span class="nt">&lt;br&gt;</span> If you&#39;re happy with the results,<span class="nt">&lt;br&gt;</span> click the button below to finish! <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;p&gt;</span> <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">&quot;btn btn-success btn-lg&quot;</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;petTag.shape&quot;</span> <span class="err">[</span><span class="na">disabled</span><span class="err">]=&quot;!</span><span class="na">done</span><span class="err">&quot;</span> <span class="err">(</span><span class="na">click</span><span class="err">)=&quot;</span><span class="na">submit</span><span class="err">()&quot;</span> <span class="na">routerLink=</span><span class="s">&quot;/complete&quot;</span><span class="nt">&gt;</span>Done<span class="nt">&lt;/button&gt;</span> <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>We'll disable the button if the <code>done</code> property is falsey. We declared <code>done</code> in the <code>CreateComponent</code>'s <code>tagStateSubscription</code> earlier. It looks like this:</p> <pre><code class="typescript">this.done = !!(this.petTag.shape &amp;&amp; this.petTag.text); </code></pre> <p>The tag can be considered ready for submission if it has a shape and text. If the user has added these, then they will be able to click the button to submit their tag. We'll also route the user to the Complete page.</p> <h2>"Complete" Page Component</h2> <p>We scaffolded the Complete page when we set up the main routes for our app. Once we've implemented the component, the Complete page will look something like this after the user has created a custom pet tag:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-complete.jpg" alt="Angular app with ngrx/store complete page" /></p> <h3>"Complete" Component TypeScript</h3> <p>Now let's open the <code>complete.component.ts</code> smart component and implement the following code:</p> <pre><code class="typescript">// src/app/pages/complete/complete.component.ts import { Component, OnInit, OnDestroy } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { Subscription } from 'rxjs/Subscription'; import { Store } from '@ngrx/store'; import { RESET } from './../../core/pet-tag.actions'; import { PetTag } from './../../core/pet-tag.model'; @Component({ selector: 'app-complete', templateUrl: './complete.component.html' }) export class CompleteComponent implements OnInit, OnDestroy { tagState$: Observable&lt;PetTag&gt;; private tagStateSubscription: Subscription; petTag: PetTag; constructor(private store: Store&lt;PetTag&gt;) { this.tagState$ = store.select('petTag'); } ngOnInit() { this.tagStateSubscription = this.tagState$.subscribe((state) =&gt; { this.petTag = state; }); } ngOnDestroy() { this.tagStateSubscription.unsubscribe(); } newTag() { this.store.dispatch({ type: RESET }); } } </code></pre> <p><code>CompleteComponent</code> is a routable smart (container) component. We'll be managing a store subscription, so we need to import <code>OnInit</code>, <code>OnDestroy</code>, <code>Observable</code>, <code>Subscription</code>, and <code>Store</code>. We'll also have a link the user can click to start over and create a new tag. This will set the state back to its initial values, so we need to import the <code>RESET</code> action, as well as <code>PetTag</code> and <code>initialTag</code> from our model.</p> <p>This component doesn't need any styling beyond Bootstrap, so we'll delete the <code>complete.component.css</code> file and remove the reference to it.</p> <p>Like in our <code>CreateComponent</code> smart component, we'll create a <code>tagState$</code> observable, <code>tagStateSubscription</code>, and a local <code>petTag</code> property. We'll also create an <code>emptyTag</code> property with the <code>PetTag</code> type. We'll set its value to <code>initialTag</code>.</p> <p>In the constructor, we'll assign <code>tagState$</code> as the store observable. Then in <code>ngOnInit()</code>, we'll <em>subscribe</em> to the observable and set the <code>petTag</code> property. In the <code>ngOnDestroy()</code> method, we'll clean up our subscribtion by <em>unsubscribing</em>.</p> <p>Finally, our <code>newTag()</code> method will dispatch the <code>RESET</code> action. This "resets" the application state so that a new tag can be customized.</p> <h3>"Complete" Component Template</h3> <p>Our <code>CompleteComponent</code>'s HTML template will look like this:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/complete/complete.component.html --&gt;</span> <span class="nt">&lt;div</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;petTag.complete&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 alert alert-success&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;strong&gt;</span>Congratulations!<span class="nt">&lt;/strong&gt;</span> You&#39;ve completed a pet ID tag for <span class="nt">&lt;strong&gt;</span>{{petTag.text}}<span class="nt">&lt;/strong&gt;</span>. Would you like to <span class="nt">&lt;a</span> <span class="err">(</span><span class="na">click</span><span class="err">)=&quot;</span><span class="na">newTag</span><span class="err">()&quot;</span> <span class="na">routerLink=</span><span class="s">&quot;/create&quot;</span> <span class="na">class=</span><span class="s">&quot;alert-link&quot;</span><span class="nt">&gt;</span>create another?<span class="nt">&lt;/a&gt;</span> <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;app-tag-preview</span> <span class="err">[</span><span class="na">petTag</span><span class="err">]=&quot;</span><span class="na">petTag</span><span class="err">&quot;</span><span class="nt">&gt;&lt;/app-tag-preview&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;div</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;!petTag.complete&quot;</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 alert alert-danger&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;strong&gt;</span>Oops!<span class="nt">&lt;/strong&gt;</span> You haven&#39;t customized a tag yet. <span class="nt">&lt;a</span> <span class="na">routerLink=</span><span class="s">&quot;/create&quot;</span> <span class="na">class=</span><span class="s">&quot;alert-link&quot;</span><span class="nt">&gt;</span>Click here to create one now.<span class="nt">&lt;/a&gt;</span> <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>First we'll show a success alert that congratulates the user on creating a custom tag for their pet, grabbing the pet's name from the <code>petTag</code> state object's <code>text</code>. We'll provide a link to create another tag that executes the <code>newTag()</code> method and routes the visitor back to the Create page to start fresh.</p> <p>Then we'll show the tag preview component and pass the <code>petTag</code> object to it: <code>&lt;app-tag-preview [petTag]="petTag"&gt;</code></p> <p>Finally, we'll need to show an error message if the user manually navigates to the <code>/complete</code> route without having finished customizing a tag. A link should be available to take them back to the Create page. The Complete page error should look like this:</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-completeError.jpg" alt="Angular app with ngrx/store complete page with error message" /></p> <p>We now have the primary functionality of our Custom Pet Tags application set up and working!</p> <h2>Authentication with Auth0</h2> <p>We'll now protect our application so that only authenticated users can access it. We already set up a "Log In" button in our <code>HomeComponent</code>, but right now it just navigates to the Create page. Let's hook up the authentication functionality using <a href="https://auth0.com">Auth0</a>.</p> <p><img src="https://cdn.auth0.com/blog/ngrx/ngrx-auth0.jpg" alt="Angular app with ngrx/store and authentication with Auth0" /></p> <h3>Sign Up for Auth0</h3> <p>The first thing we'll need is an Auth0 account. Follow these simple steps to get started:</p> <ol> <li>Sign up for a <a href="javascript:signup()">free Auth0 account</a>.</li> <li>In your <strong>Auth0 Dashboard</strong>, <a href="https://manage.auth0.com/#/clients/create">create a new client</a>.</li> <li>Name your new app and select "Single Page Web Applications".</li> <li>In the <strong>Settings</strong> for your newly created app, add <code>http://localhost:4200</code> to the Allowed Callback URLs and Allowed Origins (CORS).</li> <li>If you'd like, you can <a href="https://manage.auth0.com/#/connections/social">set up some social connections</a>. You can then enable them for your app in the <strong>Client</strong> options under the <strong>Connections</strong> tab. The example shown in the screenshot above utilizes username/password database, Facebook, Google, and Twitter.</li> </ol> <h3>Set Up Dependencies</h3> <p>Auth0 authenticates using <a href="https://jwt.io">JSON Web Tokens</a>. Let's install the <a href="https://github.com/auth0/angular2-jwt">angular2-jwt</a> helper library using npm:</p> <pre><code class="bash">$ npm install angular2-jwt --save </code></pre> <p>We also need the <a href="https://auth0.com/docs/libraries/lock">Auth0 Lock</a> library. This provides the login widget and methods. We'll include the CDN-provided script for Lock in the <code>&lt;head&gt;</code> of our <code>index.html</code> file, like so:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/index.html --&gt;</span> ... <span class="c">&lt;!-- Auth0 --&gt;</span> <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;https://cdn.auth0.com/js/lock/10.11.0/lock.min.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span> <span class="nt">&lt;/head&gt;</span> ...</code></pre></div> <h3>Create an Auth Service</h3> <p>Next we'll create a service to manage authentication. User authentication will be handled via local storage and it won't be necessary to create another store. In a more complex application, you may wish to make a user store, but for our purposes, a simple service will work just fine.</p> <p>Let's create an authentication service:</p> <pre><code class="bash">$ ng g service core/Auth </code></pre> <p>Our <code>auth.service.ts</code> file should look like this:</p> <pre><code class="typescript">// src/app/core/auth.service.ts import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { tokenNotExpired } from 'angular2-jwt'; // avoid name not found warnings declare var Auth0Lock: any; declare var localStorage: any; @Injectable() export class AuthService { lock = new Auth0Lock('[CLIENT_ID]', '[CLIENT_DOMAIN]', { auth: { redirectUrl: 'http://localhost:4200', responseType: 'token' } }); userProfile: Object; constructor(private router: Router) { this.userProfile = JSON.parse(localStorage.getItem('profile')); // add callback for lock 'hash_parsed' event this.lock.on('hash_parsed', (authResult) =&gt; { if (authResult &amp;&amp; authResult.idToken) { localStorage.setItem('id_token', authResult.idToken); // get user profile this.lock.getProfile(authResult.idToken, (error, profile) =&gt; { if (error) { throw Error('There was an error retrieving profile data.'); } localStorage.setItem('profile', JSON.stringify(profile)); this.userProfile = profile; // on successful authentication and profile retrieval, go to /create route this.router.navigate(['/create']); }); } else if (authResult &amp;&amp; !authResult.idToken) { // authentication failed: show Lock widget and log a warning this.login(); console.warn(`There was an error authenticating: ${authResult}`); } }); } login() { this.lock.show(); } logout() { localStorage.removeItem('id_token'); localStorage.removeItem('profile'); } get authenticated(): boolean { // search for an item in localStorage with key == 'id_token' return tokenNotExpired(); } } </code></pre> <p>We'll import <code>Router</code> to handle redirection after login and <code>tokenNotExpired</code> (from <code>angular2-jwt</code>) to make sure our user still has a valid JWT.</p> <p>To avoid TypeScript warnings, we need to declare types for <code>Auth0Lock</code> and <code>localStorage</code>. We'll be able to <a href="https://angular.io/docs/ts/latest/api/core/index/Injectable-decorator.html"><em>inject</em></a> our <code>AuthService</code> wherever we need access to its properties and methods (ie., in other components).</p> <p>In the <code>AuthService</code> class, we need to create a new Lock instance with our Auth0 client's ID and domain. These can be found in your Auth0 dashboard settings for the Single Page Application client you just set up. Replace <code>[CLIENT_ID]</code> and <code>[CLIENT_DOMAIN]</code> with your personalized information. We'll pass a configuration object to our Lock instance with a <code>redirectUrl</code> and <code>responseType</code>.</p> <blockquote><p><strong>Note:</strong> You can read more about <a href="https://auth0.com/docs/libraries/lock/v10/customization">Lock configuration in the docs</a>.</p></blockquote> <p>We'll create a property to store the user's profile information that we'll retrieve when a visitor authenticates. This has an <code>Object</code> type.</p> <p>Because we'll be storing the user's profile and access token in local storage, the first thing we'll do in our constructor is check for an existing profile. If there's a profile in storage already, we'll set the <code>userProfile</code> property.</p> <p>Next we need to listen to the Lock instance for the <a href="https://github.com/auth0/lock#onevent-callback"><code>hash_parsed</code> event</a>. This is a low-level event that we'll use (instead of the <code>authenticated</code> event) in order to handle single page app redirection upon login.</p> <p>If an <code>idToken</code> is present, we'll save it to <code>localStorage</code> and use it to retrieve the user's profile information. Once the profile has been successfully retrieved, we can save it to <code>localStorage</code> and redirect to the Create page. If there is no <code>idToken</code> returned, we'll reinitialize the login and log an authentication warning.</p> <p>Finally, we'll implement three methods: <code>login()</code>, <code>logout()</code>, and the <code>authenticated</code> accessor. The <code>login()</code> method will simply display the Lock widget so the user can log in with Auth0. The <code>logout()</code> method removes the user's token and profile from local storage. The <code>authenticated</code> getter checks the JWT to see if it has expired and returns a boolean representing authentication status.</p> <p>We're now ready to use <code>AuthService</code> to authenticate users in our application.</p> <h3>Provide Auth Service in App Module</h3> <p>We're going to provide <code>AuthService</code> globally to the application in our <code>app.module.ts</code>:</p> <pre><code class="typescript">// src/app/app.module.ts ... import { AuthService } from './core/auth.service'; @NgModule({ ... providers: [ AuthService ], ... </code></pre> <p>Import <code>AuthService</code> in the app module and add it to the <code>providers</code> array. We can now inject this service elsewhere in our application.</p> <h3>Home Component Login</h3> <p>The first thing we'll implement with <code>AuthService</code> is the "Log In" button we created on the homepage.</p> <p>Open <code>home.component.ts</code>:</p> <pre><code class="typescript">// src/app/pages/home/home.component.ts ... import { Router } from '@angular/router'; import { AuthService } from './../../core/auth.service'; ... constructor(public auth: AuthService, private router: Router) { } ngOnInit() { if (this.auth.authenticated) { this.router.navigate(['/create']); } } } </code></pre> <p>Import <code>AuthService</code> and <code>Router</code> and make them available to the constructor. <code>auth</code> should be <em>public</em> because we need to access its methods in the Home template. Using the <code>OnInit</code> lifecycle hook, we'll check if the user is authenticated. If so, we'll navigate to the Create page so the user can skip the login on the homepage.</p> <p>Now open <code>home.component.html</code>:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/home/home.component.html --&gt;</span> ... <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">&quot;btn btn-lg btn-primary&quot;</span> <span class="err">(</span><span class="na">click</span><span class="err">)=&quot;</span><span class="na">auth</span><span class="err">.</span><span class="na">login</span><span class="err">()&quot;</span><span class="nt">&gt;</span>Log In<span class="nt">&lt;/button&gt;</span> ...</code></pre></div> <p>We'll update the "Log In" button so that clicking it executes the <code>AuthService</code> <code>login()</code> method and shows the Auth0 Lock login box.</p> <p>We now have a functioning login in our app!</p> <h3>Complete Component Logout</h3> <p>We also need a way for our users to log out. We'll add a "Log Out" button to the Complete page component.</p> <p>Open <code>complete.component.ts</code>:</p> <pre><code class="typescript">// src/app/pages/complete/complete.component.ts ... import { AuthService } from './../../core/auth.service'; ... constructor(..., public auth: AuthService) { } ... </code></pre> <p>We'll import <code>AuthService</code> and make it publicly available to the constructor so we can access its properties and methods in the HTML template.</p> <p>Next open <code>complete.component.html</code>:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/complete/complete.component.html --&gt;</span> ... <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 alert alert-success&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;strong&gt;</span>Congratulations, {{auth.userProfile.name}}!<span class="nt">&lt;/strong&gt;</span> ... <span class="nt">&lt;/p&gt;</span> ... <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 text-center&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;a</span> <span class="na">class=</span><span class="s">&quot;btn btn-danger btn-lg&quot;</span> <span class="err">(</span><span class="na">click</span><span class="err">)=&quot;</span><span class="na">auth</span><span class="err">.</span><span class="na">logout</span><span class="err">()&quot;</span> <span class="na">routerLink=</span><span class="s">&quot;/&quot;</span><span class="nt">&gt;</span>Log Out<span class="nt">&lt;/a&gt;</span> <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>We'll greet the user by name and add a "Log Out" button to call the <code>AuthService</code>'s <code>logout()</code> method and redirect the user back to the homepage.</p> <h3>Greet User in Create Component</h3> <p>For a personal touch, we'll also greet the user by name on the Create page. Open <code>create.component.ts</code>:</p> <pre><code class="typescript">// src/app/pages/create/create.component.ts ... import { AuthService } from './../../core/auth.service'; ... constructor(..., public auth: AuthService) { } ... </code></pre> <p>Import the <code>AuthService</code> and make it publicly available in the constructor.</p> <p>Next open the <code>create.component.html</code> template and add a personalized greeting after <code>Hello</code>:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- src/app/pages/create/create.component.html --&gt;</span> <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">&quot;col-sm-12 text-center lead&quot;</span><span class="nt">&gt;</span> Hello, {{auth.userProfile.name}}! Create a customized tag for your pet. <span class="nt">&lt;/p&gt;</span> ...</code></pre></div> <p>Now our app feels more personalized.</p> <h3>Create a Route Guard</h3> <p>We can log in and out of our app, but that doesn't offer much more than simple personalization at the moment. Any visitor can still navigate to any route they wish if they simply enter URLs manually. Let's implement a route guard so that routes are activated only for logged in users.</p> <blockquote><p><strong>Important Security Note:</strong> In our simple demo app, authentication is simply for routing because we don't have a server component. <em>Client-side authentication does not confer security features.</em> If you're building an authenticated app with a server, you'll need to authorize API requests with the JWT provided by Auth0 using an <code>Authorization</code> header. You can read more on how to do this in the <a href="https://auth0.com/docs/quickstart/spa/angular2/08-calling-apis">Auth0 Angular 2 Calling APIs docs</a>. The <a href="https://github.com/auth0/angular2-jwt"><code>angular2-jwt</code> package</a> we installed provides <code>AUTH_PROVIDERS</code> to help accomplish this. When making API calls in an authenticated app, we would secure our server requests <em>in addition to</em> implementing presentational route guards. You can read more about securing a Node API in the <a href="https://auth0.com/blog/angular-2-authentication/">Angular 2 Authentication tutorial here</a>.</p></blockquote> <p>Create a new file in <code>src/app/core</code> called <code>auth.guard.ts</code>:</p> <pre><code class="typescript">// src/app/core/auth.guard.ts import { Injectable } from '@angular/core'; import { Router, CanActivate } from '@angular/router'; import { AuthService } from './auth.service'; @Injectable() export class AuthGuard implements CanActivate { constructor(private auth: AuthService, private router: Router) { } canActivate() { if (this.auth.authenticated) { return true; } this.router.navigate(['/']); return false; } } </code></pre> <p>We need to inject the route guard in our routing module, so we need to import <code>Injectable</code>. We'll also need <code>Router</code> to redirect the user when they're not authenticated, and <code>CanActivate</code> to activate (or deactivate) routes based on user authentication status. We'll import <code>AuthService</code> to get this authentication information. That's it for imports.</p> <p>The <code>AuthGuard</code> class implements <a href="https://angular.io/docs/ts/latest/api/router/index/CanActivate-interface.html"><code>CanActivate</code></a>, a guard which determines if a route can be activated or not. We'll make <code>AuthService</code> and <code>Router</code> available privately to the constructor.</p> <p>Our <code>canActivate()</code> method checks if the user is authenticated. If they are, the route can be activated so we'll <code>return true</code>. Otherwise, we'll redirect to the Home page so the user can log in and <code>return false</code>: the route cannot be activated.</p> <h3>App Routing Module with Route Guard</h3> <p>Now that we've created a route guard, we need to apply it in our application. Let's open the <code>app-routing.module.ts</code> file and make some updates:</p> <pre><code class="js">// src/app/core/app-routing.module.ts ... import { AuthGuard } from './auth.guard'; @NgModule({ imports: [ RouterModule.forRoot([ ... { path: 'create', component: CreateComponent, canActivate: [ AuthGuard ] }, { path: 'complete', component: CompleteComponent, canActivate: [ AuthGuard ] }, ... ]) ], providers: [ AuthGuard ], ... </code></pre> <p>First we need to import our <code>AuthGuard</code>. Then we'll add the <code>canActivate: [ AuthGuard ]</code> key/value to each route that we want to protect. This includes the <code>'create'</code> route and the <code>'complete'</code> route. Finally, we need to add <code>AuthGuard</code> to the <code>providers</code> array.</p> <p>Unauthorized users can no longer access routes that require authentication. Trying to access protected routes when not logged in redirects visitors to the homepage where they'll see the "Log In" button.</p> <blockquote><p><strong>Note:</strong> Don't forget to run <code>$ ng lint</code> if you haven't been doing so and make sure there are no issues with our code.</p></blockquote> <h2>Conclusion</h2> <p>Our simple Angular + ngrx/store + Auth0 application is now complete. Try it out!</p> <h3>Aside: You Might Not <em>Need</em> ngrx/store</h3> <p>State management libraries are <em>great</em>, but please make sure you've read <a href="https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367#.2hrw17sa5">You Might Not Need Redux</a> before you implement ngrx/store in a production Angular application.</p> <p>Our tutorial's sample app is reasonably simple because we're using ngrx/store for teaching and learning. When building production apps for yourself or clients, consider the necessity and ramifications of using a tool like Redux or ngrx/store before implementing. Angular (with its inclusion of <a href="https://github.com/Reactive-Extensions/RxJS">RxJS</a>) now does a great job of <a href="https://scotch.io/tutorials/get-angular-1-features-in-angular-2#global-communication-with-services">managing global data with services</a>. Therefore, smaller, simpler apps work just fine with <em>local</em> state. In these cases, it's possible to introduce confusion and indirection if ngrx/store is used unnecessarily.</p> <p>That said, ngrx/store and its kin are incredibly helpful and valuable tools when managing state in large or particularly complex applications. Hopefully you're now able to reason about the paradigm used by Redux and ngrx/store. This should help you make informed decisions regarding how and when to use state management libraries.</p> <h3>Additional State Management Resources</h3> <p>Here are some additional resources for learning how to manage state with stores:</p> <ul> <li><a href="https://github.com/ngrx/store">ngrx/store on GitHub</a></li> <li><a href="https://egghead.io/lessons/angular-2-ngrx-store-in-10-minutes">@ngrx/store in 10 minutes</a></li> <li><a href="https://gist.github.com/btroncone/a6e4347326749f938510">Comprehensive Introduction to @ngrx/store</a></li> <li><a href="https://www.youtube.com/watch?v=mhA7zZ23Odw&amp;feature=youtu.be">ng-conf: Reactive Angular 2 with ngrx - Rob Womald</a></li> <li><a href="http://blog.angular-university.io/angular-2-redux-ngrx-rxjs/">Angular 2 Service Layers: Redux, RxJS and Ngrx Store - When to Use a Store and Why?</a></li> <li><a href="https://egghead.io/courses/getting-started-with-redux">Getting Started with Redux - Dan Abramov on Egghead.io</a></li> </ul> <p>While Angular makes it reasonably straightforward to share and pass data in smaller apps with services and component communication, managing global application state can rapidly become a mess and a headache in complex apps. Global stores like ngrx/store greatly aid in organizing and compartmentalizing state management. Hopefully you're now prepared to tackle building your own Angular apps with ngrx/store!</p> Easily Migrate Your Existing Stormpath Users to Auth0 2017-03-06T12:30:00+00:00 https://auth0.com/blog/how-to-migrate-your-existing-stormpath-users-to-auth0/ Ado Kukic https://twitter.com/kukicado <hr /> <p><strong>TL;DR</strong> Stormpath announced today that it was acquired by Okta. As a result, the Stormpath API will be shutting down this coming August as the team transitions to Okta. Customers have until August 18, 2017 to export their user data to Okta or a different provider. Find out how to easily migrate your users to Auth0 without requiring your users to reset their passwords and some additional benefits you'll gain by making the switch. If you would like to follow along with our demo, download the sample app from <a href="https://github.com/auth0-blog/migrate-stormpath-users-to-auth0/tree/master/">GitHub</a>.</p> <hr /> <p><a href="https://stormpath.com">Stormpath</a> is an authentication as a service company that allows developers to offload their authentication and authorization needs to a third party. The company offered a RESTful API that customers could use to manage identity in their applications. Today, the company <a href="https://stormpath.com/blog/stormpaths-new-path">announced</a> that it had been acquired by <a href="https://www.okta.com">Okta</a>, another company that provides identity management services.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/acquisition.png" alt="Acquisition announcement" /></p> <p>Acquisitions in the software industry are a norm. What is surprising about this acquisition is that the Stormpath product will be shut down later this year as the team transitions to Okta and many customers will have to find an alternative. Customers have until <strong>August 18, 2017</strong> to find a new provider, get it up and running, and export their existing users. This could be a challenging amount of unexpected work in such a short time frame.</p> <blockquote class="tweet-quote"> <a href="https://twitter.com/intent/tweet?text=&quot;Stormpath customers have until August 18, 2017 to migrate off the platform as it is being shut down!&quot; via @auth0 http://auth0.com/blog/how-to-migrate-your-existing-stormpath-users-to-auth0/"> <p>"Stormpath customers have until August 18, 2017 to migrate off the platform as it is being shut down!"</p> <p class="tweet-link">TWEET THIS <img src="https://cdn.auth0.com/blog/resources/twitter.svg"></p> </a> </blockquote> <script> $(function() { $('.tweet-quote').on('click', function() { metricsLib.track('blog:share:twitter_quote'); }); }); </script> <p>At <a href="https://auth0.com">Auth0</a>, our goal is to provide the best authentication and identity management solution that is also simple and easy for developers to work with.</p> <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr"><a href="https://twitter.com/auth0">@auth0</a> should open user migration to everyone from <a href="https://twitter.com/goStormpath">@goStormpath</a> and gain all those clients that can&#39;t move to okta. <a href="https://twitter.com/hashtag/wearesorry?src=hash">#wearesorry</a></p>&mdash; Tom Compagno (@TomCompagno) <a href="https://twitter.com/TomCompagno/status/838825630078660608">March 6, 2017</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p><strong>You ask, we deliver :)!</strong> We're offering the database migration feature for free for all Stormpath customers 💥!</p> <h2>Custom Database Migration Made Easy with Auth0</h2> <p>The most important thing you are probably concerned with right now is how to migrate your existing users with minimal impact to your applications. At Auth0 we hope to greatly reduce your stress and anxiety with our painless user import functionality.</p> <p>The way this feature works is by setting up a <a href="https://auth0.com/docs/connections/database/mysql">custom database connection</a> and connecting it to your Stormpath account. When your users login the first time, they will enter their existing Stormpath credentials and, if authenticated successfully, we will automatically migrate that user account from Stormpath into Auth0. Your users will not have to change their password or jump through any additional hoops and you can decide what data to port over from Stormpath. Next time the user logs in, Auth0 will detect that they have been migrated and authenticate them with their Auth0 account.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/migrating-copy.png" alt="Auth0 User Migration" /></p> <p>Talk is cheap, so let me actually walk you through the steps.</p> <h3>Implementing the Database Migration Scripts</h3> <p>First of all you will need an Auth0 account. <a href="javascript:signup()">Signup for free here.</a> With your account created, let's setup a custom database connection. In your Auth0 <a href="https://manage.auth0.com">management dashboard</a>, navigate to the <a href="https://manage.auth0.com/#/connections/database">database connections</a> section.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/create-db-connection.png" alt="Create DB Connection" /></p> <p>You can name your connection anything you like. Leave all the default settings as is for now and click the <strong>Create</strong> button to create the connection.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/configure-db.png" alt="Setup Custom DB Connection" /></p> <p>Next, let's go into this database connection and connect it to our Stormpath account. Click on your newly created connection and navigate to the <strong>Custom Database</strong> tab. Flip the switch titled "Use my own database" and the <strong>Database Action Scripts</strong> section will be enabled. This is where we will write our code to connect to your existing Stormpath user datastore. We will need to write two scripts: <strong>Login</strong> and <strong>Get User</strong>. <strong>Login</strong> will proxy the login process and <strong>Get User</strong> will manage looking up accounts when a user attempts to reset their password.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/enable-custom-db.png" alt="Enable Custom Database" /></p> <p>With our custom database feature turned on, let's enable the import functionality. By default the custom database connection will allow us to authenticate with an external database. If we want to migrate users from the external platform into Auth0 we'll need to simply toggle a switch. Go to the <strong>Settings</strong> tab of the connection and flip the switch titled "Import Users to Auth0" and you're done.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/import-to-auth0.png" alt="Import Users to Auth0 Switch" /></p> <p>One final step we'll do before implementing our scripts is enabling this connection for our default client. Navigate to the <strong>Clients</strong> tab while you are in your database connection and flip the switch to enable this client for the Default Connection. <em>If you already have an existing Auth0 account, the connection name may be different.</em></p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/enable-connection.png" alt="Enable Database Connection" /></p> <h3>Login</h3> <p>The <strong>Login</strong> script is executed when a user attempts to sign in but their account is not found in the Auth0 database. Here we will implement the functionality to pass the user credentials provided to our Stormpath user datastore and see if that user is valid. Auth0 provides templates for many common databases such as MongoDB, MySQL and Sql Server, but for Stormpath we will have to write our own. We will utilize Stormpath's REST API to authenticate the user. Let's look at the implementation below:</p> <pre><code class="js">function login(username, password, callback) { // Replace the YOUR-CLIENT-ID attribute with your Stormpath ID var url = 'https://api.stormpath.com/v1/applications/{YOUR-CLIENT-ID}/loginAttempts'; // Stormpath requires the user credentials be passed in as a base64 encoded message var message = username + ':' + password; var pass = new Buffer(message).toString('base64'); // Here we are making the POST request to authenticate a user request({ url: url, method: 'POST', auth: { // Your API Client ID user: '{STORMPATH-CLIENT-ID}', // YOUR API Client Secret password: '{STORMPATH-CLIENT-SECRET}' }, headers: { 'Content-Type': 'application/json' }, json: { type: 'basic', // Passing in the base64 encoded credentials value: pass } }, function (error, response, body) { // If response is successful we'll continue if (response.statusCode !== 200) return callback(); // A successful response will return a URL to get the user information var accountUrl = body.account.href; // We'll make a second request to get the user info. This time it will be a GET request request({ url: accountUrl, method: 'GET', auth: { // Your API Client ID user: '{STORMPATH-CLIENT-ID}', // YOUR API Client Secret password: '{STORMPATH-CLIENT-SECRET}' } }, function (errorUserInfo, responseUserInfo, bodyUserInfo) { // If we get a successful response, we'll process it if (responseUserInfo.statusCode !== 200) return callback(); var parsedBody = JSON.parse(bodyUserInfo); // To get the user identifier, we'll strip out the Stormpath API var id = parsedBody.href.replace('https://api.stormpath.com/v1/accounts/', ''); // Finally, we'll set the data we want to store in Auth0 and migrate the user return callback(null, { user_id : id, username: parsedBody.username, email: parsedBody.email, // We set the users email_verified to true as we assume if they were a valid // user in Stormpath, they have already verified their email // If this field is not set, the user will get an email asking them to verify // their account email_verified: true, // Add any additional fields you would like to carry over from Stormpath }); }); }); } </code></pre> <h3>Get User</h3> <p>The <strong>Get User</strong> script is executed when the user attempts to do a password reset but their account is not found in the Auth0 database. The <strong>Get User</strong> script interfaces with your Stormpath datastore and checks to see if the user exists there. If the user does exist, their data is sent back to Auth0 where the user is automigrated and a password reset email is sent out from Auth0. Once the user confirms the reset, they are good to go and can access your app. Subsequent logins will be authenticated against the Auth0 database as the users profile is now stored with Auth0.</p> <p>Let's look at our implementation of the <strong>Get User</strong> script for Stormpath:</p> <pre><code class="js">function getByEmail(email, callback) { // Replace the YOUR-CLIENT-ID attribute with your Stormpath ID var url = 'https://api.stormpath.com/v1/applications/{YOUR-CLIENT-ID}/accounts'; request({ url: url, method: 'GET', auth: { // Your API Client ID user: '{STORMPATH-CLIENT-ID}', // YOUR API Client Secret password: '{STORMPATH-CLIENT-SECRET}' }, qs: { q: email } }, function (error, response, body) { if (response.statusCode !== 200) return callback(); var parsedBody = JSON.parse(body); var user = parsedBody.items[0]; if (!user) return callback(); var id = user.href.replace('https://api.stormpath.com/v1/accounts/', ''); return callback(null, { user_id: id, username: user.username, email: user.email, email_verified: true, // Add any additional fields you would like to carry over from Stormpath }); }); } </code></pre> <p>With these two scripts we have user migration setup and ready to go. To test it and make sure our code works, let's build a simple application that allows a user to login and request protected resources via an API. We'll build the frontend with Angular 2 and the backend we'll power with Spring.</p> <h3>Building the Frontend</h3> <p>We will build our frontend with Angular 2. We'll use the <a href="https://github.com/auth0-samples/auth0-angularjs2-systemjs-sample/tree/master/01-Login">Auth0 Angular 2 Quickstart</a> to get up and running quickly. Our source code can be found <a href="https://github.com/auth0-blog/migrate-stormpath-users-to-auth0/tree/master/frontend">here</a>. Auth0 provides a comprehensive set of quickstarts, SDKs, and guides for many popular languages and frameworks. See them all <a href="https://auth0.com/docs">here</a>. With the project downloaded, we'll need to setup our Auth0 credentials. We'll do that in the <code>auth.config.js</code> file. Open the file and change the values to look like this:</p> <pre><code class="js">"use strict"; exports.myConfig = { // Your Auth0 ClientID. clientID: '{AUTH0-CLIENT-ID}', // Your Auth0 Domain domain: '{YOUR-AUTH0-DOMAIN}.auth0.com' }; </code></pre> <p>Both of these values can be found in your Auth0 <a href="https://manage.auth0.com">management dashboard</a>. In the dashboard, simply click on the <strong>Clients</strong> link from the main menu, and select the <strong>Default Client</strong> that was created when you signed up. <em>If you already had an Auth0 account, select the client that has the database connection with the custom database enabled</em>.</p> <p>With these values configured save the file and run <code>npm install</code>. Once npm has installed all the required dependencies, run the project by executing <code>npm start</code>. Navigate to <code>localhost:3000</code> to see the app in action.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users-to-auth0/app-new.png" alt="Angular 2 Frontend" /></p> <p>Click on the <strong>Login</strong> button to login to your application. Clicking the <strong>Login</strong> button will bring up the Auth0 <a href="https://auth0.com/lock">Lock</a> widget and ask the user to provide their email and password. Here, the user will provide their Stormpath email and password credentials and if they are correct they will be logged in. If you don't already have a Stormpath user account you can login with, go into your Stormpath dashboard and create an account. Now login with your Stormpath user credentials.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/lock.png" alt="Angular 2 Login with Lock" /></p> <p>Notice that you are instantly logged in. If we look at the response data from the transaction we'll see that the user is coming from the <strong>Stormpath-Users</strong> connection alongside other data that we imported. Let's make sure that this user was migrated to Auth0 as well. To check this we'll navigate to the <a href="https://manage.auth0.com/#/users">Users</a> section of the Auth0 dashboard and we'll now see the user we logged in with.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/migrated.png" alt="User Migrated" /></p> <p>This means that our migration was successful. This user is now migrated to Auth0. The next time they login to the application, we'll check their credentials against Auth0's database instead of making the extra call to Stormpath. The workflow diagram below illustrates the process once again.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/migrating-copy.png" alt="Auth0 User Migration" /></p> <p>Now you may notice the two links <code>Call Public API</code> and <code>Call Private API</code>. Let's build a simple backend that will return data when these links are clicked. We'll do that next.</p> <h3>Building the Backend</h3> <p>For our backend, we'll build a simple Spring Boot application that exposes a RESTful API. You can get the code for the sample application <a href="https://github.com/auth0-blog/migrate-stormpath-users-to-auth0/tree/master/backend">here</a>. To setup the application, you will just need to update the application with your credentials. The file where the credentials are stored is called <code>auth0.properties</code> and can be found in the <code>src/main/resources/</code> directory. Edit the file to look like so:</p> <pre><code>auth0.domain: {YOUR-AUTH-DOMAIN}.auth0.com auth0.issuer: https://{YOUR-AUTH0-DOMAIN}.auth0.com/ auth0.clientId: {YOUR-AUTH0-CLIENT-ID} auth0.securedRoute: NOT_USED auth0.base64EncodedSecret: false auth0.authorityStrategy: ROLES auth0.defaultAuth0ApiSecurityEnabled: false auth0.signingAlgorithm: HS256 </code></pre> <p>With this update in place, you should be able to build the application by running:</p> <pre><code>mvn spring-boot:run -Drun.arguments="--auth0.secret=YOUR_SECRET_KEY" </code></pre> <p>If the application was built successfully, you will be able to access the API at <code>localhost:4000</code>. The two routes that are exposed by this application that we care about are <code>/public</code> and <code>/secure</code>. The <code>/public</code> route will be accessible by everyone, while the <code>/secure</code> route will return a successful response only if the user is authenticated and passes the correct credentials.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/public-api.png" alt="Accessing Public API" /></p> <p>Once your backend is up and running go back to your frontend application and try clicking on the the two links <code>Call Public API</code> and <code>Call Private API</code>. The public API you will be able to access even when not logged in. For the private API, you will need to be logged in to call the route and get the appropriate response.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users/private-api.png" alt="Accessing Private API" /></p> <p>We also used Angular 2 to add some dynamic classes. So if the user is logged in we'll make both of the buttons green to indicate they can be clicked.</p> <p><img src="https://cdn.auth0.com/blog/migrate-stormpath-users-to-auth0/app-logged-in.png" alt="App when logged in" /></p> <h2>Go Further with Auth0</h2> <p>I hope the user migration functionality I showed in this post helps with your use case. This gradual migration works great because it is transparent to your end-users. As the deadline approaches and Stormpath prepares to shut down their service, you may need to speed up the migration process. Auth0 can help here as well. You can <a href="https://auth0.com/docs/tutorials/bulk-importing-users-into-auth0">bulk import</a> your existing user datastore into Auth0 or since we already wrote the <strong>Get User</strong> script you can send out a mass email to your users letting them know they need to change their password and by clicking on the link in the email their accounts will be migrated to Auth0.</p> <p>Now that your migrates woes have been taken care of, let's briefly talk about what Auth0 brings to the table besides authentication and authorization. Many features that Auth0 provides can be enabled with the flip of a switch. <a href="https://auth0.com/multifactor-authentication">Multifactor authentication</a> is one such feature. You can enable MFA using our in-house MFA solution, <a href="https://auth0.com/multifactor-authentication">Guardian</a>, with just the flip of a switch.</p> <p>If you are already using a 3rd party MFA solution or have your own custom solution, you can continue to use it as well. The Auth0 <a href="https://auth0.com/docs/rules">Rules</a> extensibility platform allows you to take control of the authorization workflow. Here you can configure any number of events such as triggering 3rd party MFA, performing progressive profiling, and much more.</p> <p>We want to make your switch to Auth0 as painless as possible, so we are making the Database Migration feature free for all existing Stormpath customers. To help you get up and running faster we are also giving existing Stormpath customers 8 hours of professional services at no cost.</p> <h2>Conclusion</h2> <p>Stormpath will be shutting down their authentication and authorization API's this coming August. Customers have until August 18, 2017 to move off the platform. At Auth0, we hope to give existing Stormpath customers an easy and smooth transition plan. Our database migration feature can start migrating your users today!</p> <p>If you are affected by the Stormpath news and want to easily migrate your users, give Auth0 a try, <a href="javascript:signup()">sign up for a free account</a> and get started today.</p> An Introduction to Ethereum and Smart Contracts: Bitcoin & The Blockchain 2017-03-06T12:30:00+00:00 https://auth0.com/blog/an-introduction-to-ethereum-and-smart-contracts/ Sebastián Peyrott https://twitter.com/speyrott?lang=en <p><a href="https://www.bitcoin.com">Bitcoin</a> took the world by surprise in the year 2009 and popularized the idea of decentralized secure monetary transactions. The concepts behind it, however, can be extended to much more than just digital currencies. <a href="https://www.ethereum.org">Ethereum</a> attempts to do that, marrying the power of decentralized transactions with a Turing-complete contract system. Read on as we explore how it works!</p> <blockquote class="tweet-quote"> <a href="https://twitter.com/intent/tweet?text=&quot;Ethereum marries the power of decentralized transactions with Turing-complete contracts!&quot; via @auth0 http://auth0.com/blog/an-introduction-to-ethereum-and-smart-contracts/"> <p>"Ethereum marries the power of decentralized transactions with Turing-complete contracts!"</p> <p class="tweet-link">TWEET THIS <img src="https://cdn.auth0.com/blog/resources/twitter.svg"></p> </a> </blockquote> <script> $(function() { $('.tweet-quote').on('click', function() { metricsLib.track('blog:share:twitter_quote'); }); }); </script> <p>This is part 1 of a 3 post series.</p> <hr /> <h2>Introduction: Bitcoin and the Double-Spending Problem</h2> <p>In 2009, someone, under the alias of Satoshi Nakamoto, released this <a href="https://bitcoin.org/bitcoin.pdf">iconic Bitcoin whitepaper</a>. Bitcoin was poised to solve a very specific problem: how can the <a href="https://en.wikipedia.org/wiki/Double-spending">double-spending problem</a> be solved without a central authority acting as arbiter to each transaction?</p> <p>To be fair, this problem had been in the <a href="http://eprint.iacr.org/2015/464.pdf">minds of researchers</a> for <a href="http://ieeexplore.ieee.org/document/4268195/?reload=true">some time</a> before Bitcoin was released. But where previous solutions were of research quality, Bitcoin succeeded in bringing a working, production ready design to the masses.</p> <blockquote><p>The earliest references to some of the concepts directly applied to Bitcoin are from the 1990s. In 2005, Nick Szabo, a computer scientist, introduced the concept of <a href="http://unenumerated.blogspot.com/2005/12/bit-gold.html">Bitgold</a>, a precursor to Bitcoin, sharing many of its concepts. The similarities between Bitgold and Bitcoin are sufficient that some people <a href="https://dave.liberty.me/who-is-satoshi-nakamoto/">have speculated he might be Satoshi Nakamoto</a>.</p></blockquote> <p>The double-spending problem is a specific case of <a href="https://en.wikipedia.org/wiki/Transaction_processing">transaction processing</a>. Transactions, by definition, must either happen or not. Additionally, some (but not all) transactions must provide the guarantee of happening before or after other transactions (in other words, they must be atomic). Atomicity gives rise to the notion of ordering: transactions either happen or not before or after other transactions. A lack of atomicity is precisely the problem of the double-spending problem: "spending", or sending money from spender A to receiver B, must happen at a specific point in time, and before and after any other transactions. If this were not the case, it would be possible to spend money more than once in separate but simultaneous transactions.</p> <p><img src="https://cdn.auth0.com/blog/ethereum1/Double-Spending-1-Final.png" alt="Double-spending" /></p> <p>When it comes to everyday monetary operations, transactions are usually arbitrated by banks. When a user logs-in to his or her home banking system and performs a wire transfer, it is the bank that makes sure any past and future operations are consistent. Although the process might seem simple to outsiders, it is actually quite an involved process with <a href="https://en.wikipedia.org/wiki/Clearing_%28finance%29">clearing procedures</a> and <a href="https://en.wikipedia.org/wiki/Settlement_%28finance%29">settlement requirements</a>. In fact, some of these procedures consider the chance of a double-spending situation and what to do in those cases. It should not come as a surprise that these quite involved processes, resulting in considerable but seemingly impossible to surmount delays, where the target of computer science researchers.</p> <p><img src="https://cdn.auth0.com/blog/ethereum1/Double-Spending-2-Final.png" alt="Double-spending using a central authority" /></p> <h2>The Blockchain</h2> <p>So, the main problem any transactional system appliead to finance must address is "how to order transactions when there is no central authority". Furthermore, there can be no doubts as to whether the sequence of past transactions is valid. For a monetary system to succeed, there can be no way any parties can modify previous transactions. In other words, a "vetting process" for past transactions must also be in place. This is precisely what the blockchain system in Bitcoin was designed to address.</p> <blockquote><p>If you are interested in reading about systems that must reach consensus and the problems they face, <a href="http://lamport.azurewebsites.net/pubs/byz.pdf">the paper for The Byzantine Generals Problem</a> is a good start.</p></blockquote> <p>Although at this point the concept of what a blockchain is is murky, before getting into details about it, let's go over the problems the blockchain attempts to address.</p> <h3>Validating Transactions</h3> <p><a href="https://en.wikipedia.org/wiki/Public-key_cryptography">Public-key cryptography</a> is a great tool to deal with one of the problems: validating transactions. Public-key cryptography relies on the asymmetrical mathematical complexity of a very specific set of problems. The asymmetry in public-key cryptography is embodied in the existance of two keys: a public and a private key. These keys are used in tandem for specific purposes. In particular:</p> <ul> <li>Data encrypted with the public-key can only be decrypted by using the private-key.</li> <li>Data signed with the private-key can be verified using the public-key.</li> </ul> <p>The private-key cannot be derived from the public-key, but the public-key can be derived from the private-key. The public-key is meant to be safely shared and can usually be freely exposed to anyone.</p> <p>Of interest for creating a verifiable set of transactions is the operation of signing data. Let's see how a very simple transaction can be verified through the use of public-key cryptography.</p> <p>Let's say there is an account holder A who owns 50 coins. These coins weere sent to him as part of a previous transaction. Account holder A now wants to send these coins to account holder B. B, and anybody else who wants to scrutinize this transaction, must be able to verify that it was actually A who sent the coins to B. Furthermore, they must be able to see B redeemed them, and noone else. Obviously, they should also be able to find the exact point in time, relative to other transactions, in which this transaction took place. However, at this point we cannot do this. We can, fortunately, do everything else.</p> <p>For our simple example, let's say the data in the transaction is just an identifier for the previous transaction (the one that gave A 50 coins in first place), the public-key of the current owner and the signature from the previous owner (confirming he or she sent those coins to A in first place):</p> <pre><code class="json">{ "previous-transaction-id": "FEDCBA987654321...", "owner-pubkey": "123456789ABCDEF...", "prev-owner-signature": "AABBCCDDEEFF112233..." } </code></pre> <p>The number of coins of the current transaction is superfluous: it is simply the same amount as the previous transaction linked in it.</p> <p>Proof that A is the owner of these coins is already there: his or her public-key is embedded in the transaction. Now whatever action is taken by A must be verified in some way. One way to do this would be to add information to the transaction and then produce a new signature. Since A wants to send money to B, the added information could simply be B's public-key. After creating this new transaction it could be signed using A's private-key. This proves A, and only A, was involved in the creating of this transaction. In other words, in JavaScript based pseudo-code:</p> <pre><code class="javascript">function aToB(privateKeyA, previousTransaction, publicKeyB) { const transaction = { "previous-transaction-id": hash(previousTransaction), "owner-pubkey": publicKeyB }; transaction["prev-owner-signature"] = sign(privateKeyA, transaction); return transaction; } </code></pre> <p>An interesting thing to note is that we have defined transactions IDs as simply the hash of their binary representation. In other words, a transaction ID is simply its hash (using an, at this point, unspecified hashing algorithm). This is convenient for several reasons we will explain later on. For now, it is just one possible way of doing things.</p> <p>Let's take the code apart and write it down step-by-step:</p> <ol> <li>A new transaction is constructed pointing to the previous transaction (the one that holds A's 50 coins) and including B's public signature (new transaction = old transaction ID plus receiver's public key).</li> <li>A signature is produced using the new transaction and the previous transaction owner's private key (A's private key).</li> </ol> <p>That's it. The signature in the new transaction creates a verifiable link between the new transaction and the old one. The new transaction points to the old one explicitly and the new transaction's signature can only be generated by the holder of the private-key of the old transaction (the old transaction explicitly tells us who this is through the <code>owner-pubkey</code> field). So the old transaction holds the public-key of the one who can spend it, and the new transaction holds the public-key of the one who received it, along with the signature created with the spender's private-key.</p> <p><img src="https://cdn.auth0.com/blog/ethereum1/Transactions-Final.png" alt="Verified transactions" /></p> <p>If this seems hard to grasp at this point, think of it this way: it is all derived from this simple expression: <em>data signed with the private-key can be verified using the public-key</em>. There is nothing more to it. The spender simply signs data that says "I am the owner of transaction ID XXX, I hereby send every coin in it to B". B, and anybody else, can check that it was A, and only A, who wrote that. To do so, they need only access to A's public-key, which is available in the transaction itself. It is mathematically guaranteed that no key other than A's private-key can be used in tandem with A's public-key. So by simply having access to A's public-key anyone can see it was A who sent money to B. This makes B the rightful owner of that money. Of course, this is a simplification. There are two things we have not considered: who said those 50 coins where of A's property (or, in other words, did A just take ownership of some random transaction, is he or she the rightful owner?) and when exactly did A send the coins to B (was it before or after other transactions?).</p> <blockquote><p>If you are interested in learning more about the math behind public-key cryptography, a simple introduction with code samples is available in chapter 7 of <a href="">The JWT Handbook</a>.</p></blockquote> <p>Before getting into the matter of ordering, let's first tackle the problem of <em>coin genesis</em>. We assumed A was the rightful owner of the 50 coins in our example because the transaction that gave A his or her coins was simply modeled like any other transaction: it had A's public-key in the owner field, and it did point to a previous transaction. So, who gave those coins to A? What's more, who gave the coins to that other person? We need only follow the transaction links. Each transaction points to the previous one in the <em>chain</em>, so where did those 50 coins come from? At some point that chain must end.</p> <p>To understand how this works, it is best to consider an actual case, so let's see how Bitcoin handles it. Coins in Bitcoin were and are created in two different ways. First there is the unique <em>genesis block</em>. The genesis block is a special, hardcoded transaction that points to no other previous transaction. It is the first transaction in the system, has a specific amount of Bitcoins, and points to a public-key that belongs to Bitcoin creator Satoshi Nakamoto. Some of the coins in this transaction were sent to some addresses, but they never were really used that much. Most of the coins in Bitcoin come from another place: they are an <em>incentive</em>. As we will see in the next section about ordering transactions, the scheme employed to do this requires nodes in the network to contribute work in the form of computations. To create an incentive for more nodes to contribute computations, a certain amount of coins are awarded to contributing nodes when they successfully complete a task. This incentive essentially results in special transactions that give birth to new coins. These transactions are also ends to links of transactions, as well as the genesis block. Each coin in Bitcoin can be traced to either one of these incentives or the genesis block. Many cryptocurrency systems adopt this model of coin genesis, each with its own nuances and requirements for coin creation. In Bitcoin, per design, as more coins get created, less coins are awarded as incentive. Eventually, coin creation will cease.</p> <h3>Ordering Transactions</h3> <p>The biggest contribution Bitcoin brought to existing cryptocurrency schemes was a decentralized way to make transactions atomic. Before Bitcoin, researchers proposed different schemes to achieve this. One of those schemes was a simple voting system. To better understand the magic of Bitcoin's approach, it is better to explore these attempts.</p> <p>In a voting system, each transaction gets broadcast by the node performing it. So, to continue with the example of A sending 50 coins to B, A prepares a new transaction pointing to the one that gave him or her those 50 coins, then puts B's public-key in it and uses his or her own private-key (A's) to sign it. This transaction is then sent to each node known by A in the network. Let's say that in addition to A and B, there are three other nodes: C, D, E.</p> <p><img src="https://cdn.auth0.com/blog/ethereum1/Broadcast-Final.png" alt="A broadcasts the transaction" /></p> <p>Now let's imagine A is in fact a malicious node. Although it appears A wants to send B 50 coins, at the same time A broadcasts this transaction, it also broadcasts a different one: A sends those same 50 coins to C.</p> <pre><code class="javascript">const aToB = { "previous-transaction-id": "FEDCBA987654321...", "owner-pubkey": "123456789ABCDEF...", // B "prev-owner-signature": "..." }; const aToC = { "previous-transaction-id": "FEDCBA987654321...", "owner-pubkey": "00112233445566...", // C "prev-owner-signature": "..." }; </code></pre> <p>Note how <code>previous-transaction-id</code> points to the same transaction. <code>A</code> sends simultaneously this transaction to different nodes in the network. Who gets the 50 coins? Worse, if those 50 coins were sent in exchange for something, A might get goods from B and C although one of them won't get the coins.</p> <p>Since this is a distributed network, each node should have some weight in the decision. Let's consider the voting system mentioned before. Each node should now cast a vote on whether to pick which transaction goes first.</p> <table> <thead> <tr> <th> Node </th> <th> Vote </th> </tr> </thead> <tbody> <tr> <td> A </td> <td> A to B </td> </tr> <tr> <td> B </td> <td> A to B </td> </tr> <tr> <td> C </td> <td> A to C </td> </tr> <tr> <td> D </td> <td> A to C </td> </tr> <tr> <td> E </td> <td> A to B </td> </tr> </tbody> </table> <p>Each node casts a vote and <code>A to B</code> gets picked as the transaction that should go first. Obviously, this invalidates the <code>A to C</code> transaction that points to the same coins as <code>A to B</code>. It would appear this solution works, but only superficially so. Let's see why.</p> <p>First, let's consider the case A has colluded with some other node. Did E cast a random vote or was it in some way motivated by A to pick one transaction over the other? There is no real way to determine this.</p> <p>Secondly, our model does not consider the speed of propagation of transactions. In a sufficiently large network of nodes, some nodes may see some transactions before others. This causes votes to be unbalanced. It is not possible to determine whether a future transaction might invalidate the ones that have arrived. Even more, it is not possible to determine whether the transaction that just arrived was made before or after some other transaction waiting for a vote. Unless transactions are seen by all nodes, votes can be unfair. Worse, some node could actively delay the propagation of a transaction.</p> <p>Lastly, a malicious node could inject invalid transactions to cause a targeted denial of service. This could be used to favor certain transactions over others.</p> <p>Votes do not fix these problems because they are inherent to the design of the system. Whatever is used to favor one transaction over the other cannot be left to choice. As long as a single node, or group of nodes, can, in some way, favor some transactions over others, the system cannot work. It is precisely this element that made the design of cryptocurrencies such a hard endeavor. A strike of genius was needed to overcome such a profound design issue.</p> <blockquote><p>The problem of malicious nodes casting a vote in distributed systems is best known as <a href="http://research.microsoft.com/en-us/um/people/lamport/pubs/byz.pdf">The Byzantine Generals Problem</a>. Although there is mathematical proof that this problem can be overcome as long as there is a certain ratio of non-malicious nodes, this does not solve the problem for cryptocurrencies: nodes are cheap to add. Therefore, a different solution is necessary.</p></blockquote> <h4>Physics to the Rescue</h4> <p>Whatever system is used to ensure some transactions are preferred over others, no node should be able to choose which of these are with 100% certainty. And there is only one way one can be sure this is the case: if it is a <em>physical impossibility</em> for the node to be able to do this. Nodes are cheap to add, so no matter how many nodes a malicious user controls, it should still be hard for him or her to use this to his or her advantage.</p> <p>The answer is CPU power. What if ordering transactions required a certain amount of work, verifiable work, in such a way that it would be hard to perform initially, but cheap to verify. In a sense, cryptography works under the same principles: certain related operations are computationally infeasible to perform while others are cheap. Encrypting data is cheap next to brute-forcing the encryption key. Deriving the public-key from the private-key is cheap, while it is infeasible to do it the other way around. <em>Hashing data is cheap, while finding a hash with a specific set of requirements (by modifying the input data) is not.</em> And that is the main operation Bitcoin and other cryptocurrencies rely on to make sure no node can get ahead of others, on average. Let's see how this works.</p> <p>First, let's define what a block is. A block is simply a group of transactions. Inside the block, these transactions are set in a specific order and fulfill the basic requirements of any transaction. In particular, an invalid transaction (such as one taking funds from an account with no funds) cannot be part of a block. In addition to the transactions, a block carries something called <em>proof-of-work</em>. The proof-of-work is data the allows any node to verify that the one who created this block performed a considerable amount of computational work. In other words, no node can create a valid block without performing an indefinite but considerable amount of work. We will see how this works later, but for now know that creating any block requires a certain amount of computing power and that any other node can check that that power has been spent by whomever created the block.</p> <p>Now let's go back to our previous example of a malicious node, A, double-spending 50 coins by trying to create to two separate transactions at the same time, one sending money to B and the other to C. After A broadcasts both transactions to the network, every node working on creating blocks (which may include A) pick a number of transactions and order them in whichever way they prefer. These nodes will note that two incompatible transactions are part of the same block and will discard one. They are free to pick which one to discard. After placing these transactions in the order they chose, each node starts solving the puzzle of finding a hash for the block that fits the conditions set by the protocol. One simple condition could be "find a hash for this block with three leading zeroes". To iterate over possible solutions for this problem, the block contains a special variable field known as the "nonce". Each node must iterate as many times as necessary until they find the nonce that creates a block with a hash that fits the conditions set by the protocol (three leading zeroes). Since each change in the nonce basically results in a random output for a cryptographically secure hash function, finding the nonce is a game of chance and can only be sped up by increasing computation power. Even then, a less powerful node might find the right nonce before a more powerful node, due to the randomness of the problem.</p> <p><img src="https://cdn.auth0.com/blog/ethereum1/Block-Final.png" alt="A sample block" /></p> <p>This creates an interesting scenario because even if A is a malicious node and controls another node (for instance, E) any other node on the network still has a chance of finding a different valid block. In other words, this scheme makes it hard for malicious nodes to take control of the network.</p> <p><img src="https://cdn.auth0.com/blog/ethereum1/Proof-of-Work-Final.png" alt="Proof-of-work" /></p> <p>Still, the case of a big number of malicious nodes colluding and sharing CPU power must be considered. In fact, an entity controlling a majority of the nodes (in terms of CPU power, not number) could exercise a double-spending attack by creating blocks faster than other nodes. Big enough networks rely on the difficulty of amassing CPU power. While in a voting system an attacker need only add nodes to the network (which is easy, as free access to the network is a design target), in a CPU power based scheme an attacker faces a physical limitation: getting access to more and more powerful hardware.</p> <h3>Definition</h3> <p>At last we can attempt a full definition of what a blockchain is and how it works. A blockchain is a verifiable transaction database carrying an ordered list of all transactions that ever occurred. Transactions are stored in blocks. Block creation is a purposely computationally intensive task. The difficulty of creation of a valid block forces anyone to spend a certain amount of work. This ensures malicious users in a big enough network cannot easily outpass honest users. Each block in the network points to the previous block, effectively creating a chain. The longer a block has been in the blockchain (the farther it is from the last block), the lesser the probability it can ever be removed from it. In other words, the older the block, the more secure it is.</p> <p><img src="https://cdn.auth0.com/blog/ethereum1/Blockchain-Final.png" alt="The blockchain" /></p> <p>One important detail we left in previous paragraphs is what happens when two different nodes find different but still valid blocks at the same time. In a sense, this looks like the same problem transactions had: which one to pick. In contrast with transactions, the proof-of-work system required for each block lets us find a convenient solution: since each block requires a certain amount of work, it is only natural that the only valid blockchain is the one with most blocks in it. Think about it: if the proof-of-work system works because each block demands a certain amount of work (and time), the longest set of valid blocks is the <em>hardest</em> to break. If a malicious node or group of nodes were to attempt to create a different set of valid blocks, by always picking the longest blockchain, they would always have to redo a bigger number of blocks (because each node points to the previous one, changing one block forces a change in all blocks after it). This is also the reason malicious groups of nodes need to control over 50% of the computational power of the network to actually carry any attack. Less than that, and the rest of the network will create a longer blockchain faster.</p> <p>Valid blocks that are valid but find their way into shorter <em>forks</em> of the blockchain are discarded if a longer version of the blockchain is computed by other nodes. The transactions in the discarded blocks are sent again to the pool of transactions awaiting inclusion into future blocks. This causes new transactions to remain in an <em>uncofirmed</em> state until they find their way into the longest possible blockchain. Nodes periodically receive newer versions of the blockchain from other nodes.</p> <p><img src="https://cdn.auth0.com/blog/ethereum1/Forks-Final.png" alt="Blockchain forks" /></p> <p>It is entirely possible for the network to be forked if a sufficiently large number of nodes gets disconnected at the same time from another part of the network. If this happens, each fork will continue creating blocks in isolation from the other. If the networks merge again in the future, the nodes will compare the different versions of the blockchains and pick the longer one. The fork with the greater computational power will always win. If the fork were to be sustained for a long enough period of time, a big number of transactions would be undone when the merge took place. It is for this reason that forks are problematic.</p> <p>Forks can also be caused by a change in the protocol or the software running the nodes. These changes can result in nodes invalidating blocks that are considered valid by other nodes. The effect is identical to a network-related fork.</p> <h2>Aside: a Perpetual Message System Using Webtasks and Bitcoin</h2> <p>Although we have not delved into the specifics of how Bitcoin or Ethereum handle transactions, there is a certain <em>programmability</em> built into them. Bitcoin allows for certain conditions to be specified in each transaction. If these conditions are met, the transaction can be spent. Ethereum, on the other hand, goes much further: a Turing-complete programming language is built into the system. We will focus on Ethereum in the next post in this series, but for now we will take a look at creative ways in which the concepts of the blockchain can be exploited for more than just sending money. For this, we will develop a simple perpetual message system on top of Bitcoin. How will it work?</p> <p>We have seen the blockchain stores transactions that can be verified. Each transaction is signed by the one who can perform it and then broadcast to the network. It is then stored inside a block after performing a proof-of-work. This means that any information embedded in the transaction is stored forever inside the blockchain. The timestamp of the block serves as proof of the message's date, and the proof-of-work process serves as proof of its immutable nature.</p> <p>Bitcoin uses a scripting system that describes steps a user must perform to spend money. The most common script is simply "prove you are the owner of a certain private-key by signing this message with it". This is known as the "pay to pubkey hash" script. In decompiled form it looks like:</p> <pre><code>&lt;sig&gt; &lt;pubKey&gt; OP_DUP OP_HASH160 &lt;pubKeyHash&gt; OP_EQUALVERIFY OP_CHECKSIG </code></pre> <p>Where <code>&lt;sig&gt;</code> and <code>&lt;pubKey&gt;</code> are provided by the spender and the rest is specified by the original sender of the money. This is simply a sequence of mixed data and operations. The interpreter for this script is a stack-based virtual machine. The details of execution are out of scope for this article, but you can find a nice summary at the <a href="https://en.bitcoin.it/wiki/Script#Standard_Transaction_to_Bitcoin_address_.28pay-to-pubkey-hash.29">Bitcoin Wiki</a>. The important take from this is that transactions can have data embedded in them in the scripts.</p> <p>In fact, there exists a valid opcode for embedding data inside a transaction: the <code>OP_RETURN</code> opcode. Whatever data follows the <code>OP_RETURN</code> opcode is stored in the transaction. Of course, there is a limit for the amount of data allowed: 40-bytes. This is very little, but still certain interesting applications can be performed with such a tiny amount of storage. One of them is our perpetual message system. Another interesting use case is the "proof of existence" concept. By storing a hash of an asset in the blockchain, it serves as proof of its existence at the point it was added to a block. In fact, there <a href="https://proofofexistence.com">already exists such a project</a>. There is nothing preventing you from using our perpetual message system for a similar use. Yet other uses allow the system to prepare transactions that can only be spent after conditions are met, or when the spender provides proof of having a certain digital asset, of when a certain minimum number of users agree to spend it. Programmability opens up many possibilities and makes for yet another great benefit of cryptocurrencies in contrast with traditional monetary systems.</p> <h3>The Implementation</h3> <p>Our system will work as an HTTP service. Data will we passed in JSON format as the body of <code>POST</code> requests. The service will have three endpoints plus one for debugging.</p> <h4>The <code>/new</code> endpoint</h4> <p>It creates a new user using the username and password passed in. Sample body:</p> <pre><code class="javascript">{ "id": "username:password", // password is not hashed for simplicity, // TLS is required! "testnet": true // True to use Bitcoin's test network } </code></pre> <p>The response is of the form:</p> <pre><code class="javascript">{ "address": "..." // A Bitcoin address for the user just created } </code></pre> <h4>The <code>/address</code> endpoint</h4> <p>Returns the address for an existing user. Sample body:</p> <pre><code class="javascript">{ "id": "username:password", // password is not hashed for simplicity, // TLS is required! } </code></pre> <p>The response is identical to the <code>/new</code> endpoint.</p> <h4>The <code>/message</code> endpoint</h4> <p>Broadcasts a transaction to the Bitcoin network with the message stored in it. A fee is usually required for the network to accept the transaction (though some nodes may accept transactions with no fees). Messages can be at most 33 bytes long. Sample body:</p> <pre><code class="javascript">{ "id": "username:password", "fee": 667, "message": "test" } </code></pre> <p>The response is either a transaction id or an error message. Sample of a successful response:</p> <pre><code class="javascript">{ "status": "Message sent!", "transactionId": "3818b4f03fbbf091d5b52edd0a58ee1f1834967693f5029e5112d36f5fdbf2f3" } </code></pre> <p>Using the transaction id one can see the message stored in it. One can use any publicly available blockchain explorer to do this.</p> <h4>The <code>/debugNew</code> endpoint</h4> <p>Similar to the <code>/new</code> endpoint but allows one to create an user with an existing Bitcoin private key (and address). Sample body:</p> <pre><code class="javascript">{ "id": "username:password", // password is not hashed for simplicity, // TLS is required! "testnet": true, // True to use Bitcoin's test network "privateKeyWIF": "..." // A private key in WIF format. // Note testnet keys are different from livenet keys, // so the private key must agree with the // value of the "testnet" key in this object } </code></pre> <p>The response is identical to the <code>/new</code> endpoint.</p> <h3>The Code</h3> <p>The most interesting endpoint is the one that builds and broadcasts the transaction (<code>/message</code>). We use the <code>bitcore-lib</code> and <code>bitcore-explorers</code> libraries to do this:</p> <pre><code class="javascript">getUnspentUtxos(from).then(utxos =&gt; { let inputTotal = 0; utxos.some(utxo =&gt; { inputTotal += parseInt(utxo.satoshis); return inputTotal &gt;= req.body.fee; }); if(inputTotal &lt; req.body.fee) { res.status(402).send('Not enough balance in account for fee'); return; } const dummyPrivateKey = new bitcore.PrivateKey(); const dummyAddress = dummyPrivateKey.toAddress(); const transaction = bitcore.Transaction() .from(utxos) .to(dummyAddress, 0) .fee(req.body.fee) .change(from) .addData(`${messagePrefix}${req.body.message}`) .sign(req.account.privateKeyWIF); broadcast(transaction.uncheckedSerialize()).then(body =&gt; { if(req.webtaskContext.secrets.debug) { res.json({ status: 'Message sent!', transactionId: body, transaction: transaction.toString(), dummyPrivateKeyWIF: dummyPrivateKey.toWIF() }); } else { res.json({ status: 'Message sent!', transactionId: body }); } }, error =&gt; { res.status(500).send(error.toString()); }); }, error =&gt; { res.status(500).send(error.toString()); }); </code></pre> <p>The code is fairly simple:</p> <ol> <li>Gets the unspent transactions for an address (i.e. the coins available, the balance).</li> <li>Build a new transaction using the unspent transactions as input.</li> <li>Point the transaction to a new, empty address. Assign 0 coins to that address (do not send money unnecessarily).</li> <li>Set the fee.</li> <li>Set the address where the unspent money will get sent back (the change address).</li> <li>Add our message.</li> <li>Broadcast the transaction.</li> </ol> <p>Bitcoin requires transactions to be constructed using the money from previous transactions. That is, when coins are sent, it is not the origin address that is specified, rather it is the transactions pointing to that address that are included in a new transaction that points to a different destination address. From these transactions is subtracted the money that is then sent to the destination. In our case, we use these transactions to pay for the fee. Everything else gets sent back to our address.</p> <h3>Deploying the Example</h3> <p>Thanks to the power of <a href="https://webtask.io">Webtasks</a>, deploying and using this code is a piece of cake. First clone the repository:</p> <pre><code class="sh">git clone git@github.com:auth0-blog/ethereum-series-bitcoin-perpetual-message-example.git </code></pre> <p>Now make sure you have the Webtask command-line tools installed:</p> <pre><code class="sh">npm install -g wt-cli </code></pre> <p>If you haven't done so, initialize your Webtask credentials (this is a one time process):</p> <pre><code class="sh">wt init </code></pre> <p>Now deploy the project:</p> <pre><code class="sh">cd ethereum-series-bitcoin-perpetual-message-example wt create --name bitcoin-perpetual-message --meta 'wt-node-dependencies={"bcryptjs":"2.4.3","bitcore-lib":"0.13.19","bitcore-explorers-bitcore-lib-0.13.19":"1.0.1-3"}' app.js </code></pre> <p>Your project is now ready to test! Use CURL to try it out:</p> <pre><code class="sh">curl -X POST https://wt-sebastian_peyrott-auth0_com-0.run.webtask.io/bitcoin-perpetual-message/new -d '{ "id":"test:test", "testnet":true }' -H "Content-Type: application/json" {"address":"mopYghMw5i7rYiq5pfdrqFt4GvBus8G3no"} # This is your Bitcoin address </code></pre> <p>You now have to add some funds to your new Bitcoin address. If you are on Bitcoin's testnet, you can simply use a <a href="https://testnet.manu.backend.hamburg/faucet">faucet</a>.</p> <blockquote><p>Faucets are Bitcoin websites that give free coins to addresses. These are easy to get for the testnet. For the "livenet" you need to buy Bitcoins using a <a href="https://en.wikipedia.org/wiki/Digital_currency_exchange">Bitcoin exchange</a>.</p></blockquote> <p>Now send a message!</p> <pre><code class="sh">curl -X POST https://wt-sebastian_peyrott-auth0_com-0.run.webtask.io/bitcoin-perpetual-message/message -d '{ "id":"test:test", "fee":667, "message":"test" }' -H "Content-Type: application/json" {"status":"Message sent!","transactionId":"3818b4f03fbbf091d5b52edd0a58ee1f1834967693f5029e5112d36f5fdbf2f3"} </code></pre> <p>Now you can <a href="https://www.blocktrail.com/tBTC/tx/3818b4f03fbbf091d5b52edd0a58ee1f1834967693f5029e5112d36f5fdbf2f3">look at the transaction</a> using a blockchain explorer and the transaction id. If you go down to the bottom of the page in the link before you will see our message with a prefix <code>WTMSG: test</code>. This will get stored in the blockchain forever.</p> <p>Try it yourself! The webtask at <code>https://wt-sebastian_peyrott-auth0_com-0.run.webtask.io/bitcoin-perpetual-message/</code> is live. You will need to create your own account and fund it, though.</p> <p>You can also <a href="https://github.com/auth0-blog/ethereum-series-bitcoin-perpetual-message-example">get the full code</a> for this example and run it!</p> <h2>Conclusion</h2> <p>Blockchains enable distributed, verified transactions. At the same time they provide a creative solution to the double-spending problem. This has enabled the rise of cryptcurrencies, of which Bitcoin is the most popular example. Millions of dollars in Bitcoins are traded each day, and the trend is not giving any signs of slowing down. Bitcoin provides a limited set of operations to customize transactions. Still, many creative applications have appeared through the combination of blockchains and computations. Ethereum is the greatest example of these: marrying decentralized transactions with a Turing-complete execution environment. In the next post in the series we will take a closer look at how Ethereum differs from Bitcoin and how the concept of decentralized applications was brought to life by it.</p> Cloudpets Data Breach Affects Over 820,000 Customers 2017-03-03T08:30:00+00:00 https://auth0.com/blog/cloudpets-data-breach/ Ado Kukic https://twitter.com/kukicado <p><a href="http://spiraltoys.com/">Spiral Toys</a> is a company that creates toys for children. It has an internet-connected product called <a href="http://cloudpets.com/">CloudPets</a> which allows parents and children to record and send voice messages to each other through a mobile app. On January 7, hackers discovered that the database the company was using to store data for this product was unsecured. Hackers took control of the database, deleted all information, and demanded a payment to restore the data.</p> <p><img src="https://cdn.auth0.com/blog/cloudpets-data-breach/cloudpets.png" alt="Cloudpets Homepage" /></p> <p>The database contained information for 820,000+ users containing emails, bcrypt hashed passwords, and links to voice recordings customers and their children had made which could now be publicly accessed. Additional information stored included pictures, names, birthdays, and relationships. Customers were not notified that their data had been compromised.</p> <p><a href="https://twitter.com/troyhunt">Troy Hunt</a> wrote an excellent <a href="https://www.troyhunt.com/data-from-connected-cloudpets-teddy-bears-leaked-and-ransomed-exposing-kids-voice-messages/">article</a> covering this incident. Some highlights include that the database used was publicly accessible and did not even require a password to access. Cloudpets was also notified at least four times that their database was exposed and the reporters never heard back from the company. Finally, staging and test databases were also discovered which had production data that could have also been compromised.</p> <p>Aside from the devops failure to secure the database properly, password requirements for user accounts were non-existant. Although the passwords were stored as bcrypt hashes, Troy was able to use <a href="https://hashcat.net/hashcat/">Hashcat</a> and find valid passwords such as "qwe", "password", and "123456".</p> <p><img src="https://cdn.auth0.com/blog/cloudpets-data-breach/cracked-bcrypt-hashes.png" alt="Cracked Bcrypt Hashes" /></p> <p>Source: <a href="https://www.troyhunt.com/data-from-connected-cloudpets-teddy-bears-leaked-and-ransomed-exposing-kids-voice-messages/">Troy Hunt</a></p> <p>Since the database has been publicly exposed since at least December 25, 2016, it is safe to assume that many malicious parties have accessed and downloaded the data. We urge customers that have Cloudpets accounts to change their passwords and monitor their other accounts for signs of malicious activity.</p> <h2>Personal Information Security Guide</h2> <p>Even if you don't have a Cloudpets account, it may be a good time to review our <a href="https://auth0.com/blog/personal-information-security-identity-guide/">personal information security guide</a> which has plenty of tips on securing your personal information online, best practices for choosing good passwords, and much more.</p> <p>Top things to remember when it comes to choosing a good password:</p> <ul> <li>Don't reuse the same password for multiple accounts.</li> <li>Combine alphanumeric, special, lower and uppercase characters.</li> <li>Your password should be at least 10 characters long.</li> <li>If possible, enable <a href="https://auth0.com/multifactor-authentication">multifactor authentication</a> for your account.</li> </ul> <h2>Auth0 Can Protect Your Users and Apps</h2> <p>Managing identity is a complex and difficult task. At <a href="https://auth0.com">Auth0</a>, our goal is to make identity simple for developers. A recent feature we launched called <a href="https://auth0.com/breached-passwords">Breached Password Detection</a> can help alert your users that their credentials have been compromised in a data breach when they login to your app. We are still working on getting and adding credentials from this breach to our database to better protect your users. This feature helps your users stay safe, but also protects your apps from malicious access. Additionally, Auth0 meets the standards for various <a href="https://auth0.com/docs/connections/database/password-strength">password strength requirements</a>, provides <a href="https://auth0.com/multifactor-authentication">multifactor authentication</a>, and more.</p> <p>If you want to make identity simple and secure for your applications, <a href="javascript:signup()">give Auth0 a try</a>.</p> Create a Docker dashboard with TypeScript, React and Socket.io 2017-03-02T08:45:00+00:00 https://auth0.com/blog/docker-dashboard-with-react-typescript-socketio/ Steve Hobbs http://twitter.com/elkdanger <p>In this article, we are going to use a few different technologies together to build something which, after a bit more elaboration, might actually be useful! We will be creating a web-based dashboard for a <a href="https://www.docker.com/">Docker</a> installation using a number of different frameworks and technologies, both front-end and server-side, enabling some administrator to monitor running containers, start and stop existing containers, and create new containers based on existing Docker images. There is a wide scope for elaboration here, of course, but I'll leave that as an exercise for you, the reader. Hopefully this article will set you off on the right foot with a good overview of the relevant technologies, enabling you to add even more value to the product!</p> <h2>The app</h2> <p>This is a quick preview of what the app looks like when it's finished. It's essentially a page that displays two lists of Docker containers; those that are currently running, and those that are stopped. It allows the user to start and stop these containers, as well as start a new container from an existing image by clicking the 'New container' button.</p> <p><img src="https://i.imgur.com/jfWUxBY.png" alt="Preview of the Docker dashboard app" /></p> <h2>The code</h2> <p>If you want to explore the finished product as a reference (finished as far as the article is concerned!) then you can <a href="https://github.com/elkdanger/docker-dashboard-example">fork the code on Github.com</a>.</p> <h2>Technology stack</h2> <p>Let's have a look at exactly what we're going to be using, and why. I'll go through the prerequisites and installation requirements in a bit.</p> <ul> <li><strong>Node</strong>: We will use this to write our server-side code in JavaScript to run it on our machine, and serve up our website to our users.</li> <li><strong>Docker</strong>: This uses container technology to reliably run apps and services on a machine. The app interfaces with the Docker daemon through the <a href="https://docs.docker.com/engine/reference/api/docker_remote_api/">Docker Remote API</a>. More on this later.</li> <li><strong>TypeScript</strong>: This allows us to add type safety to JavaScript and allows us to use modern JavaScript syntax in older browsers.</li> <li><strong>React</strong>: Allows us to write the front-end of our application in isolated components in an immutable, state-driven way, mixing Html with JavaScript.</li> <li><strong>Socket.io</strong>: Provides us with a way to communicate in real-time with the server and other clients using WebSocket technology, gracefully degrading on older browsers.</li> </ul> <p>Peppered amongst the main technologies mentioned above are various libraries which also provide a lot of value during development time:</p> <ul> <li><strong>ExpressJS</strong>: Used to serve our web application.</li> <li><strong>Webpack 2</strong>: To transpile our TypeScript assests into normal JavaScript.</li> <li><strong>Bootstrap</strong>: To provide something decent looking - a problem I know all of us programmers endure!</li> </ul> <p>There are a few more minor ones, but I will cover those as we come to them.</p> <h2>Prerequisites</h2> <h3>Docker</h3> <p>As this is going to be a slick-looking dashboard for Docker, we need to make sure we have Docker installed (if you don't already).</p> <p>Head to <a href="https://www.docker.com">docker.com</a> and download the latest version of the client for your operating system. If you've never heard of or used Docker before, don't worry about it too much, but it might be worth following through their <a href="https://docs.docker.com/docker-for-mac/">getting started tutorial for Mac</a> or <a href="https://docs.docker.com/docker-for-windows/">Windows</a> or <a href="https://docs.docker.com/engine/installation/">Linux</a>.</p> <p>To make sure your Docker installation is up and running, open up a command prompt and type: <code>docker -v</code>. You should see some version information repeated back to you; mine says <code>Docker version 1.12.5, build 7392c3b</code>. If you can't see this or you get an error, follow through the installation docs again carefully to see if you missed anything.</p> <p>Keep the command prompt open - you're going to need it!</p> <p><strong>A note about the Docker Toolbox:</strong> The article was written assuming that you have the Docker native tools installed. If you happen to have the older <a href="https://www.docker.com/products/docker-toolbox">Docker Toolbox</a> installed then the Docker API may not work for you straight out of the box. If you're in this situation, you may need to <a href="http://stackoverflow.com/questions/40294853/how-to-enable-docker-api-access-from-windows-running-docker-toolbox-docker-mach">perform some additional steps to enable the API</a> with Docker Toolbox.</p> <p><em>Many thanks to reader</em> Rick Wolff <em>for pointing this out!</em></p> <h3>NodeJS</h3> <p>To write our app and serve the web interface to the user, we're going to use NodeJS. This has a number of libraries and frameworks which will make the job very easy for us.</p> <p>Node, version 6.3.1 was used to build the demo app for this article, so I would urge you to use the same version or later if you can, as there are some language features that I'm using which may not be available in earlier versions of the framework.</p> <p>You can <a href="https://nodejs.org/en/download/releases/">grab the 6.3.1 release</a> from their website, or simply grab the <a href="https://nodejs.org/en/download/">latest release</a> from their main downloads page. You can also use something like <a href="https://github.com/creationix/nvm">NVM</a> if you want to mix and match your versions for different projects, which is something I can recommend doing.</p> <p>Once you have Node installed, open up your command line and make sure it's available by typing:</p> <p><code>node -v</code></p> <p>It should repeat the correct version number back to you. Also check that NPM is available (it should have been installed by the NodeJS installer) by typing:</p> <p><code>npm -v</code></p> <p>It should ideally be version 3 or greater.</p> <h3>TypeScript</h3> <p>We will need to install the <a href="https://www.npmjs.com/package/typescript">TypeScript</a> compiler for our application to work; luckily we can do this through NPM.</p> <p>Now that we have NPM installed from the previous step, we can install TypeScript using the following command:</p> <p><code>npm install -g typescript</code></p> <p>This will download the TypeScript compiler using the node package manager and make the tools available on the command-line. To verify that your installation has worked, type:</p> <p><code>tsc -v</code></p> <p>Which should again echo a version number back to you (I'm using 2.0.10).</p> <h3>Webpack 2</h3> <p>Finally, install <a href="https://www.npmjs.com/package/webpack">Webpack</a>, which will allow us to package our JavaScript assets together and will effectively run our TypeScript compiler for us. Again, we can do this through NPM:</p> <p><code>npm install -g webpack</code></p> <p>This has installed webpack into our global package repository on our machine, giving us access to the 'webpack' tool.</p> <h2>Setting up the project</h2> <p>First of all, create a folder somewhere on your machine to house the development of your Docker dashboard, and navigate to it in your command line. We'll go through a number of steps to set this folder up for use before we start coding.</p> <p>Next, initialise the NodeJS project by typing: <code>npm init</code></p> <p>This will ask you a number of questions about the project, none of which are terribly important for this demo, except that the name must be all lower-case and contain no spaces.</p> <p>Once that has finished, you will be left with a <code>package.json</code> file in your project. This is the manifest file that describes your node project and all of its dependencies, and we'll be adding to this file shortly.</p> <h2>Creating the web server</h2> <p>Next, we'll get the basic web server up and running which will eventually serve our ReactJS app to the user.</p> <p>Let's begin by installing <a href="http://expressjs.com/">ExpressJS</a>, which will enable us to get this done:</p> <p><code>npm install --save express</code></p> <p><a href="http://expressjs.com/">Express</a> is a framework that provides us with an API for handling incoming HTTP requests, and defining their responses. You can apply a number of view engines for serving web pages back to the user, along with a whole host of middleware for serving static files, handling cookies, and much more. Alas, we're simply going to use it to serve up a single HTML file and some JavaScript assets, but at least it makes that job easy!</p> <p>Next, create the file <code>server.js</code> inside the root of your project, and add the code which will serve the HTML file:</p> <pre><code class="javascript">let express = require('express') let path = require('path') let app = express() let server = require('http').Server(app) // Use the environment port if available, or default to 3000 let port = process.env.PORT || 3000 // Serve static files from /public app.use(express.static('public')) // Create an endpoint which just returns the index.html page app.get('/', (req, res) =&gt; res.sendFile(path.join(__dirname, 'index.html'))) // Start the server server.listen(port, () =&gt; console.log(`Server started on port ${port}`)) </code></pre> <p><em>Note: You're going to see a lot of new ES6 syntax in this article, like <code>let</code>, <code>const</code>, arrow functions and a few other things. If you're not aware of modern JavaScript syntax, it's worth having <a href="https://babeljs.io/learn-es2015/">a read up on some the new features</a>!</em></p> <p>Next, create an <code>index.html</code> file in the root of the project with the following content:</p> <pre><code class="html">&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt; &lt;title&gt;Docker Dashboard&lt;/title&gt; &lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" type="text/css"&gt; &lt;/head&gt; &lt;body&gt; &lt;div id="app"&gt; Docker Dashboard! &lt;/div&gt; &lt;script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"&gt;&lt;/script&gt; &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"&gt;&lt;/script&gt; &lt;/body&gt; &lt;/html&gt; </code></pre> <p>This simply gives us a basic template for the front page of our app - we'll be adding to this later!</p> <p>Finally, let's test it out to make sure it's all working so far. In the command line, type:</p> <p><code>node server.js</code></p> <p>The prompt should tell you that it has managed to start the site on port 3000. <a href="http://localhost:3000">Browse there now</a> and make sure we can see our default index page. If not, check both the browser window and the console to see if Node has spat out any useful errors, and try again.</p> <h3>Keeping a smooth development workflow</h3> <p>Right now when you make changes to the site you will be forced to stop and restart the node app to see your changes to NodeJS code take effect, or re-run the webpack command whenever you make a change to your React components. We can mitigate both of these by causing them to reload themselves whenever changes are made.</p> <p>To automatically reload your NodeJS server-side changes, you can use a package called <a href="https://nodemon.io/">nodemon</a>. If you want to use this package from the command line, you can do <code>npm install -g nodemon</code>. This will allow us to run our app in such a way that any changes to the server-side code will cause the web server to automatically restart, by using <code>nodemon server.js</code>. We only want to do this on our development machines though, so we will configure our <code>package.json</code> accordingly.</p> <p>To handle the recompilation of your React components automatically, webpack has a 'watch' option that will cause it to re-run by itself. To do this, start webpack using <code>webpack --watch</code> and notice that your JavaScript bundles will start recompiling automatically whenever you change your React components.</p> <p>To have thes two things - nodemon and webpack - running together, you can either start them in two different console windows, or if you're using OSX or Linux you can run them from one console using this neat one-liner:</p> <p><code>nodemon server.js &amp; webpack --watch</code></p> <p><strong>Note</strong> This won't work on Windows systems, but luckily there is a package for that called <a href="https://www.npmjs.com/package/concurrently">concurrently</a> that you can use to achieve the same affect:</p> <pre><code>npm install -g concurrently concurrently "nodemon server.js" "webpack --watch" </code></pre> <p>While you can use these tools by installing them globally, for our application we're going to install these two things as development dependencies, and adjust our <code>package.json</code> file with two commands: one to start the app normally without nodemon, and a development script we can use to start both nodemon and webpack watch.</p> <p>Firstly, install these two packages as development dependencies:</p> <pre><code>npm install -D nodemon concurrently </code></pre> <p>Then edit the 'scripts' node of the <code>package.json</code> file to look like the following:</p> <pre><code class="javascript">... "main": "index.js", "scripts": { "start": "webpack -p &amp;&amp; node server.js", "start-dev": "./node_modules/.bin/concurrently 'nodemon server.js' 'webpack --watch'" }, "author": "", ... </code></pre> <ul> <li>The <code>start</code> script (run using <code>npm start</code>) will firstly compile your JavaScript assets using Webpack and then run our app using node. The <code>-p</code> switch causes Webpack to automatically optimize and minimize our scripts, ready for production</li> <li>The <code>start-dev</code> script (run using <code>npm run start-dev</code>) is our development mode. It starts our webserver using Nodemon and Webpack in 'watch' mode, meaning that both our server-side and client-side code will be automatically reloaded when something changes</li> </ul> <p>(Thanks to <a href="https://twitter.com/OmgImAlexis">@OmgImAlexis</a> for some suggestions in this area!)</p> <h2>Starting some React and TypeScript</h2> <p>The main body of our client application is going to be constructed using React and TypeScript, which means we need to spend a little more time setting up one or two more tools. Once we set up a workflow for compiling the first component, the rest will easily follow.</p> <p>Firstly, let's have a look at how we're going to structure our React components.</p> <pre><code>app/ |--- components/ | |--- app.tsx | |--- containerList.tsx | |--- dialogTrigger.tsx | |--- modal.tsx | |--- newContainerModal.tsx |--- index.tsx </code></pre> <p>They will all be housed inside an 'app' folder, with the smaller components inside a 'components' subfolder. <code>index.tsx</code> is essentially an entry point into our client-side app; it binds the React components to the Html Dom.</p> <p><code>app.tsx</code> glues everything together - it arranges and communicates with the other components in order to present the interface to the user and allow them to interact with the application. Let's set the project up to start compiling <code>index.tsx</code></p> <p>Create the 'app' folder, and then the 'index.tsx' file inside of that, with the following contents:</p> <pre><code class="javascript">import * as React from 'react' import * as ReactDOM from 'react-dom' import { AppComponent } from './components/app' ReactDOM.render( &lt;AppComponent /&gt;, document.getElementById('app') ) </code></pre> <p>If you're using the excellent <a href="https://code.visualstudio.com/">Visual Studio Code</a> you'll notice that it will immediately start throwing up intellisense issues, mainly because it doesn't know what 'react', 'react-dom' and our application component is. We're going to use Webpack and TypeScript to fix that!</p> <h3>Setting up Webpack</h3> <p>Webpack will take all our .tsx files, work out their dependencies based on the imported files, run them through the TypeScript compiler and then spit out one JavaScript file that we can include on the main Html page. It does this primarily by referencing a configuration file in the root of our project, so let's create that next.</p> <p>Create the file <code>webpack.config.js</code> in the root of your project, with the following contents:</p> <pre><code class="javascript">module.exports = { entry: "./app/index.tsx", output: { filename: "bundle.js", path: __dirname + "/public/js" }, devtool: "source-map", resolve: { extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"] }, module: { loaders: [ { test: /\.tsx?$/, loader: "ts-loader" } ] } }; </code></pre> <p>There's quite a bit in there, so let's go through it:</p> <ul> <li>The <code>entry</code> key tells Webpack to start processing files using the <code>/app/index.tsx</code> file.</li> <li>The output key tells Webpack where to put the output files; in the <code>/public/js</code> folder with the name <code>bundle.js</code>.</li> <li>The <code>devtool</code> key, along with the <code>source-map-loader</code> preloader in the <code>module</code> section, tells Webpack to generate source maps, which will come in very handy when trying to debug your JavaScript app later.</li> <li>The <code>resolve</code> key tells Webpack which extensions to pay attention to when resolving module.</li> <li>The <code>loaders</code> section tells Webpack what middleware to use when processing modules. Here we tell it that, whenever Webpack comes across a file with a .ts or .tsx extension, it should use the <code>ts-loader</code> tool. This is the tool that processes a TypeScript file and turns it into regular JavaScript.</li> </ul> <p>There is a lot more you can do with Webpack, including automatically splitting out common modules into a <code>common.js</code> file, or including css files along with your JavaScript, but what we have here is sufficient for our requirements.</p> <p>To get this to work, we still need to install the <code>ts-loader</code> and <code>source-map-loader</code> packages:</p> <p><code>npm install --save-dev ts-loader source-map-loader</code></p> <p>We also need to install the React packages that we need:</p> <p><code>npm install --save-dev react react-dom</code></p> <p>Next, we need install TypeScript into the project. We have already installed it globally in the first section of this article, so we can simply link it in:</p> <p><code>npm link typescript</code></p> <p>TypeScript itself needs a configuration file, which lives in the <code>tsconfig.json</code> file in the root of the project. Create that now, with the following content:</p> <pre><code class="json">{ "compilerOptions": { "outDir": "dist/", "sourceMap": true, "noImplicitAny": true, "module": "commonjs", "target": "es5", "jsx": "react" } } </code></pre> <p>The main parts of this configuration are the <code>module</code>, <code>target</code> and <code>jsx</code> keys, which instruct TypeScript how to output the correct code to load modules in the right way, and also how to deal with the React JSX syntax correctly (covered later).</p> <p>Let's see what state our Webpack set up is in at the moment. From the command line, simply type <code>webpack</code> to start compilation.</p> <p>It should give you some stats about compile times and sizes, along with a few errors:</p> <pre><code>ERROR in ./app/index.tsx (1,24): error TS2307: Cannot find module 'react'. ERROR in ./app/index.tsx (2,27): error TS2307: Cannot find module 'react-dom'. ERROR in ./app/index.tsx (3,30): error TS2307: Cannot find module './components/app'. ERROR in ./app/index.tsx (6,5): error TS2602: JSX element implicitly has type 'any' because the global type 'JSX.Element' does not exist. ERROR in ./app/index.tsx Module not found: Error: Cannot resolve 'file' or 'directory' ./components/app in /Users/stevenhobbs/Dev/personal/docker-dashboard/app @ ./app/index.tsx 4:12-39 </code></pre> <p>Essentially, it still doesn't know what 'react' is, so let's fix that now!</p> <h3>Installing typings for React</h3> <p>Because we've told Webpack that we're going to handle the React and ReactDOM libraries ourselves, we need to tell TypeScript what those things are. We do that using <a href="https://github.com/DefinitelyTyped/DefinitelyTyped">Type Definition Files</a>. As you can see from the Github repository, there are thousands of files, covering most of the JavaScript frameworks you've heard of. This is how we get rich typing, compile-time hints and intellisense while writing TypeScript files. Luckily, we can also install them using NPM.</p> <p>To install them, use:</p> <p><code>npm install --save-dev @types/react @types/react-dom</code></p> <p>Now try running <code>webpack</code> again. This time we get just one error, telling us that the <code>./components/app</code> module is missing. Create a skeleton file for now so that we can get it compiling, and inspect the results. Create the file <code>app/components/app.tsx</code> with the following content:</p> <pre><code class="javascript">import * as React from 'react' export class AppComponent extends React.Component&lt;{}, {}&gt; { render() { return (&lt;h1&gt;Docker Dashboard&lt;/h1&gt;) } } </code></pre> <p>At the moment it does nothing except print out 'Docker Dashboard' in a header tag, but it should at least compile. We'll flesh this out much more later on! For now though, you should be able to run the <code>webpack</code> command again now, and have it produce no errors.</p> <p>To inspect what Webpack has created for us, find the <code>public/js</code> folder and open the <code>bundle.js</code> file. You'll see that, while it does look rather obtuse, you should be able to recognise elements of your program in there towards the very bottom, as normal JavaScript that can run in the browser. It's also rather large, as it also includes the React libraries and it will include even more by the time we're finished!</p> <p>The next thing to do is include this file in our Html page. Open <code>index.html</code> and put a script tag near the bottom, underneath the Bootstrap include:</p> <pre><code class="html"> &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"&gt;&lt;/script&gt; &lt;!-- Add our bundle here --&gt; &lt;script src="/js/bundle.js"&gt;&lt;/script&gt; &lt;/body&gt; </code></pre> <p>Now, you should be at the point where you can run the site using <code>node server.js</code>, browse to <code>http://localhost:3000</code> and view the running website. If you can see 'Docker Dashboard' written using a large header font, then you've successfully managed to get your Webpack/TypeScript/React workflow working! Congratulations!</p> <p>Now let's flesh out the actual application a bit more and add some real value.</p> <h2>Creating the components</h2> <p>What we have now is a server-side application which acts as the backbone of our React app. Now that we have done all that setup and configuration, we can actually concentrate on creating the React components that will form the application's interface. Later on, we will tie the interface to the server using socket.io, but for now let's start with some React components.</p> <p>To figure out what components we need, let's take another look at a screenshot of the application, this time with the individual React components highlighted:</p> <p><img src="https://i.imgur.com/1Qek2Fd.png" alt="The Docker dashboard with components" /></p> <ul> <li>The DialogTrigger component displays a button which can trigger a Bootstrap modal dialog</li> <li>The ContainerItem component knows how to display a single Docker container, including some info about the container itself</li> <li>The ContainerList displays a number of ContainerItem components. There are two ContainerList components here - one for running containers, and one for stopped containers</li> </ul> <p>One additional component which is not shown in that screenshot is the modal dialog for starting new containers:</p> <p><img src="https://i.imgur.com/3YJoSpn.png" alt="The Docker dashboard modal dialog component" /></p> <p>To start with, let's create the component to display a single container. Create a new file in /app/components called <code>containerListItem.tsx</code>, and give it the following content:</p> <pre><code class="javascript">import * as React from 'react' import * as classNames from 'classnames' export interface Container { id: string name: string image: string state: string status: string } export class ContainerListItem extends React.Component&lt;Container, {}&gt; { // Helper method for determining whether the container is running or not isRunning() { return this.props.state === 'running' } render() { const panelClass = this.isRunning() ? 'success' : 'default' const classes = classNames('panel', `panel-${panelClass}`) const buttonText = this.isRunning() ? 'Stop' : 'Start' return ( &lt;div className="col-sm-3"&gt; &lt;div className={ classes }&gt; &lt;div className="panel-heading"&gt;{ this.props.name }&lt;/div&gt; &lt;div className="panel-body"&gt; Status: {this.props.status}&lt;br/&gt; Image: {this.props.image} &lt;/div&gt; &lt;div className="panel-footer"&gt; &lt;button className="btn btn-default"&gt;{buttonText}&lt;/button&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; ) } } </code></pre> <p>Here we have defined a component that can render a single container. We also declare an interface that has all of the properties about a container that we'd want to display, like its name, image and current status. We define the 'props' type of this component to be a Container, which means we can get access to all the container information through <code>this.props</code>.</p> <p>The goal of this component is to not only display the current status of the component, but also to handle the start/stop button - this is something we'll flesh out later once we get into the socket.io goodness.</p> <p>The other interesting this component can do, is slightly alter its appearance depending on whether the container is running or not. It has a green header when it's running, and a grey header when it's not. It does this by simply switching the Css class depending on the status.</p> <p>We'll need to install the <code>classnames</code> package for this to work, along with its TypeScript reference typings. To do that, drop into the command line once more:</p> <p><code>npm install --save classnames</code></p> <p><code>npm install --save-dev @types/classnames</code></p> <p><a href="https://www.npmjs.com/package/classnames">Classnames</a> is not strictly necessary, but does provide a handy API for conditionally concatenating CSS class names together, as we are doing here.</p> <p>Next, let's create the <code>ContainerItemList</code> component, which is in charge of displaying a whole list of these components together. Create a new file in <code>/app/components</code> called <code>ContainerList</code> with the following content:</p> <pre><code class="javascript">import * as React from 'react' import { Container, ContainerListItem } from './containerListItem' export class ContainerListProps { containers: Container[] title?: string } export class ContainerList extends React.Component&lt;ContainerListProps, {}&gt; { render() { return ( &lt;div&gt; &lt;h3&gt;{this.props.title}&lt;/h3&gt; &lt;p&gt;{ this.props.containers.length == 0 ? "No containers to show" : "" }&lt;/p&gt; &lt;div className="row"&gt; { this.props.containers.map(c =&gt; &lt;ContainerListItem key={c.name} {...c} /&gt;) } &lt;/div&gt; &lt;/div&gt; ) } } </code></pre> <p>This one is a little simpler as it doesn't do too much except display a bunch of <code>ComponentListItem</code>s in a list. The properties for this component include an array of <code>Container</code> objects to display, and a title for the list. If the list of containers is empty, we show a short message.</p> <p>Otherwise, we use <code>map()</code> to convert the list of <code>Container</code> types into <code>ContainerListItem</code> components, using the <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Spread_operator">spread operator</a> (the <code>...c</code> part) to apply the properties on <code>Container</code> to the component. We also give it a key so that React can uniquely identify each container in the list. I'm using the name of the container, seeing as that will be unique in our domain (you can't create two Docker containers with the same name, running or not).</p> <p>So now we have a component to render a container, and one to render a list of containers with a title, let's flesh out the App container a bit more.</p> <h3>Displaying some containers</h3> <p>Back to <code>app.tsx</code>. First we need to import our new containers into the module:</p> <pre><code class="javascript">import { Container, ContainerListItem } from './containerListItem' import { ContainerList } from './containerList' </code></pre> <p>Next, we'll create a couple of dummy containers just for the purpose of displaying something on screen; we'll swap this out later with real data from the Docker Remote API. Add this inside the AppComponent class, near the top:</p> <pre><code class="javascript">containers: Container[] = [ { id: '1', name: 'test container', image: 'some image', state: 'running', status: 'Running' }, { id: '2', name: 'another test container', image: 'some image', state: 'stopped', status: 'Running' } ] </code></pre> <p>Now we need to create some state for this application component. The state will simply tell us which components are running, and which are stopped. We'll use this state to populate the two lists of containers respectively.</p> <p>To this end, create a new class <code>AppState</code> outside of the main application component to hold this state:</p> <pre><code class="javascript">class AppState { containers?: Container[] stoppedContainers?: Container[] } </code></pre> <p>Now change the type of the state on <code>AppComponent</code> so that TypeScript knows what properties are available on our state. Your <code>AppComponent</code> declaration should now look like this:</p> <pre><code class="javascript">export class AppComponent extends React.Component&lt;{}, AppState&gt; { </code></pre> <p>Then create a constructor inside <code>AppComponent</code> to initialise our state, including giving it our mocked-up containers. To do this, we use <a href="https://lodash.com/docs/4.17.2">lodash</a> to partition our container list into two lists based on the container state. This means that we'll have to install lodash and the associated typings:</p> <pre><code>npm install --save lodash npm install --save-dev @types/lodash </code></pre> <p>And then import the lodash library at the top of the file:</p> <pre><code class="javascript">import * as _ from 'lodash' </code></pre> <p>Lodash is a very handy utility library for performing all sorts of operations on lists, such as sorting, filtering - and in our case - partitioning!</p> <p>Here's the constructor implementation:</p> <pre><code class="javascript">constructor() { super() const partitioned = _.partition(this.containers, c =&gt; c.state == 'running') this.state = { containers: partitioned[0], stoppedContainers: partitioned[1] } } </code></pre> <p>Now in our state we should have two lists of containers - those that are running, and those that aren't.</p> <p>Finally, let's replace the render method so that it takes our dummy containers and uses our components to represent them on the screen:</p> <pre><code class="javascript">render() { return ( &lt;div className="container"&gt; &lt;h1 className="page-header"&gt;Docker Dashboard&lt;/h1&gt; &lt;ContainerList title="Running" containers={this.state.containers} /&gt; &lt;ContainerList title="Stopped containers" containers={this.state.stoppedContainers} /&gt; &lt;/div&gt; ) } </code></pre> <p>At this point you should have a basic dashboard setup with some dummy containers - let's have a look:</p> <p><img src="https://i.imgur.com/faVfciE.png" alt="A basic dashboard" /></p> <h2>Making things dynamic!</h2> <p>Let's have a look at the Docker and socket.io side of things now, and replace those dummy containers with some real data!</p> <p>Firstly, install <a href="https://github.com/apocas/dockerode">dockerode</a>, a NodeJS library that enables us to interact with the Docker Remote API:</p> <p><code>npm install --save dockerode</code></p> <p>Next, install the libraries and associated typings for <a href="http://socket.io/">socket.io</a> - we'll be using this both on the server-side <em>and</em> the client, as a means of communicating between the two:</p> <pre><code>npm install --save socket.io npm install --save-dev @types/socket.io @types/socket.io-client </code></pre> <p>Now, open <code>server.js</code> in the root of the project and import socket.io, binding it to the Express server that we've already created:</p> <pre><code class="javascript">let io = require('socket.io')(server) </code></pre> <p>We can also get a connection to the Docker Remote API at this point, through Dockerode. We need to connect to the API differently depending on whether we're on a Unix system or a Windows system, so let's house this logic in a new module called <code>dockerapi.js</code> in the root of the project:</p> <pre><code class="javascript">let Docker = require("dockerode"); let isWindows = process.platform === "win32"; let options = {}; if (isWindows) { options = { host: '127.0.0.1', port: 2375 } } else { options = { socketPath: '/var/run/docker.sock' } } module.exports = new Docker(options); </code></pre> <p>Now we can include this in our <code>server.js</code> file and get a handle to the API:</p> <pre><code class="javascript">let docker = require('./dockerapi') </code></pre> <p>We're going to provide the client with a few methods; getting a list of containers, starting a container, stopping a container, and running a new container from an exiting image. Let's start with the container list.</p> <p>Firstly, we need to listen for connections. We can do this further down the <code>server.js</code> script, after we start the web server on the line that begins <code>server.listen(..)</code></p> <pre><code class="javascript">io.on('connection', socket =&gt; { socket.on('containers.list', () =&gt; { refreshContainers() }) }) </code></pre> <p>This starts socket.io listening for connections. A connection will be made when the React app starts; at least it will be when we put the code in a bit later on!</p> <p>In order to send the list of Docker containers, we listen for the 'containers.list' message being sent from the socket that has connected to the server; in other words, the client app has requested the list of containers from the server. Let's go ahead and define the <code>refreshContainers()</code> method:</p> <pre><code class="javascript">function refreshContainers() { docker.listContainers({ all: true}, (err, containers) =&gt; { io.emit('containers.list', containers) }) } </code></pre> <p>Whenever we call <code>refreshContainers()</code>, the Docker API will be used to retrieve the list of all of the containers that exist on the current system (running or not), which will then send them all using the 'containers.list' message through socket.io. Notice though that we're sending the message through the main <code>io</code> object rather than through a specific socket - this means that <em>all of the clients</em> currently connected will have their container lists refreshed. You will see why this becomes important later in the article.</p> <p>Moving over to the main React component, we should now be able to start picking up messages through socket.io which indicate that we should display the container list. First, import the socket.io library and connect to the socket.io server:</p> <pre><code class="javascript">import * as io from 'socket.io-client' let socket = io.connect() </code></pre> <p>Next, delete the mocked-up containers that we had put in before. Then change the constructor so that we react to the messages being passed to us from socket.io instead of using our mocked-up containers. We will also initialise the component state so that the containers are just empty lists; the component will populate them at some short time in the future when it has received the appropriate message. Here's what the constructor looks like now:</p> <pre><code class="javascript">constructor() { super() this.state = { containers: [], stoppedContainers: [] } socket.on('containers.list', (containers: any) =&gt; { const partitioned = _.partition(containers, (c: any) =&gt; c.State == "running") this.setState({ containers: partitioned[0].map(this.mapContainer), stoppedContainers: partitioned[1].map(this.mapContainer) }) }) } </code></pre> <p>We listen for messages using <code>io.on()</code> and specify the message string. When our socket receives a message with this name, our handler function will be called. In this case, we handle it and receive a list of container objects down the wire. We then partition it into running and stopped containers (just as we did before) and then we set the state appropriately. Each container from the server is mapped to our client-side Container type using a function <code>mapContainer()</code>, which is shown here:</p> <pre><code class="javascript">mapContainer(container:any): Container { return { id: container.Id, name: _.chain(container.Names) .map((n: string) =&gt; n.substr(1)) .join(", ") .value(), state: container.State, status: `${container.State} (${container.Status})`, image: container.Image } } </code></pre> <p>This is where we extract out properties such as the name, image, status and so on. Any other properties that you want to include on the UI in the future, you will probably read inside this function.</p> <p>So now we have the ability to react to socket.io messages coming down the wire, the next thing to do is cause the server to send us the container list! We do this by sending a 'containers.list' message to the server using <code>socket.emit</code>, which will send all the connections a similarly-titled message back with the container data. We can send this message from the <code>componentDidMount</code> event, which is called on our Component once it has been 'mounted' to the DOM:</p> <pre><code class="javascript">componentDidMount() { socket.emit('containers.list') } </code></pre> <p>Right now, you should be able to start your app and have it display a list of the running and stopped Docker containers on your machine!</p> <p><img src="https://i.imgur.com/F1Llyk4.png" alt="My Docker containers" /></p> <h2>Starting containers</h2> <p>Being able to start and stop a container is merely an extension of what we've already accomplished. Let's have a look at how we can start a container when we click the 'Start' button.</p> <h3>Wiring up the start button</h3> <p>The workflow we're going to implement looks like this:</p> <ol> <li>We are going to handle the 'click' event of the start button from inside the React component.</li> <li>Inside the click event, we're going to send a message to the socket running on the server.</li> <li>The server will receive the message and tell Docker to start the appropriate container.</li> <li>When the container starts, the server will dispatch a message to all connections with a refreshed list of containers.</li> </ol> <p>Let's start with the button. Alter the button inside your <code>ContainerListItem</code> component so that it handles the click event using a method called <code>onActionButtonClick</code>:</p> <pre><code class="javascript">&lt;button onClick={this.onActionButtonClick.bind(this)} className="btn btn-default"&gt;{buttonText}&lt;/button&gt; </code></pre> <p>Next create, the <code>onActionButtonClick</code> handler somewhere inside the same component:</p> <pre><code class="javascript">onActionButtonClick() { socket.emit('container.start', { id: this.props.id }) } </code></pre> <p>Here we post the 'container.start' message to the socket along with the container id. Armed with this information, we'll be able to tell Docker which container to start. You might find that you'll get an issue here, because TypeScript doesn't know what <code>socket</code> is yet. We can fix that by importing <code>socket.io-client</code> and connecting to the server socket. At the top of the file, then:</p> <pre><code class="javascript">import * as io from 'socket.io-client' const socket = io.connect() </code></pre> <p>Now everything should be fine. To complete the feature, let's pop over to the server side and handle the incoming message. Open <code>server.js</code> and add the following somewhere inside your socket connection handler, alongside where you handle the 'containers.list' message:</p> <pre><code class="javascript">socket.on('container.start', args =&gt; { const container = docker.getContainer(args.id) if (container) { container.start((err, data) =&gt; refreshContainers()) } }) </code></pre> <p>Here we simply get a container from Docker using the id that we get from the client. If the container is valid, we call <code>start</code> on it. Once start has completed, we call our <code>refreshContainers</code> method that we already have. This will cause socket.io to send our current list of containers to all the connected clients.</p> <h2>Stopping containers</h2> <p>The functionality for stopping containers that are running is done in much the same way; we send a message through socket.io to the server with a 'containers.stop' message, the server stops the relevant container and then tells everyone to refresh their container list.</p> <p>Once again, let's start on the component side of things. In the previous section, we added a handler for the 'start/stop' button which tells socket.io to send a message to start the container. Let's tweak that a bit so that we can use it for stopping containers too; we'll just send the right message or not depending on whether the container is currently running or not. So this handler now becomes:</p> <pre><code class="javascript">onActionButtonClick() { const evt = this.isRunning() ? 'container.stop' : 'container.start' socket.emit(evt, { id: this.props.id }) } </code></pre> <p>Next, we'll handle the message on the server. Add a handler for this alongside the one we added in the previous section for 'container.start':</p> <pre><code class="javascript">socket.on('container.stop', args =&gt; { const container = docker.getContainer(args.id) if (container) { container.stop((err, data) =&gt; refreshContainers()) } }) </code></pre> <p>The code looks strikingly similar to the start code, except we <em>stop</em> a container instead of starting it. If you run the app now, you should be able to start and stop your containers!</p> <h3>Periodically refreshing container state</h3> <p>Before we head into the last section, now would be a good time to add a quick feature that will automatically refresh our container state. As awesome as our new Docker dashboard is, containers can be started, stopped, created and destroyed from a few different places outside of our app, such as the command line. It would be nice to reflect these changes in our app too.</p> <p>A quick and easy way to achieve this is to simply read the container state every x seconds, then update our clients. We already have most of the tools to do this, so let's implement it!</p> <p>Back in <code>server.js</code> in the server-side app, add a quick one-liner to send an updated list of Docker containers every 2 seconds. Put this outside of the <code>io.on('connection', ...</code> block:</p> <pre><code class="javascript">setInterval(refreshContainers, 2000) </code></pre> <p>Now, once your app is running, dive into the command line and stop one of your containers using <code>docker stop &lt;container id or name&gt;</code>, and you should see the container stop inside your dashboard too!</p> <p>Furthermore, thanks to the power of socket.io, you should be able to open your dashboard in multiple browsers and <em>see them all update at the same time</em>. Go ahead and try browsing your dashboard on your mobile device too!</p> <h2>Starting brand new containers</h2> <p>In this final section, we're going to explore how we can start brand new containers from exiting Docker images. This will involve a couple of new React components, a <a href="http://getbootstrap.com/javascript/#modals">Bootstrap Modal popup</a> and some more interaction with socket.io and the Docker API.</p> <p>First, let's create the React components. There are 3 components involved:</p> <ul> <li>A 'modal' component, which is a generic component for creating any modal dialog</li> <li>A 'new container model' component, which is based upon the generic modal component for showing the new container-specific UI, as well as handling validation</li> <li>A 'dialog trigger' component which is used to show a modal dialog component on the screen.</li> </ul> <h3>Creating a generic modal popup component</h3> <p>Let's start with the generic component, seeing as our modal for creating a new container will be based upon this one. We're making a generic component just as an exercise to show you how you can extend such a component for multiple uses. For example, later you might go on to create a dialog to accept an image name that will be pulled from the Docker hub - you could also base that modal upon this generic component.</p> <p>Create a new file in the 'components' director called <code>modal.tsx</code>, and begin by importing the relevant modules:</p> <pre><code class="javascript">import * as React from 'react' </code></pre> <p>Next, define some properties that our modal can accept so that we can configure how it looks and works:</p> <pre><code class="javascript">interface ModalProperties { id: string title: string buttonText?: string onButtonClicked?: () =&gt; boolean|undefined } </code></pre> <p>We must take an id and a title, but we can also accept some text for the button on the dialog and also a handler for the button click, so that we can define what happens when the user clicks the button. Remember that this component is designed to be used in a generic way - we don't actually know what the behaviour will be yet!</p> <p>Now let's define the component itself:</p> <pre><code class="javascript">export default class Modal extends React.Component&lt;ModalProperties, {}&gt; { // Store the HTML element id of the modal popup modalElementId: string constructor(props: ModalProperties) { super(props) this.modalElementId = `#${this.props.id}` } onPrimaryButtonClick() { // Delegate to the generic button handler defined by the inheriting component if (this.props.onButtonClicked) { if (this.props.onButtonClicked() !== false) { // Use Bootstrap's jQuery API to hide the popup $(this.modalElementId).modal('hide') } } } render() { return ( &lt;div className="modal fade" id={ this.props.id }&gt; &lt;div className="modal-dialog"&gt; &lt;div className="modal-content"&gt; &lt;div className="modal-header"&gt; &lt;button type="button" className="close" data-dismiss="modal" aria-hidden="true"&gt;&amp;times;&lt;/button&gt; &lt;h4 className="modal-title"&gt;{ this.props.title }&lt;/h4&gt; &lt;/div&gt; &lt;div className="modal-body"&gt; { this.props.children } &lt;/div&gt; &lt;div className="modal-footer"&gt; &lt;button type="button" onClick={this.onPrimaryButtonClick.bind(this)} className="btn btn-primary"&gt;{ this.props.buttonText || "Ok" } &lt;/button&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; ) } } </code></pre> <p>The component definition itself is mostly straightforward - we just render out the appropriate Bootstrap markup for modal popups, but we pepper it with values, such as the component title. We also specify the client handler on the button as well as the button text. If the component doesn't specify what the button text should be, the default value "Ok" is used, using this line:</p> <pre><code class="javascript">{ this.props.buttonText || "Ok" } </code></pre> <p>Most importantly, the component called <code>this.props.children</code> for the modal body. You'll see why this important in the next section, but basically it allows us to render other components that are specified as children of this component. More on that later.</p> <p>Also note the <code>onPrimaryButtonClick</code> handler; when the button is clicked, it delegates control to whatever is using this component, but it also inspects the return value from that call. If false is returned, it doesn't automatically close the dialog. This is useful for later when we don't want to close the dialog in the event that our input isn't valid.</p> <p>One last thing before we move on; when this component compiles, you'll probably find that TypeScript will complain that it can't find <code>$</code>, which is true since we haven't imported it. To fix this, we need to simply install the typings for jQuery so that it knows how to resolve that symbol. You will also need to install the types for Twitter Bootstrap, so that it knows what the bootstrap-specific methods and properties are.</p> <p>In the command line, then:</p> <pre><code>npm install --save-dev @types/jquery @types/bootstrap </code></pre> <h3>Creating the 'new container' dialog</h3> <p>This dialog will be defined by creating a new dialog component and wrapping the content in the generic dialog component that we created in the last section, specifing some things like the title and what happens when the user clicks the button. Create a new file for the component called 'newContainerModal'.</p> <p>Firstly, define our imports:</p> <pre><code class="javascript">import * as React from 'react' import Modal from './modal' import * as classNames from 'classnames' </code></pre> <p>Note that we're importing our generic modal as <code>Modal</code>, allowing us to make use of it in this new modal component - more on that shortly.</p> <p>Now let's define some incoming properties, and some state for our new component:</p> <pre><code class="javascript">interface ModalProperties { id: string, onRunImage?: (name: string) =&gt; void } interface ModalState { imageName: string isValid: boolean } </code></pre> <p>For the properties, we allow an id for the component to be set - this will make sense soon when we create our last component, the 'modal dialog trigger'. We also take a function that we can call when the name of an image to run has been entered.</p> <p>For the state, we're going to record the name of the image that was entered, and also some basic form validation state using the <code>isValid</code> flag.</p> <p>As a reminder, this is what this modal popup is going to look like; there's just one text field and one button:</p> <p><img src="https://i.imgur.com/3YJoSpn.png" alt="The Docker dashboard modal dialog component" /></p> <p>Let's fill out the component and have a look at its <code>render</code> method. Also note the constructor, where can initialise the component state to something default:</p> <pre><code class="javascript">export class NewContainerDialog extends React.Component&lt;ModalProperties, ModalState&gt; { constructor(props: ModalProperties) { super(props) this.state = { imageName: '', isValid: false } } render() { let inputClass = classNames({ "form-group": true, "has-error": !this.state.isValid }) return ( &lt;Modal id="newContainerModal" buttonText="Run" title="Create a new container" onButtonClicked={this.runImage.bind(this)}&gt; &lt;form className="form-horizontal"&gt; &lt;div className={inputClass}&gt; &lt;label htmlFor="imageName" className="col-sm-3 control-label"&gt;Image name&lt;/label&gt; &lt;div className="col-sm-9"&gt; &lt;input type="text" className="form-control" onChange={this.onImageNameChange.bind(this)} id="imageName" placeholder="e.g mongodb:latest"/&gt; &lt;/div&gt; &lt;/div&gt; &lt;/form&gt; &lt;/Modal&gt; ) } } </code></pre> <p>Hopefully now you can see how the component is constructing using the generic modal component we created earlier. In this configuration, the <code>Modal</code> component acts as a <em>higher-order component</em>, wrapping other components inside of it, instead of our new component <em>inheriting</em> from it as we might have otherwise done.</p> <p>The rest of the markup is fairly standard Bootstrap markup that defines a form field with a label. Three things to note, however:</p> <ul> <li>We apply a class to the <code>div</code> that wraps the form elements that is derived from our <code>isValid</code> state property; if the form isn't valid, the input box gets a nice red border, and the user can see they've done something wrong</li> <li>We specify a handler for the textbox's 'onChange' event, allowing us to handle and record what the user is typing in</li> <li>We specify a handler for the generic modal's button click - when the user clicks that button, our new component is going to handle the event and do something specific to our needs. We'll come back to this in a minute</li> </ul> <p>Let's define that change handler now:</p> <pre><code class="javascript">onImageNameChange(e: any) { const name = e.target.value this.setState({ imageName: name, isValid: name.length &gt; 0 }) } </code></pre> <p>All of the form behaviour is captured here. As the user is typing into the box, we record the input value into the <code>imageName</code> state property, and also determine whether or not it's valid; for now, it's good enough for the image name to have at least one character.</p> <p>Next, we need to define what happens when the user clicks the button on the modal popup. This is done inside the <code>runImage</code> function:</p> <pre><code class="javascript">runImage() { if (this.state.isValid &amp;&amp; this.props.onRunImage) this.props.onRunImage(this.state.imageName) return this.state.isValid } </code></pre> <p>This should be fairly straightforward - we simply say that if the state of the component is valid, and the <code>onRunImage</code> handler has been defined, we call it with the name of the image that the user typed in. We also return a value which indicates to the generic modal component that it should close itself. This happens to just be the same thing is the value of the <code>isValid</code> flag.</p> <p>That's it for this component - let's create a trigger component so that we can open it!</p> <h3>Triggering the modal</h3> <p>This last component is going to represent the trigger - the thing the user will click on - that opens a modal popup. It's definition is actually very simple. Create a new component called 'dialogTrigger.tsx' and populate it with the following:</p> <pre><code class="javascript">import * as React from 'react' export interface DialogTriggerProperties { id: string buttonText: string } export class DialogTrigger extends React.Component&lt;DialogTriggerProperties, {}&gt; { render() { const href = `#${this.props.id}` return ( &lt;a className="btn btn-primary" data-toggle="modal" href={ href }&gt;{ this.props.buttonText }&lt;/a&gt; ) } } </code></pre> <p>For the component properties, we take the id of the modal we want to trigger, and also the text that we want to show on the button. Then inside the render function, a standard Bootstrap link is displayed with button styling and the id of the modal to open. If you're not familiar with Bootstrap, note that the actual opening of the dialog is all done with the Bootstrap JavaScript library - all we need to do is specify the <code>data-toggle="modal"</code> attribute and set the href attribute to the id of the modal we want to open.</p> <h2>Tying it all together</h2> <p>Now that we have all of our modal components, we can put them all together. Head back to <code>app.tsx</code> and import all the components we just created:</p> <pre><code class="javascript">import { NewContainerDialog } from './newContainerModal' import { DialogTrigger } from './dialogTrigger' </code></pre> <p>There's no need to import the generic Modal component, as that will be done by the <code>NewContainerDialog</code> component; we're not going to use it directly here.</p> <p>Now, update the render function so that it contains our new components. For the trigger, place it under the header, and for the 'new container' dialog, it just needs to go on the page somewhere; Bootstrap will place it correctly once it has been opened:</p> <pre><code class="javascript">render() { return ( &lt;div className="container"&gt; &lt;h1 className="page-header"&gt;Docker Dashboard&lt;/h1&gt; &lt;DialogTrigger id="newContainerModal" buttonText="New container" /&gt; &lt;ContainerList title="Running" containers={this.state.containers} /&gt; &lt;ContainerList title="Stopped containers" containers={this.state.stoppedContainers} /&gt; &lt;NewContainerDialog id="newContainerModal" onRunImage={this.onRunImage.bind(this)} /&gt; &lt;/div&gt; ) } </code></pre> <p>Note how the id property of <code>DialogTrigger</code> is the same as the id property of <code>NewContainerDialog</code> - this is necessary in order for the trigger to understand that this is the dialog it needs to trigger.</p> <p>Also note how the <code>onRunImage</code> property of the dialog component is defined - let's create that now:</p> <pre><code class="javascript">onRunImage(name: String) { socket.emit('image.run', { name: name }) } </code></pre> <p>It just sends the name of the image to the server inside a message called 'image.run'. We can define that now by heading over to <code>server.js</code> and handling a new message alongside where we've created the others:</p> <pre><code class="javascript">socket.on('image.run', args =&gt; { docker.createContainer({ Image: args.name }, (err, container) =&gt; { if (!err) container.start((err, data) =&gt; { if (err) socket.emit('image.error', { message: err }) }) else socket.emit('image.error', { message: err }) }) }) </code></pre> <p>Here we call out to the Docker API and its convenient <code>createContainer</code> method, passing in the image name that the user typed in. <em>This will not pull new images from the Docker Hub</em> - it will only start new containers from existing images that exist on the local system. However, it can certainly be done - I'll leave it as an exercise for you, the reader, to complete in your own time.</p> <p>If we're able to create the container, we'll start it. Remember our timer that we created earlier? Once the container starts, that timer will pick up the new container and display it to all the clients that are connected!</p> <p>Finally, if there is an error we can send an 'image.error' message back to the socket that sent the original 'image.run' message, which will be useful for the user so that they are aware that something didn't work as expected. Let's head back to the app component for the final piece of the puzzle. Inside the constructor of the <code>app.tsx</code> component:</p> <pre><code class="javascript">socket.on('image.error', (args: any) =&gt; { alert(args.message.json.message) }) </code></pre> <p>Here we simply throw an alert if Docker encounters an error running the image. Armed with your new-found React knowledge, I'm sure you can now come up with some fancy UI to make this a lot prettier!</p> <h2>Wrapping up</h2> <p>By now you should have a useful but somewhat basic Docker dashboard, and hopefully the journey has been worth it! With all the socket.io goodness, be sure to play around with loading your app from multiple sources, like your desktop browser and mobile phone, and watch them all keep in sync!</p> <p>Some things you could continue on with to make it a lot more useful, include:</p> <ul> <li>Using the Docker API to pull images instead of simply running them.</li> <li>Using the Docker API to stream the container logs to the client through Socket.io.</li> <li>Extending the container dialog form to include options for port mapping, volumes, container name and more!.</li> </ul> The Real Story Behind ECMAScript 4 2017-03-01T12:30:00+00:00 https://auth0.com/blog/the-real-story-behind-es4/ Sebastián Peyrott https://twitter.com/speyrott?lang=en <p>Our JavaScript history article sparked interesting comments regarding what really happened during the ECMAScript 4 era. Below you will find a more detailed perspective of what really went down between 1999 and 2008 in the world of JavaScript. Read on!</p> <blockquote class="tweet-quote"> <a href="https://twitter.com/intent/tweet?text=&quot;A deeper look onto what really went on with ECMAScript 4&quot; via @auth0 http://auth0.com/blog/the-real-story-behind-es4/"> <p>"A deeper look onto what really went on with ECMAScript 4"</p> <p class="tweet-link">TWEET THIS <img src="https://cdn.auth0.com/blog/resources/twitter.svg"></p> </a> </blockquote> <script> $(function() { $('.tweet-quote').on('click', function() { metricsLib.track('blog:share:twitter_quote'); }); }); </script> <hr /> <h2>A Short Recap</h2> <p>As we explained in detail in our <a href="https://auth0.com/blog/a-brief-history-of-javascript/">JavaScript history piece</a>, JavaScript was originally conceived as a "glue" programming language for designers and amateur programmers. It was meant to be a simple scripting language for the Web, one that could be used for animations, preliminary form checks and dynamic pages. Time showed, however, that people wanted to do much more with it.</p> <p>A year after its release in 1995 Netscape took JavaScript to ECMA, a standards organization, to create a standard for JavaScript. In a way, this was a two-sided effort: on one hand, it was an attempt to keep implementors in check (i.e., keeping implementations compatible), and it was also a way for other players to be part of the development process without leaving room for classic "embrace, extend, extinguish" schemes.</p> <p>A major milestone was finally reached in 1999 when ECMAScript 3 was released. This was the year of Netscape Navigator 6 and Internet Explorer 5. AJAX was just about to be embraced by the web development community. Although dynamic web pages were already possible through hidden forms and inner frames, AJAX brought a revolution in web functionality, and JavaScript was at its center.</p> <p>To better understand what happened after 1999, we need to take a look at three key players: Netscape, Microsoft and Macromedia. Of these three, only Netscape and Microsoft were part of TC-39, the ECMAScript committee, in 1999.</p> <h2>Netscape</h2> <p>In 1999, some members of TC-39 were already working on ideas for what could be ECMAScript 4. In particular, Waldemar Horwat at Netscape had begun documenting a series of ideas and proposals for the future evolution of ECMAScript. The <a href="https://web.archive.org/web/20000816194528/http://mozilla.org/js/language/js20-1999-02-18/index.html">earliest draft, dated February, 1999 can be found in the Wayback Machine</a>. An interesting look at the ideas for the next version of ECMAScript is outlined in the <a href="https://web.archive.org/web/20000823225602/http://mozilla.org/js/language/js20-1999-02-18/motivation.html">Motivation section</a>:</p> <blockquote><p>JavaScript is not currently a general-purpose programming language. Its strengths are its quick execution from source (thus enabling it to be distributed in web pages in source form), its dynamism, and its interfaces to Java and other environments. JavaScript 2.0 is intended to improve upon these strengths, while adding others such as the abilities to reliably compose JavaScript programs out of components and libraries and to write object-oriented programs. - <strong><a href="https://web.archive.org/web/20000823225602/http://mozilla.org/js/language/js20-1999-02-18/motivation.html">Waldemar Horwat's early JavaScript 2.0 proposal</a></strong></p></blockquote> <p>However, Netscape would not be the first with a public implementation of these ideas. It would be Microsoft.</p> <h2>Microsoft</h2> <p>In 1999 Microsoft was focused on a revolution of its own: <a href="https://en.wikipedia.org/wiki/.NET_Framework">.NET</a>. It was around the release of Internet Explorer 5 and ECMAScript 3 that Microsoft was getting ready to release the first version of the .NET Framework: a full development platform around a new set of libraries and a common language runtime, capable of providing a convenient execution environment for many different languages. The first exponents of .NET were C# and Visual Basic .NET: the first, an entirely new language inspired by Java and C++; the second, an evolution of its popular Visual Basic language, targeting the new platform. The .NET Framework included support for Microsoft's server-side programming framework: ASP.NET. It was perhaps natural that ASP.NET should provide a JavaScript-like language as part of its tools, and an implementation of a dynamic language such as JavaScript could very well serve as a natural demonstration of the capabilities of the common language runtime. Thus JScript .NET was born.</p> <p>JScript .NET was <a href="https://msdn.microsoft.com/en-us/library/ms974588.aspx">introduced in 2000</a>. It was slated as an evolution of JScript, the client-side scripting engine used by Internet Explorer, with a focus on performance and server-side uses, a natural fit for the .NET architecture and the ASP.NET platform. It would also serve to displace VBScript, another scripting language developed by Microsoft in the '90s with heavy inspiration from Visual Basic, normally used for server-side/desktop scripting tasks.</p> <p>One of the design objectives of JScript .NET was to remain largely compatible with existing JScript code; in other words, mostly compatible with ECMAScript 3. There were implementation differences between JScript and Netscape's JavaScript; however it was Microsoft's stated objective to follow the standard. It was also one of the objectives from ECMAScript 4 to remain compatible with previous versions of the standard (in the sense that ECMAScript 3 code should run on ECMAScript 4 interpreters). ECMAScript 4 was, thus, a convenient evolution path for JScript .NET. Released from the constraints of browser development, the team behind JScript .NET could work faster and iterate at their discretion. JScript .NET became, much like Macromedia's ActionScript, another experimental implementation of many of the ideas behind ECMAScript 4.</p> <p>In the words of the JScript .NET team:</p> <blockquote><p>(...) all the new features have been designed in conjunction with other ECMA members. It's important to note that the language features in the JScript .NET PDC release are not final. We're working with other ECMA members to finalize the design as soon as possible. In fact, there's an ECMA meeting this week at the PDC where we'll try to sort out some of the remaining issues. - <strong><a href="https://msdn.microsoft.com/en-us/library/ms974588.aspx">Introducing JScript .NET</a></strong></p></blockquote> <p>In contrast with the first versions of ActionScript, the first releases of JScript .NET in 2000 already included much more functionality from ECMAScript 4: classes, optional typing, packages and access modifiers were some of its new features.</p> <h2>Macromedia</h2> <p>As the Internet was becoming popular, spearheaded by Netscape and its Communicator suite, a different but no less important battle was taking place. Vector animation companies FutureWave Software and Macromedia had developed by 1995 two of the leading animation platforms: Macromedia Shockware and FutureWave FutureSplash.</p> <p>From the beginning, Macromedia saw the importance of taking its product to the Web, so with help from Netscape it integrated its Shockwave Player into Netscape Navigator as a plugin. Much of the work required for having "external components" in the browser had already been done for Java, so the needed infrastructure was in place.</p> <p>In November 1996, Macromedia acquired FutureSplash and promptly renamed it Flash. This made Macromedia the sole owner of the two most important vector-based animation tools for the Web: Shockwave and Flash. For a time, both players and authoring tools coexisted, but after a few years Flash emerged as the winner.</p> <p>The combined power of the web platform, getting bigger and bigger by the day, and the push from content creators caused Flash to evolve rapidly. The next big step for animation software was to become a platform for interactive applications, much like Java offered at the moment, but catering to designers and with special focus on animation performance and authoring tools. The power of a certain programmability first came to Flash in version 2 (1997) with <em>actions</em>.</p> <p>"Actions" were simple operations that could be triggered by user interaction. These operations did not resemble a full programming language. Rather, they were limited to simple "goto-style" operations in the animation timeline.</p> <p>However, by version 4 (1999), <em>actions</em> had pretty much evolved into a programming language: loops, conditionals, variables and other typical language constructs were available. However, the limitations of the language were becoming apparent and Macromedia was in need of something more mature. As it turns out, browsers already had one such language: JavaScript. Catering to non-programmers and already with considerable mindshare, JavaScript was a sound choice.</p> <p>Flash Player version 5 (2000) drew heavily from ECMAScript 3 for its scripting language. Combined with some of the constructs used for previous versions, this new language expanded actions with many tools from ECMAScript such as its prototype-based object model and weak typed variables. Many keywords (such as <code>var</code>) were also shared. This new language was called ActionScript.</p> <p>By this year, Macromedia was committed to improving ECMAScript. The synergy between JavaScript in the browser and ActionScript in Flash was just what Macromedia needed: Macromedia got a powerful programming language, and at the same time tapped into the mindshare from the already-existing designer-oriented JavaScript community. It would be in Macromedia's best interest to see ECMAScript succeed.</p> <h3>Flash as a Platform</h3> <p>The power of vector-based animations, a convenient editor and a powerful programming language proved to be a killer combination. Not only were more and more end users installing the Flash Player plugin, but content creators were also producing ever more complex content. Flash was quickly becoming a tool for more than just animations; it was becoming a platform to deliver rich content, with complex business logic behind it. In a sense, Macromedia had a big advantage compared to the rest of the Web: it was the sole owner and developer of the platform. That meant it could iterate and improve on it and at a much quicker pace than the Web itself. Not only that, it also had the best authoring tools for visual and interactive content, and the mindshare of developers and designers dedicated to this type of content. All of this put Macromedia ahead of other players, even Sun and its Java language (with regards to Java applets in the browser).</p> <p>The next natural step for Macromedia was to move forward. It had the best authoring tools and it was gaining developer mindshare. It was only logical to keep investing and advancing the development of its tools. And one of these tools was ActionScript. Macromedia saw with good eyes the ideas Netscape was putting forth in its ECMAScript 4 proposals document, and so began adopting many of them for their own language. At the same time, they knew it was in their best interest to not stray too far away from the general community of JavaScript developers, so they made a good effort to first become compliant with the ECMAScript 3 standard. It could only do them good: ECMAScript 4 was slated as the improvement JavaScript needed for bigger programs, and their community would certainly make use of that. Also, by leading the charge, they could have more leverage in the committee to push forward features that worked, or even new ideas. It was a sound plan.</p> <p>Although interest in ECMAScript 4 eventually dwindled inside the committee, by 2003 Macromedia was ready to release its new version of ActionScript as part of Flash 7. ActionScript 2.0 brought compile-time type checks and classes, two slated features found in the ECMAScript 4 drafts, and improved compliance with ECMAScript 3.</p> <h2>The Years of Silence</h2> <p>TC-39 and ECMA were active between 1999 and 2003. Horwat's (Netscape) latest draft document is dated August 11, 2000. Macromedia and Microsoft continued independently based largely on this draft document, but no interoperability tests were performed at this stage. By 2003, work by the committee had all but stopped. This meant there was no real push for a new release of the ECMAScript standard. Although Macromedia was about to release ActionScript 2.0 in 2003 and Microsoft's .NET platform was flourishing, ECMAScript 4 was not moving forward.</p> <p>It is important to note that at this stage, the drafts published by Horwat (Netscape) were not exhaustive enough to ensure compatibility between implementations. In other words, although ActionScript and JScript .NET were loosely based on the same drafts, they were not really compatible. Worse, code was already being developed using these implementations; code that could potentially become incompatible with the standard in the future. In a sense, this was not seen as a big problem, as ActionScript and JScript .NET were mostly isolated in their own platforms. Browser engines, for their part, had not advanced as much. Some extensions implemented by the big browsers, Internet Explorer and Netscape, were in use, but nothing big enough.</p> <p>Two long years passed between when work halted in 2003 until it was resumed. In between several significant events took place:</p> <ul> <li>Internet Explorer, the free browser bundled with Windows by Microsoft, succeeded in crushing Netscape out of the browser market.</li> <li>Firefox was released by Mozilla in 2004.</li> <li>A new standard integrating XML processing into JavaScript was released in 2004: ECMAScript for XML (E4X, ECMA-357). It gained little traction outside certain browser implementations.</li> <li>Macromedia was acquired by Adobe in 2005.</li> </ul> <p>Although it may seem these events are not related, they all played a part in the reactivation of TC-39.</p> <h2>TC-39 Comes Back to Life</h2> <p>The success of Internet Explorer on the desktop, due in great part to its bundling with Windows, forced Netscape's hand. In 1998, they released Netscape Communicator's source code and started the Mozilla project. By 2003, Microsoft had the majority of the browser market share and AOL, then owner of Netscape, announced major layoffs. The Mozilla project was to be spun off as an independent entity: the Mozilla Foundation. Mozilla would continue the development of Gecko (Netscape Navigators's layout engine) and SpiderMonkey. Soon, the Mozilla Foundation would shift its focus to the development of Firefox, a standalone browser without the bloat of the whole suite of applications that came bundled since Netscape's days. In an unexpected turn of events, Firefox's marketshare commenced to grow.</p> <p>Microsoft, by the time Firefox was released, had mostly stagnated with regards to web development. Internet Explorer was the king, and .NET was making big inroads in the server market. JScript .NET, getting little traction and developer interest, was left mostly unchanged. In other words, Microsoft had no particular interest at this point in reviving ECMAScript: they controlled the browser, and JScript .NET was an afterthought. It would require some prodding to wake them up.</p> <p>Macromedia, and then Adobe after its acquisition, started a push toward integration of their internal ActionScript work into ECMA in 2003. They had spent a considerable amount of technical effort on ActionScript, and it would only be in their best interest to see that work integrated into ECMAScript. They had the users, the implementation, and the experience to use as leverage inside the committee.</p> <p>At this point, Brendan Eich, now part of Mozilla, was concerned about Microsoft's stagnation with regards to web technologies. He knew web development was based on consensus, and, at the moment, the biggest player was Microsoft. He needed their involvement if things were to move forward. Taking notice of Macromedia's renewed interest in restarting the work on ECMAScript 4, he realized now was a good time to get the ball rolling.</p> <p>At the same time, there was interest in the community in standardizing a set of extensions to ECMAScript 3 meant to make it easier to manipulate XML data. A prototype of this had been developed by BEA Systems in 2002 and integrated into Mozilla Rhino, an alternative JavaScript engine written in Java. BEA Systems took their extension to ECMA; thus, ECMAScript for XML (E4X, ECMA-357) was born in 2004.</p> <p>As E4X was an ECMA standard concerning ECMAScript, it was a good way to get the key players from TC-39 working back together. Eich used this opportunity to jump-start ECMAScript development again by pushing for a second E4X release in 2005. By the end of 2005, TC-39 was back at work on ECMAScript 4.</p> <blockquote><p>Although E4X was unrelated to the ECMAScript 4 proposal, it brought important ideas that would end up being used: namely namespaces and the <code>::</code> operator.</p></blockquote> <p>Macromedia, now Adobe, took the work of TC-39 as a clear indication ActionScript was a safe bet. As work progressed, Adobe continued internal development of ActionScript at a fast pace, implementing many of the ideas discussed by the committee in short time. In 2006, Flash 9 was released, and with it ActionScript 3 was also out the door. The list of features integrated in it was <em>extensive</em>. On top of ActionScript 2 classes were added: optional typing, byte arrays, maps, compile time <em>and</em> runtime type checking, packages, namespaces, regular expressions, events, E4X, proxies, and iterators.</p> <p>Adobe decided to take one more step to make sure things moved forward. In November 2006, Tamarin, Adobe's in-house ActionScript 3.0 engine (used in Flash 9), was <a href="https://blog.mozilla.org/press/2006/11/adobe-and-mozilla-foundation-to-open-source-flash-player-scripting-engine/">released as open source and donated to the Mozilla Foundation</a>. This was a clear indication that Adobe wanted ECMAScript to succeed and, if at all possible, to be as little different from ActionScript as possible.</p> <blockquote><p>A colorful fact of history is that Macromedia <a href="https://twitter.com/BrendanEich/status/834124316476219392">wanted to integrate Sun's J2ME JVM into Flash</a> for ActionScript 3. The internal name for this project was "Maelstrom." For <a href="https://twitter.com/BrendanEich/status/834149931405283328">legal and strategic reasons</a> this plan never came to fruition and Tamarin was born instead.</p></blockquote> <h2>The Fallout</h2> <p>Work on ECMAScript was progressing and a <a href="http://www.ecmascript.org/es4/spec/overview.pdf">draft design document</a> with an outline of the expected features of ECMAScript 4 was released. The list of features had become quite long. By 2007, TC-39 was composed of more players than at the beginning. Of particular importance were newcomers Yahoo and Opera.</p> <p>Microsoft, for their own part, <a href="https://blogs.msdn.microsoft.com/cwilso/2007/10/31/what-i-think-about-es4/">were not sold on the idea of ECMAScript 4</a>. Allen Wirfs-Brock, Microsoft's representative at TC-39, viewed the language as <a href="https://blogs.msdn.microsoft.com/jscript/2008/08/20/ecmascript-3-and-beyond-the-road-to-harmony/">too complex for its own good</a>. His reasons were strictly technical, though internally, Microsoft also had strategic concerns. Internal discussions at Microsoft eventually converged on a the idea that ECMAScript 4 should take a different course.</p> <p>Another member of the committee, Douglas Crockford from Yahoo, also had his concerns about ECMAScript 4, although perhaps for different technical reasons. However, he had not been too vocal about them. Wirfs-Brock realized this and convinced Crockford it would be a good idea to voice his concerns. This created an impasse in the committee, which was now not in consensus. In Crockford's words:</p> <blockquote><p>Some of the people at Microsoft wanted to play hardball on this thing, they wanted to start setting up paper trails, beginning grievance procedures, wanting to do these extra legal things. I didn't want any part of that. My disagreement with ES4 was strictly technical and I wanted to keep it strictly technical; I didn't want to make it nastier than it had to be. I just wanted to try to figure out what the right thing to do was, so I managed to moderate it a little bit. But Microsoft still took an extreme position, saying that they refused to accept any part of ES4. So the thing got polarized, but I think it was polarized as a consequence of the ES4 team refusing to consider any other opinions. At that moment the committee was not in consensus, which was a bad thing because a standards group needs to be in consensus. A standard should not be controversial. - <strong><a href="https://developer.yahoo.com/yui/theater/video.php?v=crockford-yuiconf2009-state">Douglas Crockford — The State and Future of JavaScript</a></strong></p></blockquote> <p>Wirfs-Brock put forth the idea of <a href="http://wiki.ecmascript.org/lib/exe/fetch.php?id=es3.1%3Aes3.1&amp;cache=cache&amp;media=proposals:proposal_to_refocus_tc39-tg1.pdf">somehow meeting at the middle</a>. The committee decided to split into two work teams: one focused on finding a subset of ECMAScript 4 that was still useful but much easier to implement, and another team focused on moving forward with ECMAScript 4. Wirfs-Brock became the editor of the smaller, more focused standard, tentatively called ECMAScript 3.1. It is important to note that members from both teams worked in both groups, so they were not really separate in this sense.</p> <p>As time passed, it became clear ECMAScript 4 was too big for its own weight. The group did not advance as much as they had hoped, and by 2008 many problems still had to be solved before a new standard could be drafted. The ECMAScript 3.1 team, however, had made considerable progress.</p> <h2>ECMAScript 4 is Dead, Long Live ECMAScript!</h2> <p>A meeting in Oslo, Norway, had been planned for the committee to establish a way forward. Before this meeting took place, Adobe, off the record, had made it clear they were planning to withdraw from ECMAScript 4 development, joining Microsoft and Yahoo in their stance. This was perhaps the result of seeing ECMAScript 4 become too different from ActionScript 3.</p> <p>The <a href="https://mail.mozilla.org/pipermail/es-discuss/2008-August/003400.html">iconic meeting took place in 2008</a>. In it, the committee made the hard decision: ECMAScript 4 was dead. A new version of ECMAScript was to be expected, and a change in direction for future work was drafted. Brendan Eich broke the official news in an iconic email. The conclusions of this meeting were to:</p> <ol> <li>Focus work on ES3.1 with full collaboration from all parties, and target two interoperable implementations by early next year.</li> <li>Collaborate on the next step beyond ES3.1, which will include syntactic extensions but which will be more modest than ES4 in both semantic and syntactic innovation.</li> <li>Some ES4 proposals have been deemed unsound for the Web, and are off the table for good: packages, namespaces and early binding. This conclusion is key to Harmony.</li> <li>Other goals and ideas from ES4 are being rephrased to keep consensus in the committee; these include a notion of classes based on existing ES3 concepts combined with proposed ES3.1 extensions.</li> </ol> <p>ECMAScript 3.1 was soon renamed to ECMAScript 5 to make it clear it was the way forward and that version 4 was not to be expected. Version 5 was finally released in 2009. All major browsers (including Internet Explorer) were fully compliant by 2012.</p> <p>Of particular interest is the word "harmony" in Eich's e-mail. "Harmony" was the designated name for the new ECMAScript development process, to be adopted from ECMAScript 6 (later renamed 2015) onwards. Harmony would make it possible to develop complex features without falling into the same traps ECMAScript 4 experienced. Some of the ideas in ECMAScript 4 were recycled in Harmony. ECMAScript 6/2015 finally brought many of the big ideas from ECMAScript 4 to ECMAScript. Others were completely scrapped.</p> <h3>Wait, What Happened to ActionScript (and JScript .NET)?</h3> <p>Unfortunately for Adobe, the death of ECMAScript 4 and their decision to stop supporting it meant the large body of work they had performed to keep in sync with the ECMAScript 4 proposal was, at least in part, useless. Of course, they had a useful, powerful, and tested language in the form of ActionScript 3. The community of developers was quite strong as well. However, it is hard to argue against the idea that they bet on ECMAScript 4's success and lost. Tamarin, which was open-sourced to help adoption and progress of the new standard, was largely ignored by browsers. Mozilla initially attempted to merge it with SpiderMonkey, but they later realized performance suffered considerably for certain important use cases. Work was needed, and ECMAScript 4 was not complete, so it never got merged. Microsoft continued improving JScript. Opera and Google worked on their own clean-room implementations.</p> <p>An interesting take on the matter was exposed by Mike Chambers, an Adobe employee:</p> <blockquote><p>ActionScript 3 is not going away, and we are not removing anything from it based on the recent decisions. We will continue to track the ECMAScript specifications, but as we always have, we will innovate and push the Web forward when possible (just as we have done in the past). - <strong><a href="http://www.mikechambers.com/blog/2008/08/14/actionscript-3-and-ecmascript-4/">Mike Chambers' blog</a></strong></p></blockquote> <p>It was the hope of ActionScript developers that <a href="http://blogs.adobe.com/open/standards_ecmascript_and_repre/">innovation in ActionScript would drive features in ECMAScript</a>. Unfortunately, this was never the case, and what later came to ECMAScript 2015 was in many ways incompatible with ActionScript.</p> <p>JScript .NET, on the other hand, had been largely left untouched since the early 2000s. Microsoft had long realized developer uptake was just too low. It went into maintenance mode in .NET 2.0 (2005) and remains available only as a legacy product inside the latest versions of .NET. It does not support features added to .NET after version 1 (such as generics, delegates, etc.).</p> <h2>An ECMAScript timeline</h2> <p><img src="https://cdn.auth0.com/blog/es4/timeline2.png" alt="ECMAScript history timeline" /></p> <h2>Aside: JavaScript use at Auth0</h2> <p>At Auth0 we are <a href="https://github.com/auth0">heavy users of JavaScript</a>. From our <a href="https://github.com/auth0/lock">Lock library</a> to our back end, JavaScript powers the core of our operations. We find its asynchronous nature and the low entry barrier for new developers essential to our success. We are eager to see where the language is headed and the impact it will have in its ecosystem.</p> <p><a href="javascript:signup()">Sign up for a free Auth0 account</a> and take a firsthand look at a production-ready ecosystem written in JavaScript. And don't worry, we have <a href="https://auth0.com/docs/quickstarts">client libraries for all popular frameworks and platforms</a>!</p> <h2>Conclusion</h2> <p>JavaScript has a bumpy history. The era of ECMAScript 4 development (1999-2008) is of particular value to language designers and technical committees. It serves as a clear example of how aiming for a release too big for its own weight can result in development hell and stagnation. It is also a stark reminder that even when you have an implementation and are at the forefront of development, things can go in a completely different direction (Adobe, Microsoft). Being cutting-edge is always a bet. On the other hand, the new process established by the Harmony proposal has started to show progress, and where ECMAScript 4 failed in the past, the newer ECMAScript has succeeded. Progress cannot be stopped when it comes to the Web. Exciting years are ahead, and they cannot come soon enough.</p> What Cloudbleed Means for You and Your Customers 2017-02-28T08:30:00+00:00 https://auth0.com/blog/what-cloudbleed-means-for-you-and-your-customers/ Diego Poza https://twitter.com/diegopoza <p>On February 17th, Tavis Ormandy, a vulnerabilities researcher at Google, sent the tweet that kicked off 2017's biggest security story yet:</p> <p><img src="https://cdn.auth0.com/blog/cloudbleed-post/tweet.png" alt="Tweet" /></p> <p><em>Could someone from cloudflare security urgently contact me.</em> That's not something anyone wants to read on a Friday afternoon, but especially not when it's coming from one of the world's top infosec researchers.</p> <p>The problem? While doing some routine bug checking, <a href="https://twitter.com/taviso?lang=en">Ormandy</a> saw some data that did not match at all what he expected to find.</p> <p>"It's not unusual to find garbage, corrupt data, mislabeled data or just crazy non-conforming data...but the format of the data this time was confusing enough that I spent some time trying to debug what had gone wrong, wondering if it was a bug in my code," <a href="https://bugs.chromium.org/p/project-zero/issues/detail?id=1139">he wrote</a>, "In fact, the data was bizarre enough that some colleagues around the Project Zero office even got intrigued."</p> <p>The rest of the Google Project Zero team (a team of security researchers employed specifically to find new <a href="https://en.wikipedia.org/wiki/Project_Zero_(Google">zero-day exploits</a>)) probably expected Google's announcement of the first <a href="https://auth0.com/blog/sha-1-collision-attack/">practical SHA-1 collision</a> to be the big news of the week.</p> <p>As they looked closer, they found “encryption keys, cookies, passwords, chunks of POST data and even HTTPS requests” for all sorts of different sites using Cloudflare—private messages, reservations, plaintext API requests from a password manager, hotel bookings.</p> <p>How did all of this happen?</p> <h2>Cloudflare was dumping memory across the web</h2> <p>It begins with a simple bug in the code to Cloudflare's highly popular reverse proxy service. HTTP requests to certain types of sites signed up with Cloudflare would trigger the bug, which would then "leak" data from random<em> </em>Cloudflare customers' sites (those that happened to be in memory at the time).</p> <p><img src="https://cdn.auth0.com/blog/cloudbleed-post/cloudflare.png" alt="Cloudflare" /></p> <p><em>A simple depiction of how a reverse proxy like Cloudflare's works. Since reverse proxies are shared between customers, data from all was at risk of being disclosed.</em></p> <p>Since September, random bits of data have been coming out of initialized memory and leaking across random Cloudflare customer's sites. In other words, if you went to visit a site that used Cloudflare, you could have had other people's sensitive information “leaking” into your own browsing session.</p> <p> When search engines “crawled” these pages to index them, the same kind of information “leaked.” Because search engines cache the output they receive when they visit a page, all these leaked tokens, secrets, and messages were indexed, split up and spread across <em>millions </em>of pages of search results.</p> <p><img src="https://cdn.auth0.com/blog/cloudbleed-post/SERPs.png" alt="Search Results" /></p> <p>(Source: <a href="https://www.wordfence.com/blog/2017/02/cloudflare-data-leak/">Wordfence</a>)</p> <p>While Cloudflare is working with the major search engines to purge their caches of sensitive information now, it's hard to avoid thinking about the paranoid version of events.</p> <p>Paranoid version: state actors, or state-sponsored actors with significant resources, discovered this vulnerability before Google did. They found a way to send manipulated HTTP requests to Cloudflare sites that would output a predictable stream of user data—and have either packaged everything they found for resale or set about figuring out how to crack what could be billions of passwords, credit card numbers, and secret tokens.</p> <p>Cloudflare claims they can rule out this scenario with access logs, but whether or not that's true has been subject to <a href="https://news.ycombinator.com/item?id=13721452">some debate</a>.</p> <h2>What you should do now</h2> <p>The way that data was disclosed means that any site using Cloudflare could potentially have had its secrets and tokens compromised. Patreon, Yelp, Uber, Medium, Fitbit, and OKCupid all use Cloudflare—for a full list of sites you can <a href="https://github.com/pirate/sites-using-cloudflare">click here</a>. Several tools have also been <a href="http://www.doesitusecloudflare.com/">built to assess your risk</a>, like this script that <a href="https://gist.github.com/kamaljoshi/2cce5f6d35cd28de8f6dbb27d586f064">crawls your Chrome history</a>.</p> <p>Though many, many sites use Cloudflare, at least to some degree. It's still quite unlikely that your personal information has been exposed. Many of the individual sites mentioned have also come out and written posts to explain whether you should be concerned—perhaps most notably, 1Password, which was initially mentioned in Tavis's tweets as a <a href="https://blog.agilebits.com/2017/02/23/three-layers-of-encryption-keeps-you-safe-when-ssltls-fails/">potentially compromised site</a>.</p> <p>The first thing you want to do to protect yourself from this and future incidents is to enable <a href="https://auth0.com/multifactor-authentication">multifactor authentication</a>. The most important sites to enable MFA on are the ones you use as an SSO iDP—if you're logging into 20 different sites using your Google credentials, then you definitely want to enable some form of MFA there.</p> <p>While it's unlikely your passwords were exposed, this is as good a reminder as any that you should be using strong, unique passwords and organizing them using a password manager.</p> <p>Resetting individual passwords for sites doesn't make much sense—the list of compromised sites is simply so vast. The only solution is to do a mass reset and make sure you're using proper password hygiene going forward.</p> <h2>What you should do for your customers</h2> <p>As a site operator, you're probably wondering 1) if you're at risk, and 2) if any of your users' data was exposed in this incident.</p> <p>Cloudflare has already reached out to domain owners that they have proactively identified as being at risk in this leak. However, the absence of notification does not mean that your domain (and customers) are safe.</p> <p>First off, enable multifactor authentication <a href="https://auth0.com/multifactor-authentication">if you haven't already</a>. It's the easiest way to get a huge boost to the security of your site.</p> <p>Many site operators have begun forcing password resets for all of their users. If you run a consumer site, it may not be worth the trouble and inconvenience. If your customers are in the enterprise, then it is probably a very good idea to force a change. If you're not going to make your users change their passwords (and from a cursory browse of the web this Monday morning, it appears that this is mostly the case), then you should at least recommend it.</p> <p>As far as data invalidation, any secrets which you can easily rotate—session identifiers, tokens, keys—should immediately be changed. Customer SSL keys do not appear to have been compromised in this incident, but it would be prudent to change as much data as you can which may have passed through Cloudflare.</p> <p>If you or any of your customers are regulated by the Health Insurance Portability and Accountability Act (HIPAA), then you'll <a href="https://www.aptible.com/blog/aptible-was-not-affected-by-cloudbleed/">definitely want</a> to have your security/compliance teams get in touch with your lawyers and discuss whether this is a breach that needs to be reported.</p> Houghton Mifflin Harcourt Chooses Auth0 to Consolidate Identity 2017-02-27T08:30:00+00:00 https://auth0.com/blog/houghton-mifflin-harcourt-chooses-auth0-for-identity-management/ Martin Gontovnikas http://twitter.com/mgonto <p><strong>BELLEVUE, WA</strong> - <a href="http://www.hmhco.com/">Houghton Mifflin Harcourt</a> (HMH), a global learning company specializing in pre-K-12 education content and services, has chosen Auth0 as their identity management platform for their new educational portal. The new portal allows school districts across the United States and the world to access content and technology through a unified experience.</p> <p><img src="https://cdn.auth0.com/blog/houghton-mifflin-harcourt-pr/website.png" alt="Houghton Mifflin Harcourt Website" /></p> <p>Being a global organization with many unique technologies, data stores, and customers to serve, HMH needed a solution that would allow them to consolidate everything through a single unified experience while allowing existing customers to access this new platform through their existing identity. Auth0 stepped up to challenge and delivered a solution that did just that. Existing customers could log in with their established identities while new customers and users could easily be onboarded.</p> <p>Performance was a key consideration for HMH. The company has to deal with large changing user sets and enrollment data, especially right before the school year begins. Auth0 was able to demonstrate exceptional performance with their bulk loader for managing large data sets as well as the platforms capability to handle over 1 billion authentication transactions per day.</p> <h3>About Auth0</h3> <p>Auth0 provides frictionless authentication and authorization for developers. The company makes it easy for developers to implement even the most complex identity solutions for their web, mobile, and internal applications. Ultimately, Auth0 allows developers to control how a person’s identity is used with the goal of making the internet safer. As of August, 2016, Auth0 has raised over $24m from Trinity Ventures, Bessemer Venture Partners, K9 Ventures, Silicon Valley Bank, Founders Co-Op, Portland Seed Fund and NXTP Labs, and the company is further financially backed with a credit line from Silicon Valley Bank.</p> <p>For more information visit <a href="https://auth0.com">https://auth0.com</a> or follow <a href="https://twitter.com/auth0">@auth0</a> on Twitter.</p> SHA-1 Has Been Compromised In Practice 2017-02-24T08:30:00+00:00 https://auth0.com/blog/sha-1-collision-attack/ Ado Kukic https://twitter.com/kukicado <hr /> <p><strong>TL;DR</strong> Researchers published a technique for causing SHA-1 collisions and demonstrated it by providing two unique PDF documents that produced the same SHA1 hash value.</p> <hr /> <p><a href="https://en.wikipedia.org/wiki/SHA-1">Secure Hash Algorithm 1</a> or SHA-1 is a cryptographic hash function designed by the United States <a href="https://www.nsa.gov/">National Security Agency</a> and released in 1995. The algorithm was widely adopted in the industry for digital signatures and data integrity purposes. For example, applications would use SHA-1 to convert plain-text passwords into a hash that would be useless to a hacker, unless of course, the hacker could reverse engineer the hash back into the original password, which they could not. As for data integrity, a SHA-1 hash ensured that no two files would have the same hash, and even the slightest change in a file would result in a new, completely unique hash.</p> <p>According to <a href="https://en.wikipedia.org/wiki/Cryptographic_hash_function">Wikipedia</a>, the ideal cryptographic hash function has five main properties:</p> <ul> <li>It is deterministic so the same message always results in the same hash.</li> <li>It is quick to compute the hash value for any given message.</li> <li>It is infeasible to generate a message from its hash value except by trying all possible messages.</li> <li>A small change to a message should change the hash value so extensively that the new hash value appears uncorrelated with the old hash value.</li> <li><strong>It is infeasible to find two different messages with the same hash value.</strong></li> </ul> <p>In 2005, researchers discovered potential <a href="http://www.darkreading.com/vulnerabilities---threats/researchers-warn-against-continuing-use-of-sha-1-crypto-standard/d/d-id/1322565">vulnerabilities</a> in the SHA-1 algorithm and by 2010 many organizations stopped it as it was deemed <a href="https://www.entrust.com/understanding-sha-1-vulnerabilities-ssl-longer-secure/">insecure</a>. The potential vulnerabilities had not been proven, until today, when CWI Institute and Google demonstrated a practical collision attack against SHA-1. The researchers were able to provide two unique PDF files that produced the same exact SHA-1 hash value.</p> <p><img src="https://cdn.auth0.com/blog/sha1-collision/example.png" alt="Data Integrity" /></p> <p><small>Source: <a href="http://shattered.io/static/infographic.pdf" target="_blank">shattered.io</a></small></p> <p>The team published a practical technique showing how to generate a collision bringing the fears that SHA-1 was insecure to reality. The technique outlined required years of research and immense computation resources. From the research published, it would take a cluster of 110 powerful GPU’s running computations 24 hours a day for an entire year to cause a collision, or about 6,500 years on a single-CPU. So while this attack vector is fairly impractical, it is not impossible.</p> <blockquote class="tweet-quote"> <a href="https://twitter.com/intent/tweet?text=&quot;The SHA1 collision attack required 9,223,372,036,854,775,808 SHA1 computations.&quot; via @auth0 http://auth0.com/blog/sha-1-collision-attack/"> <p>"The SHA1 collision attack required 9,223,372,036,854,775,808 SHA1 computations."</p> <p class="tweet-link">TWEET THIS <img src="https://cdn.auth0.com/blog/resources/twitter.svg"></p> </a> </blockquote> <script> $(function() { $('.tweet-quote').on('click', function() { metricsLib.track('blog:share:twitter_quote'); }); }); </script> <p>This is a big deal because even though many organization have stopped using SHA-1, underlying systems still often rely on SHA-1. Software updates, ISO checksums, PGP signatures, digital certificate signatures, git, and others still make use of SHA-1 for data integrity. If a malicious party were able to create a collision for a popular piece of software for example, and distributed it on the web, they could infect many unsuspecting users causing all sorts of damage.</p> <p>On the bright side, the typical user does not have to worry too much. Certification Authorities are forbidden from issuing SHA-1 certificates, and Google and Mozilla will warn users accessing HTTPS websites that use SHA-1 signed certificates. More and more organizations are using safer alternatives like SHA-256 for their cryptographic needs. Additionally, since the published attack vector has only been proven with PDF files, the team created a website, <a href="https://shattered.io">shattered.io</a>, which allows you to test your PDF files and see if they could have been compromised.</p> <p>For most, security is not actively thought about, but for us at <a href="https://auth0.com">Auth0</a>, security is the only thing we think about. Ok, not the only thing, but it’s up there. In addition to embracing open authentication standards like <a href="https://oauth.net/2/">OAuth</a> and <a href="http://openid.net/">OpenID</a>, we follow industry standards and best practices for security and when this popped up on our radar we just had to share it. Learn more about our security practices <a href="https://auth0.com/security">here</a>.</p> <p>For more info on the SHA-1 collision attack be sure to check out <a href="http://shattered.io/">shattered.io</a> and Google’s Security Blog <a href="https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html">post</a>. If you are using SHA-1, please switch to a more secure hasing algorithm like <a href="https://en.wikipedia.org/wiki/SHA-2">SHA-256</a>.</p> Auth0 is OpenID Connect Certified 2017-02-23T10:00:00+00:00 https://auth0.com/blog/we-are-now-open-id-certified/ Martin Gontovnikas http://twitter.com/mgonto <p>In May of last year, Auth0 officially gained certifications for <em>OP Basic</em> and <em>OP Config</em> profiles of the OpenID Connect spec. As of February this year, Auth0 has gained two new <a href="http://oixnet.org/openid-certifications/auth0/">OpenID Connect certifications: <em>OP Implicit</em> and <em>Hybrid OP</em></a>. With these certifications we're thrilled to join the ranks of industry leaders such as Google, Microsoft, PayPal, and others who are embracing standards based authentication.</p> <p>OpenID Connect, as a layer on top of the OAuth 2.0 authorization protocol, allows for decentralized authentication and improves user access to websites and apps.</p> <p>Getting certified means ensuring that our implementation of the protocol meets the official specifications as outlined by <a href="http://openid.net/developers/specs/">OpenID</a>.</p> <p>OpenID is a cornerstone of the modern, open web, and we're proud that our implementation has the official stamp of approval.</p> <h2>What Is OpenID Connect?</h2> <p>OpenID Connect is an open identity standard. It acts as an authentication layer (proving who you are) on top of the OAuth 2.0 authorization standard (granting you access).</p> <p>A user gets an OpenID account through an OpenID identity provider. The user uses that account to sign into any site (a relying party) that accepts OpenID authentication (for example, YouTube). This open-source framework, provided by the OpenID standard, lets the user, relying party and the identity provider “just work” together.</p> <p>Instead of having to sign up on a website and keep track of your passwords, you only need to sign up once and use that login across various applications.</p> <p>On a website, it might look something like this:</p> <p><img src="https://cdn.auth0.com/blog/open-id-certified/sign-in-form.png" alt="login" /></p> <p>A user is already logged into Facebook or Google (an identity provider) with a set of credentials. This set of credentials can then be used to log into another website or application, a relying party. This site or app will ask the user "Sign up with Facebook or Google?"</p> <p>When a user clicks on Google or Facebook, they're authorizing that identity provider to back up their claim. Then the user is redirected to the website or application.</p> <p><img src="https://cdn.auth0.com/blog/open-id-certified/social-provider-authorization.png" alt="authorization" /></p> <p>This use of linked identities means you only have to manage a single username and password for websites.</p> <p>With OpenID, users don't need traditional authentication tokens like a username and password. All they need is to be registered on a site with an OpenID identity provider. It's decentralized; any website can use OpenID as a way to log users in.</p> <h2>Why is OpenID Connect Important?</h2> <p>Before OpenID, people built site-specific networks with their own signup and login systems. The idea that you could select your own identity provider for logging into a website and a common standard that would connect all these systems didn't exist. Some big players, like Facebook, had built their own solutions for SSO. But the decentralized OpenID model was so powerful and beneficial that even they eventually adopted it. Like VentureBeat's Eric Eldon <a href="http://venturebeat.com/2009/04/14/single-sign-on-service-openid-getting-more-usage/">wrote</a> upon its release,</p> <blockquote><p><em>The point of OpenID, as all of these companies seem to accept, is that users don’t want to use just any one service to sign in everywhere. Instead, users should have the choice to log into any site using any other identity. Making it easier for people to log in anywhere just means more people will log in overall — and potentially become users of any of these companies.</em></p></blockquote> <p>Think of OpenID as your driver's license for the entire internet.</p> <p>Websites that use OpenID won't ask for your information constantly, making it faster and easier to sign up. Plus, you can associate information with your OpenID such as your name and email address, and decide how much websites get to know about you. So, websites that use OpenID won't bug you for the same information every single time you sign up.</p> <p>Since you're uniquely identified over the internet, OpenID Connect is also a good way connect your accounts into a more unified persona. The moment you establish yourself as the individual who uses a specific OpenID, whenever someone sees you're using your OpenID online, they'll know it's you.</p> <p>If your friend opens a website and sees someone with your OpenID has made a comment, they can be certain it was you, not someone with the same name coincidentally.</p> <h2>Why Get OpenID Certification?</h2> <p>You've carried rounds and rounds of tests to check your OpenID specs. The results were great with strong participation. So what's the point of getting certified?</p> <p>Certification ensures credibility. In your own testing, you can pick and choose what aspects of your OpenID implementation you want to test. Certification involves meeting a set of minimum criteria that are standard across the board, and your results (and the process you used to get there) are open for public oversight.</p> <p>When you're done, you can prove that your <a href="https://auth0.com/learn/how-auth0-uses-identity-industry-standards/">OpenID implementation</a> is conformant with the <a href="http://openid.net/certification/">official specs</a> — not just for your customers and potential customers, but for yourself.</p> Serverless REST API with Angular, Persistence and Security 2017-02-22T08:30:00+00:00 https://auth0.com/blog/serverless-angular-app-with-persistence-and-security/ Bruno Krebs https://twitter.com/brunoskrebs <p><strong>TL;DR</strong></p> <p>Using the right tools, you can create an application from scratch and release it to production very quickly. In this post, I will show you how to develop a task list application, with Angular, that consumes a serverless REST API and persists data to a MongoDB database hosted by mLab. This application will also focus on security, with Auth0, and will be deployed to GitHub Pages.</p> <h2>Overview</h2> <p>In this post I will show you that, with the right tools, it is possible to start a <strong>full stack</strong> app—task list application in this case—from scratch, and release it to production in a short time. Our full stack app will support static file hosting, a secure REST API, and a robust persistence layer. This is how we will manage all the moving parts:</p> <ul> <li><strong>Identity management and security</strong> supported by <a href="https://auth0.com">Auth0</a> and JSON Web Tokens (JWT)</li> <li><strong>Serverless REST API</strong> provided by an <a href="https://expressjs.com/">Express</a> app with <a href="https://webtask.io">Webtask</a></li> <li><strong>Persistence layer</strong> with a <a href="https://www.mongodb.com/">MongoDB database</a> hosted by <a href="https://mlab.com/">mLab</a></li> <li><strong>Static file hosting</strong> via deployment to <a href="https://pages.github.com/">GitHub Pages</a></li> </ul> <p>Since the app that we are going to develop is quite simple in terms of features, it won't be necessary to have MongoDB running on our local environment. We will use mLab during development as well as production. The only tools that are expected to be installed are <a href="https://docs.npmjs.com/getting-started/installing-node">NodeJS and NPM</a>.</p> <p>Our application will have the following features:</p> <ul> <li>Sign in and sign out</li> <li>List that shows tasks from a user</li> <li>Form that allows users to add new tasks</li> <li>A button for each task, to enable users to remove these tasks</li> </ul> <h2>Creating a New Angular App</h2> <p>We are going to create our new Angular app with <a href="https://github.com/angular/angular-cli">Angular CLI</a>. Actually, we will be using this tool during the whole process to create components/services and build our app for production.</p> <p>Here is a list of a few commands that we will have to issue to install Angular CLI and to create our app skeleton:</p> <pre><code class="bash"># install Angular CLI globally npm install -g @angular/cli # create skeleton ng new task-list &amp;&amp; cd task-list # serve the skeleton on our dev env ng serve </code></pre> <p>The last command is responsible for packaging our application with the development profile, and for serving it locally with <a href="https://webpack.github.io/docs/webpack-dev-server.html">Webpack Development Server</a>. After executing all these commands, navigate to <code>http://localhost:4200/</code> to see it up and running.</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/ng-cli-skeleton.png" alt="Angular app skeleton up and running." /></p> <h2>Securing Angular with Auth0</h2> <p>The first thing that we are going to take care of in our application is security. Security must be a first priority in any application that handles sensitive, third party data like the task list that we are about to develop.</p> <p>To start, <a href="javascript:signup()">sign up for a free Auth0 account</a> and take note of <code>Client ID</code> and <code>Domain</code>. Both values are going to be used to configure <a href="https://auth0.com/docs/libraries/lock">Lock</a>: an embeddable login system.</p> <p><strong>Important</strong>: Auth0 requires a list of <em>Allowed Callback URLs</em>. This list contains all the URLs to which Auth0 can redirect a user to after issuing a JWT. Therefore we must configure at least two URLs: <code>http://localhost:4200/</code> and the URL where our app will be exposed, something like: <code>https://brunokrebs.github.io/task-list/</code>. This URL will be defined when we release to GitHub Pages.</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/auth0-client-config.png" alt="Auth0 client settings." /></p> <p>To use Lock, we must install two libraries in our application: <code>auth0-lock</code> and <code>angular2-jwt</code>. Since we are using TypeScript with Angular, we will also install the <code>@types/auth0-lock</code> library, which provides TypeScript definitions for Lock. Also, since we want to provide our users a good looking interface, we are going to install <a href="https://github.com/angular/material2">Angular Material</a>. These dependencies are installed with the following commands:</p> <pre><code class="bash"># Auth0 Lock and Angular 2 JWT runtime deps npm install --save auth0-lock angular2-jwt @angular/material # Types definitions for Auth0 Lock npm install --save-dev @types/auth0-lock </code></pre> <p>Let's use Angular CLI to create a <code>NavBarComponent</code>. This component will have <em>Sign in</em> and <em>Sign out</em> buttons. We will also create a <code>AuthService</code> that will be responsible for <code>sign in</code>, <code>sign out</code> and to validate if the user is <code>authenticated</code> or not.</p> <pre><code class="bash"># generates NavBarComponent files under src/app/nav-bar ng g component nav-bar # generates AuthService under src/app/auth.service.ts ng g service auth </code></pre> <p>After executing these commands, Angular CLI will have created the following file structure:</p> <pre><code>src |-app |-nav-bar |-nav-bar.component.ts |-nav-bar.component.html |-nav-bar.component.css] |-auth.service.ts </code></pre> <blockquote><p>Actually two extra files were created: <code>src/app/auth.service.spec.ts</code> and <code>src/app/nav-bar/nav-bar.component.spec.ts</code>. We would use these files to write tests for both the component and the service. However, for the sake of simplicity, we won't address testing in this post. You can check the following references to read about testing in Angular: <a href="https://auth0.com/blog/angular-2-testing-in-depth-services/">Angular 2 Testing In Depth: Services</a>; <a href="https://angular.io/docs/ts/latest/guide/testing.html">Angular Testing</a>; <a href="https://semaphoreci.com/community/tutorials/testing-components-in-angular-2-with-jasmine">Testing Components in Angular 2 with Jasmine</a></p></blockquote> <p>To integrate with Lock, let's first implement <code>src/app/auth.service.ts</code> with the following code:</p> <pre><code class="typescript">import { Injectable } from '@angular/core'; import Auth0Lock from 'auth0-lock'; import { tokenNotExpired } from 'angular2-jwt'; // FIXME: replace these with your own Auth0 'Client ID' and 'Domain' const AUTH0_CLIENT_ID = 'YOUR_AUTH0_CLIENT_ID'; const AUTH0_DOMAIN = 'YOUR_AUTH0_DOMAIN'; // this is the key to the JWT in the browser localStorage const ID_TOKEN = 'id_token'; @Injectable() export class AuthService { lock = new Auth0Lock(AUTH0_CLIENT_ID, AUTH0_DOMAIN, {}); constructor() { // listening to 'authenticated' events this.lock.on('authenticated', (authResult) =&gt; { localStorage.setItem(ID_TOKEN, authResult.idToken); }); } signIn() { this.lock.show(); } signOut() { localStorage.removeItem(ID_TOKEN); } authenticated() { return tokenNotExpired(); } } </code></pre> <p>In the code above, there are three things that worth mentioning. First, we must replace <code>AUTH0_CLIENT_ID</code> and <code>AUTH0_DOMAIN</code> with the values that we noted previously. Second, the <code>ID_TOKEN</code> references the key were the JWT will be saved (on the user's browser <code>localStorage</code>). And third, the constructor of this service adds a callback listener to the <code>authenticated</code> event on Lock. This callback saves the token issued by Auth0 in <code>localStorage</code>. To sign out a user, it is just a matter of removing this token from <code>localStorage</code>.</p> <p>Our <code>AuthService</code> class is good to go, but unlike <code>components</code>, Angular CLI does not add <code>services</code> to our <code>@NgModule</code> definition by default. To do this, open the <code>src/app/app.module.ts</code> file, add this <code>service</code> as a <code>provider</code> and add Angular Material in the <code>imports</code> array:</p> <pre><code class="typescript">// ... other imports import { AuthService } from './auth.service'; import { MaterialModule } from '@angular/material'; @NgModule({ // ... other properties imports: [ // ... other imports MaterialModule.forRoot(), ], providers: [ AuthService ], // ... other properties }) export class AppModule { } </code></pre> <p>We can now focus on implementing our <code>NavBarComponent</code>. First, we will inject <code>AuthService</code> and add three public methods that will be used by our HTML interface. Then we will implement the interface and add some CSS rules to improve it.</p> <p>Let's open the <code>src/app/nav-bar/nav-bar.component.ts</code> file and implement the following code:</p> <pre><code class="typescript">import { Component } from '@angular/core'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-nav-bar', templateUrl: './nav-bar.component.html', styleUrls: ['./nav-bar.component.css'] }) export class NavBarComponent { constructor(private authService: AuthService) { } } </code></pre> <p>This component simply gets <code>AuthService</code> injected and nothing else. Injecting a service like this allows the user interface to call its methods, as we will see. Now, let's open <code>src/app/nav-bar/nav-bar.component.html</code> and implement it as follows:</p> <pre><code class="html">&lt;md-toolbar color="primary"&gt; &lt;span&gt;Task List&lt;/span&gt; &lt;span class="fill-space"&gt;&lt;/span&gt; &lt;button md-button (click)="authService.signIn()" *ngIf="!authService.authenticated()"&gt;Sign In&lt;/button&gt; &lt;button md-button (click)="authService.signOut()" *ngIf="authService.authenticated()"&gt;Sign Out&lt;/button&gt; &lt;/md-toolbar&gt; </code></pre> <p>Our <code>NavBar</code> exposes our application's title along with two buttons. At any given time, only one button is truly visible to the user. The <em>Sign In</em> button is going to be visible when the user is not yet <code>authenticated</code> and the <em>Sign Out</em> will be visible otherwise. To make our interface look better, we have also added a <code>span.fill-space</code> element. This element will be responsible to push both buttons to the right border. To accomplish this, we need to add the CSS rule that follows to the <code>src/app/nav-bar/nav-bar.component.css</code> file:</p> <pre><code class="css">.fill-space { flex: 1 1 auto; } </code></pre> <p>Good, we now have both the <code>NavBarComponent</code> and the <code>AuthService</code> fully implemented and integrated. But we still need to add this component to our <code>src/app/app.component.html</code> file, otherwise it will never get rendered. To do this, just replace the content of this file with the following line of code: <code>&lt;app-nav-bar&gt;&lt;/app-nav-bar&gt;</code>.</p> <p>If we run our application now, it wouldn't look neat because most major browsers come with an <code>8px</code> margin on <code>body</code> elements and because we haven't configured any <a href="https://github.com/angular/material2/blob/master/guides/theming.md">Angular Material Theme</a>. We will fix both issues by updating our <code>src/styles.css</code> file to look like:</p> <pre><code class="css">@import '~@angular/material/core/theming/prebuilt/indigo-pink.css'; body { margin: 0; } </code></pre> <p>We are now good to go, so let's start our development server, by issuing <code>ng serve</code>, and head to <code>http://localhost:4200</code> to look how things are. You can even <em>sign in</em> and <em>sign out</em>, although there won't be much to see.</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/auth-lock-open-with-navbar.png" alt="Auth0 Lock running on Angular and Angular Material" /></p> <h3>Adding a Welcome Message to Visitors</h3> <p>To make our application a friendly place, let's add a welcoming message. To do that, first we will add two methods and inject <code>AuthService</code> in the <code>src/app/app.component.ts</code> file, making it look like this:</p> <pre><code class="typescript">import { Component } from '@angular/core'; import { AuthService } from './auth.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor(private authService: AuthService) { } } </code></pre> <p>After that we are going to add the message, as a <code>md-card</code> component from <a href="https://material.angular.io/components/component/card">Angular Material</a>, to <code>src/app/app.component.html</code>:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;app-nav-bar&gt;&lt;/app-nav-bar&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;app-container&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;md-card</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;!authService.authenticated()&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;md-card-title&gt;</span>Hello, visitor.<span class="nt">&lt;/md-card-title&gt;</span> <span class="nt">&lt;md-card-subtitle&gt;</span> Please <span class="nt">&lt;a</span> <span class="err">(</span><span class="na">click</span><span class="err">)=&quot;</span><span class="na">authService</span><span class="err">.</span><span class="na">signIn</span><span class="err">()&quot;</span><span class="nt">&gt;</span>sign in<span class="nt">&lt;/a&gt;</span> to manage your task list. <span class="nt">&lt;/md-card-subtitle&gt;</span> <span class="nt">&lt;/md-card&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>And last, we are going to make a fix to the interface by adding a rule to <code>src/app/app.component.css</code>:</p> <pre><code class="css">.app-container { padding: 20px; } </code></pre> <p>Heading to our app, <code>http://localhost:4200/</code>, we can see our new welcome message (if we are not authenticated).</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/welcome-message.png" alt="Welcome message on our Angular task list app" /></p> <h2>Implementing Serverless REST API</h2> <p>Now that we have our application integrated with Auth0, which allows our users to sign in and sign out, let's create our serverless REST API. This API will handle <code>POST</code> requests (to persist new tasks), <code>GET</code> requests (to retrieve tasks from a user) and <code>DELETE</code> requests (to remove tasks).</p> <p>We will first create a file called <code>tasks.js</code> in a new folder called <code>webtask</code>, and then we will add the following code to it:</p> <pre><code class="js">'use strict'; // imports node modules const express = require('express'); const mongojs = require('mongojs'); const bodyParser = require('body-parser'); const jwt = require('jsonwebtoken'); // creates Express app with JSON body parser const app = new express(); app.use(bodyParser.json()); // defines REST API (HTTP methods) app.get('/', getTasks); app.post('/', addTask); app.delete('/', deleteTask); // exports REST API module.exports = app; function addTask(req, res) { let userCollection = loadUserCollection(req.webtaskContext); // save new task to user collection userCollection.save({ createdAt: new Date(), description: req.body.description }, () =&gt; res.end()) } function getTasks(req, res) { let userCollection = loadUserCollection(req.webtaskContext); // retrieves all tasks sorting by descending creation date userCollection.find().sort({ createdAt: -1 }, (err, data) =&gt; { res.status(err ? 500 : 200).send(err || data); }); } function deleteTask(req, res) { let userCollection = loadUserCollection(req.webtaskContext); // removes a task based on its id userCollection.remove({ _id: mongojs.ObjectId(req.query.id) }, () =&gt; res.end()); } function loadUserCollection(webtaskContext) { // this secrets are configured when creating the Webtask const AUTH0_SECRET = webtaskContext.secrets.AUTH0_SECRET; const MONGO_USER = webtaskContext.secrets.MONGO_USER; const MONGO_PASSWORD = webtaskContext.secrets.MONGO_PASSWORD; const MONGO_URL = webtaskContext.secrets.MONGO_URL; // removes the 'Bearer ' prefix that comes in the authorization header, let authorizationHeader = webtaskContext.headers.authorization; authorizationHeader = authorizationHeader.replace('Bearer ', ''); // verifies token authenticity let token = jwt.verify(authorizationHeader, AUTH0_SECRET); // connects to MongoDB and returns the user collection let mongodb = mongojs(`${MONGO_USER}:${MONGO_PASSWORD}@${MONGO_URL}`); return mongodb.collection(token.sub); } </code></pre> <p>The code is quite simple and easy to understand, but an overall explanation might come in handy. The main purpose of this file is to export an <a href="https://expressjs.com/en/starter/hello-world.html">Express app</a> that handles three HTTP methods for a single route, the main <code>/</code> route. These three methods, as explained before, allow users to create, retrieve and delete tasks from collections on a MongoDB database.</p> <p>Every user will have their own collection—not the best approach, since <a href="https://docs.mongodb.com/manual/reference/limits/#namespaces">MongoDB can handle a maximum of 24,000 collections</a>, but good enough to start. This collection is based on the <code>sub</code> claim, <a href="https://tools.ietf.org/html/rfc7519#section-4.1.2">which identifies user</a>, present in the JWT issued by Auth0.</p> <p>The last function definition in the <code>tasks.js</code> file, <code>loadUserCollection</code>, is actually responsible for two things: security and MongoDB connection. When a user issues any request to our API, the function verifies if the <code>authorization</code> header sent was actually signed by Auth0. If none is sent, a non-user-friendly error is generated. This is done through the <code>jwt.verify</code> function with the help if <code>AUTH0_SECRET</code> key. The second responsibility, connecting to MongoDB, is handled by the <code>mongojs</code> module and depends on three configuration variables: <code>MONGO_USER</code>, <code>MONGO_PASSWORD</code>, <code>MONGO_URL</code>.</p> <p>All these configuration variables—three to connect to MongoDB and one to verify Auth0 tokens—are passed to Webtask when creating the serverless function. We will see how this is done soon.</p> <p>This is the <strong>whole REST API implementation</strong>, with this code we are ready to handle users requests that will be sent by the components that we are about to create on our Angular app. But there are a few more steps that we need to perform.</p> <h3>Creating a MongoDB Database</h3> <p>To make our lives easier and to avoid heaving to install and support MongoDB by ourselves, we are going to use <a href="https://mlab.com">mLab</a>, a cloud-hosted MongoDB. The first thing that we have to do is to <a href="https://mlab.com/">head to their website</a> and sign up for a free account. After verifying our email address, we have to <a href="https://mlab.com/create">create a new deployment</a>. Since we are just starting our app and we won't get too much traffic, let's choose the <strong><em>Single Node</em></strong> plan and the <strong><em>Sandbox</em></strong> type, which provides us 500 MB of DB storage for free. You will also need to type a database name, choose something like <code>task-list</code>.</p> <p>The last thing that we will have to do is to create a user to connect to this database. If you choose <code>task-list</code> as the name of your database, <a href="https://mlab.com/databases/task-list#users">this is the link to create users</a>.</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/mlab-user.png" alt="Creating a mLab user" /></p> <h3>Configuring Webtask Account</h3> <p>We will also need to create a <a href="https://webtask.io">Webtask account</a>, but this as easy as it can be. Webtask, being a product of Auth0, relies on Lock and enables us to create an account with one of the following identity providers (IdP): Facebook, GitHub, Google or Microsoft. It is just a matter of hitting a button to create an account.</p> <p>After choosing an IdP, we are presented with a succinct, three-step process demonstrating how to create a <em>Hello World</em> serverless function. We already have a Webtask to deploy, so let's follow only the first two steps in order to configure the CLI tool in our computer:</p> <pre><code class="bash"># install Webtask CLI tool npm install wt-cli -g # initialize it with our email address wt init me@somewhere.com </code></pre> <p>You will be asked to enter the verification code that was sent to your email address. This is the final step in the Webtask account configuration.</p> <h3>Deploying Our Serverless REST API</h3> <p>With mLab and Webtask accounts created and having Webtask CLI tool correctly configured, we can now deploy our serverless REST API to production. This is done with the following code:</p> <pre><code class="bash">wt create webtask/tasks.js \ --meta wt-compiler=webtask-tools/express \ -s AUTH0_SECRET=secret-from-auth0.com \ -s MONGO_USER=task-list-user \ -s MONGO_PASSWORD=111222 \ -s MONGO_URL=ds147069.mlab.com:47069/task-list \ --prod </code></pre> <p>The first option passed to the <code>wt</code> tool specifies that we want to <code>create</code> a Webtask based on our <code>webtask/tasks.js</code> file. The second parameter identifies our code as being an Express app, which needs to be pre-compiled by Webtask with the help of <code>webtask-tools/express</code> tool. The following four parameters are the <code>secrets</code> that we use in our Webtask (<code>-s</code> prefix denotes them as <code>secrets</code>). The last parameter creates our Webtask in <code>production</code> mode, which makes it faster.</p> <p>Be aware that the values above have to be replaced with values that come from our Auth0 account and from our mLab account. <code>AUTH0_SECRET</code> value can be found at the same place of <code>Client ID</code> and <code>Domain</code>. And the last three values, related to MongoDB, can be found at mLab's dashboard.</p> <p>Having successfully issued the Webtask creation command, we can now focus on working on the main feature of our Angular application, the task list component.</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/creating-webtask-with-secrets.png" alt="Webtask Express app creation with secrets" /></p> <h2>Building our Angular Interface</h2> <p>There are two components that we will need to create to allow users to interact with their task lists. We will create a <code>TaskListComponent</code>, to expose the task list, and a <code>TaskFormComponent</code>, that will allow the user to create new tasks. Besides these components, we will create a <code>TaskListService</code> that will handle all AJAX requests. We will use Angular CLI to create them to us:</p> <pre><code class="bash"># creates the main component that lists tasks ng g component task-list # creates a component to hold a form to add tasks ng g component task-list/task-form # creates a service to handle all interaction with our REST API ng g service task-list/task-list </code></pre> <h3>Integrating Angular with Serverless REST API</h3> <p>Both <code>TaskListComponent</code> and <code>TaskFormComponent</code> will depend on <code>TaskListService</code> to communicate with our serverless REST API, so let's handle the service implementation first.</p> <p>Open the recently created service file, <code>src/app/task-list/task-list.service.ts</code>, and insert the following code:</p> <pre><code class="typescript">import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { AuthHttp } from 'angular2-jwt'; @Injectable() export class TaskListService { private static TASKS_ENDPOINT = 'https://wt-e1870b8a73b27cdee73c468b8c8e3bc4-0.run.webtask.io/tasks'; constructor(private authHttp: AuthHttp) { } loadTasks$(): Observable&lt;any&gt; { return this.authHttp.get(TaskListService.TASKS_ENDPOINT); } addTask$(task) : Observable&lt;any&gt; { return this.authHttp.post(TaskListService.TASKS_ENDPOINT, { description: task }); } deleteTask$(task): Observable&lt;any&gt; { return this.authHttp.delete(TaskListService.TASKS_ENDPOINT + '?id=' + task._id); } } </code></pre> <p>There are three important things to note in this code. First, the <code>TASKS_ENDPOINT</code> constant. This constant must reference the <em>URL</em> returned by the <code>wt create</code> command above.</p> <p>Second, this class is not using <code>Http</code> from <code>@angular/http</code>. It is using <code>AuthHttp</code>, which is provided by <code>angular2-jwt</code> and which integrates gracefully with <code>auth0-lock</code>. Instances of this class automatically send an <code>authorization</code> header with whatever content it finds on <code>id_token</code> key on the user browser <code>localStorage</code>. As you may have noted, this is the same place where we stored tokens when configuring <code>AuthService</code>.</p> <p>Third, all methods in <code>TaskListService</code> return <code>Observables</code>, leaving the caller to decide what to do with the response sent by our serverless REST API.</p> <p>To inject <code>TaskListService</code> in our components, we need to make a few changes in our main <code>@NgModule</code>, located in <code>src/app/app.module.ts</code>:</p> <pre><code class="typescript">// ... other imports import { Http, RequestOptions } from '@angular/http'; import { AuthHttp, AuthConfig } from 'angular2-jwt'; import { TaskListService } from './task-list/task-list.service'; // creates a factory to AuthHttp export function authHttpFactory(http: Http, options: RequestOptions) { return new AuthHttp(new AuthConfig(), http, options); } @NgModule({ // ... other properties providers: [ AuthService, TaskListService, // adds new service { provide: AuthHttp, useFactory: authHttpFactory, // defines how to provide AuthHttp deps: [ Http, RequestOptions ] } ], bootstrap: [AppComponent] }) </code></pre> <p>The first change that we made to our module was to add <code>TaskListService</code> as a provider, just like we did before with <code>AuthService</code>. The second change also added a provider, but in a more complex form.</p> <p>The <code>AuthHttp</code> provider needed help from a factory - declared as <code>authHttpFactory</code> - to be created. This factory has <code>Http</code> and <code>RequestOptions</code> as dependencies, so we needed to define the provider as a literal object, passing this dependencies explicitly.</p> <h3>Listing Tasks with Angular</h3> <p>Our <code>TaskListComponent</code> can now be implemented. We will now open the <code>src/app/task-list/task-list.component.ts</code> file and apply the code below:</p> <pre><code class="typescript">import { Component, OnInit } from '@angular/core'; import { TaskListService } from './task-list.service'; @Component({ selector: 'app-task-list', templateUrl: './task-list.component.html', styleUrls: [ './task-list.component.css' ] }) export class TaskListComponent implements OnInit { private tasks: String[]; constructor(private taskListService: TaskListService) { } ngOnInit() { this.loadTasks(); } private loadTasks() { this.taskListService.loadTasks$().subscribe( response =&gt; this.tasks = response.json(), error =&gt; console.log(error) ); } taskAddedHandler(task) { this.taskListService.addTask$(task).subscribe( response =&gt; this.loadTasks(), error =&gt; console.log() ); } deleteTask(task) { this.taskListService.deleteTask$(task).subscribe( response =&gt; this.loadTasks(), error =&gt; console.log() ); } } </code></pre> <p>This class gets <code>TaskListService</code> injected and add a few callback methods to the <code>Observables</code> responses. Both <code>taskAdded$</code> and <code>deleteTask$</code> triggers a call to <code>loadTasks</code> method when the <code>Observables</code> respond without errors. <code>console.log</code> is triggered by these methods to handle cases where errors are issued by the serverless REST API.</p> <p>The <code>loadTasks</code> method calls <code>taskListService.loadTasks$</code> to assign the result to <code>tasks</code> property.</p> <p>With the three exposed methods and the <code>task</code> property filled, we can now implement the <code>TaskListComponent</code> interface, which resides in the <code>src/app/task-list/task-list.component.html</code> file.</p> <p>This is what this file should look like:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;md-card&gt;</span> <span class="nt">&lt;md-card-title&gt;</span>Task List<span class="nt">&lt;/md-card-title&gt;</span> <span class="nt">&lt;md-card-subtitle&gt;</span>All your tasks in one place.<span class="nt">&lt;/md-card-subtitle&gt;</span> <span class="nt">&lt;md-list&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;task-item&quot;</span> <span class="err">*</span><span class="na">ngFor=</span><span class="s">&quot;let task of tasks; trackBy: $index&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;p&gt;&lt;small&gt;&lt;strong&gt;</span>{{ task.createdAt | date: &#39;short&#39; }}<span class="nt">&lt;/strong&gt;&lt;/small&gt;&lt;/p&gt;</span> <span class="nt">&lt;p&gt;</span>{{ task.description }}<span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">&quot;delete&quot;</span> <span class="na">md-button</span> <span class="na">md-raised-button</span> <span class="na">color=</span><span class="s">&quot;accent&quot;</span> <span class="err">(</span><span class="na">click</span><span class="err">)=&quot;</span><span class="na">deleteTask</span><span class="err">(</span><span class="na">task</span><span class="err">)&quot;</span><span class="nt">&gt;</span>Delete<span class="nt">&lt;/button&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;task-item&quot;</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;tasks?.length == 0&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;p&gt;</span>You have no pending tasks.<span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/md-list&gt;</span> <span class="nt">&lt;/md-card&gt;</span></code></pre></div> <p>Here we added a <code>md-list</code> component, <a href="https://material.angular.io/components/component/list">provided by Angular Material</a>, that iterates through the <code>tasks</code>, showing their creation date and their description. Also, each task got a <code>button</code> that enables users to delete them.</p> <p>To make our interface better, let's add two CSS rules to the <code>src/app/task-list/task-list.component.css</code> file:</p> <pre><code class="css">.task-item { padding: 10px; margin-bottom: 10px; background-color: #eee; } button.delete { float: right; top: -60px; } </code></pre> <p>This will make different tasks distinguishable with a gray background color, and push the delete button to the right, aligning it vertically to the task.</p> <p>Now our interface is ready to list tasks, so we need to make it visible by adding it to the <code>src/app/app.component.html</code> file. Open it and the <code>TaskListComponent</code> as follows:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;app-nav-bar&gt;&lt;/app-nav-bar&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;app-container&quot;</span><span class="nt">&gt;</span> <span class="c">&lt;!-- ... card with welcome message --&gt;</span> <span class="nt">&lt;app-task-list</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;authService.authenticated()&quot;</span><span class="nt">&gt;&lt;/app-task-list&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>If we open our application in a browser, by accessing <code>http://localhost:4200</code>, we would see the following screen.</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/no-pending-tasks.png" alt="Angular material with empty list of tasks" /></p> <p>Our app's completion now depends on implementing the last component, <code>TaskFormComponent</code>, to allow users to add tasks to their lists.</p> <h3>Adding Tasks with Angular</h3> <p>To enable a user to add tasks, we need to open the <code>src/app/task-list/task-form/task-form.component.ts</code> file and implement it as follows:</p> <pre><code class="typescript">import { Component, EventEmitter, Output } from '@angular/core'; @Component({ selector: 'app-task-form', templateUrl: './task-form.component.html', styleUrls: ['./task-form.component.css'] }) export class TaskFormComponent { @Output() taskAdded = new EventEmitter(); public task: String = null; addTask() { this.taskAdded.emit(this.task); this.task = null; } } </code></pre> <p>This component accepts a user's task input and emits a <code>taskAdded</code> event with the data. This component's HTML, located in the <code>src/app/task-list/task-form/task-form.component.html</code> file, is also really simple:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;task-form&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;md-input</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&quot;</span><span class="na">task</span><span class="err">&quot;</span> <span class="na">placeholder=</span><span class="s">&quot;New task&quot;</span><span class="nt">&gt;&lt;/md-input&gt;</span> <span class="nt">&lt;button</span> <span class="na">md-button</span> <span class="na">md-raised-button</span> <span class="na">color=</span><span class="s">&quot;primary&quot;</span> <span class="err">(</span><span class="na">click</span><span class="err">)=&quot;</span><span class="na">addTask</span><span class="err">()&quot;</span><span class="nt">&gt;</span>Add<span class="nt">&lt;/button&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>When clicked, the <em>Add</em> button triggers the <code>addTask</code> method in the component. This method then triggers the <code>taskAdded</code> event emitter. <code>TaskListComponent</code> is the component that will listen to these events. We already implemented a method, called <code>taskAdded</code>, that can handle such events. We just need to update this component's HTML to add <code>TaskFormComponent</code> and register the event handler.</p> <p>To do that, let's open <code>src/app/task-list/task-list.component.html</code> and add the <code>app-task-form</code> tag just before our list, as follows:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;md-card&gt;</span> <span class="c">&lt;!-- ... card title and subtitle --&gt;</span> <span class="nt">&lt;app-task-form</span> <span class="err">(</span><span class="na">taskAdded</span><span class="err">)=&quot;</span><span class="na">taskAddedHandler</span><span class="err">($</span><span class="na">event</span><span class="err">)&quot;</span><span class="nt">&gt;&lt;/app-task-form&gt;</span> <span class="c">&lt;!-- ... md-list --&gt;</span> <span class="nt">&lt;/md-card&gt;</span></code></pre></div> <p>And here we go. Our app is now fully implemented and ready to go to production.</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/first-task-recorded.png" alt="Task list Angular app with serverless REST API and MongoDB fully implemented" /></p> <p>Or is it? If we play a little with the application we will see that under some conditions the user experience is not that good. The app takes a while to update the task list when a new task is added or an existing one gets deleted. So there is room for improvement.</p> <h3>Adding an AJAX Loading Indicator</h3> <p>To solve this issue let's use a small module called <a href="https://github.com/akserg/ng2-slim-loading-bar">Angular 2 Slim Loading Bar</a>. To install it run <code>npm install --save ng2-slim-loading-bar</code> and then open the <code>src/app/app.module.ts</code> file to import it:</p> <pre><code class="typescript">// ... other module imports import { SlimLoadingBarModule } from 'ng2-slim-loading-bar'; @NgModule({ // ... declarations imports: [ // ... other imports SlimLoadingBarModule.forRoot() ], // ... providers and bootstrap }) export class AppModule { } </code></pre> <p>We will also import its CSS rules by adding the following line to the top of our <code>src/styles.css</code> file:</p> <pre><code class="css">@import '~ng2-slim-loading-bar/bundles/style.css'; /* ... everything else ... */ </code></pre> <p>After that we need to make our <code>AppComponent</code> use <code>SlimLoadingBarService</code>. To do that let's open <code>src/app/app.component.ts</code> and edit as follows:</p> <pre><code class="typescript">// ... other imports import { SlimLoadingBarService } from 'ng2-slim-loading-bar'; // ... component definition export class AppComponent { constructor(private authService: AuthService, private slimLoading: SlimLoadingBarService) { } // ... method definitions } </code></pre> <p><code>SlimLoadingBarService</code> contains two methods that we will use: <code>start</code>, which starts the loading bar; and <code>complete</code>, which ends the loading indicator. These methods will be registered as event listeners on <code>TaskListComponent</code>. We still didn't create event emitters in this component, but we can configure the listeners in advance. Let's open <code>src/app/app.component.html</code> and edit like this:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;app-nav-bar&gt;&lt;/app-nav-bar&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;app-container&quot;</span><span class="nt">&gt;</span> <span class="c">&lt;!-- ... welcome message ... --&gt;</span> <span class="nt">&lt;app-task-list</span> <span class="err">*</span><span class="na">ngIf=</span><span class="s">&quot;authService.authenticated()&quot;</span> <span class="err">(</span><span class="na">startAjaxRequest</span><span class="err">)=&quot;</span><span class="na">slimLoading</span><span class="err">.</span><span class="na">start</span><span class="err">()&quot;</span> <span class="err">(</span><span class="na">completeAjaxRequest</span><span class="err">)=&quot;</span><span class="na">slimLoading</span><span class="err">.</span><span class="na">complete</span><span class="err">()&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;/app-task-list&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="c">&lt;!-- adds the slim loading bar to our app --&gt;</span> <span class="nt">&lt;ng2-slim-loading-bar</span> <span class="err">[</span><span class="na">color</span><span class="err">]=&quot;&#39;</span><span class="na">gold</span><span class="err">&#39;&quot;</span> <span class="err">[</span><span class="na">height</span><span class="err">]=&quot;&#39;</span><span class="na">4px</span><span class="err">&#39;&quot;</span><span class="nt">&gt;&lt;/ng2-slim-loading-bar&gt;</span></code></pre></div> <p>The last thing we will have to do is edit the <code>src/app/task-list/task-list.component.ts</code> file to create and use both <code>startAjaxRequest</code> and <code>completeAjaxRequest</code> event emitters on <code>TaskListComponent</code>:</p> <pre><code class="typescript">// ... other imports import { EventEmitter, Output } from '@angular/core'; // ... component definition export class TaskListComponent implements OnInit { @Output() startAjaxRequest = new EventEmitter&lt;void&gt;(); @Output() completeAjaxRequest = new EventEmitter&lt;void&gt;(); // ... properties, constructor and ngOnInit definitions private loadTasks() { this.startAjaxRequest.emit(); this.taskListService.loadTasks$().subscribe( response =&gt; this.tasks = response.json(), error =&gt; console.log(error), () =&gt; this.completeAjaxRequest.emit() ); } taskAddedHandler(task) { this.startAjaxRequest.emit(); this.taskListService.addTask$(task).subscribe( response =&gt; this.loadTasks(), error =&gt; console.log() ); } deleteTask(task) { this.startAjaxRequest.emit(); this.taskListService.deleteTask$(task).subscribe( response =&gt; this.loadTasks(), error =&gt; console.log() ); } } </code></pre> <p>Here we have create both event emitters and have added them to the three methods that depend on AJAX request. Whenever one of these methods gets called we emit an event, through <code>this.startAjaxRequest.emit()</code>, to make the <em>Slim Loading Bar</em> start running the loading bar indicator. After getting a response back from the AJAX requests sent by the <code>loadTasks</code> method, that updates the task list, we tell <em>Slim Loading Bar</em> to complete its progress through <code>this.completeAjaxRequest.emit()</code>.</p> <p>If we run our development server by issuing <code>ng serve</code> and heading to <code>http://localhost:4200/</code>, we will see our application with a better user experience:</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/slim-loading-bar.png" alt="Slim loading bar on task list Angular application" /></p> <h2>Going Live with GitHub Pages</h2> <p>Our application is ready to be deployed to production. We have a persistence layer that saves all users' tasks. We have a serverless REST API that accepts <code>GET</code>, <code>POST</code> and <code>DELETE</code> requests to manipulate tasks. We have security, provided by Auth0. And we have a good looking Angular single page application interface. The only thing that is missing is a place to host our static (HTML, CSS and JavaScript) files.</p> <p>That is exactly what <a href="https://pages.github.com/">GitHub Pages provides</a>. To use it is simple. We just need to create a repository and push our work to a branch called <code>gh-pages</code>. This branch should contain only our production bundles.</p> <p>To create a GitHub repository go to <a href="https://github.com/">GitHub</a>, sign in (or sign up if you don't have an account) and choose the <em>Create a New Repository</em> option. Create your new repository naming it as <em>task-list</em>. Note that if you choose another name, you will have to adjust the <code>base-href</code> parament of the <code>ng build</code> command that we will run later.</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/create-github-repo.png" alt="Creating a GitHub repository" /></p> <p>Now we have to add this repository as a remote to our application. When we created our project with Angular CLI, it already came with <a href="https://git-scm.com/">Git</a>. We just have to add this remote, commit all our changes and push to its master:</p> <pre><code class="bash"># adds new repo as a remote git remote add origin git@github.com:YOUR-USERNAME/YOUR-REPO.git # commits our code git add . git commit -m "Task List Angular app with a secure serverless REST API." # push work to new repo git push origin master </code></pre> <p>Having our code safe, we can now work on the <em>going live</em> task. Two steps are needed here. The first one is to prepare our code for production and package it. Again Angular CLI comes in handy. To do that we just have to issue <code>ng build --prod --base-href=/task-list/</code>. Note that we have to set <code>base-href</code> to the exact same name of our GitHub repository, otherwise our application won't be able to load all the resources and it won't work.</p> <p>The second step used to be handled by Angular CLI, but <a href="https://github.com/angular/angular-cli/pull/4385">this command has been removed in the latest release</a>, so we will need a third party tool to help us here. Fortunately, there is one that is very easy to use called <code>angular-cli-ghpages</code>. To install it issue <code>npm install -g angular-cli-ghpages</code>. After that we just have to execute <code>angular-cli-ghpages</code> (yep, without any parameters) and voilà. Our app is up and running on GitHub Pages.</p> <p><strong>Important</strong>: do not forget to update the <em>Allowed Callback URLs</em> on your Auth0 account. The list of allowed URLs must have the URL where our app was exposed. This should be something like <code>https://brunokrebs.github.io/task-list/</code>.</p> <p><img src="https://cdn.auth0.com/blog/serverless-angular/running-on-github-pages.png" alt="Angular application, with secured serverless REST API running on GitHub Pages" /></p> <h2>Conclusion</h2> <p>As we could see, when we choose the right tools, it gets easy to achieve great accomplishments. We started with nothing, just an idea to develop a task list application, and managed to create and release it to the internet with not that much effort.</p> <p>We didn't even have to worry about building, supporting and securing servers to host our web application or our database. If we had to manage these tasks by ourselves, we would take much more time and wouldn't be as confident about our app's security, fault tolerance and scalability.</p> <p>And this is just the beginning. Freeing ourselves from all these issues enables us to focus 100% on our ideas and on what makes our applications unique.</p> ReactJS Authentication Tutorial 2017-02-21T08:30:00+00:00 https://auth0.com/blog/reactjs-authentication-tutorial/ Prosper Otemuyiwa https://twitter.com/unicodeveloper?lang=en <hr /> <p><strong>TL;DR:</strong> ReactJS is a declarative, efficient and flexible JavaScript library for building user interfaces. Currently, ReactJS has over 58,000 stars on <a href="https://github.com/facebook/react">GitHub</a>. ReactJS makes it easy for you to build your web applications in the form of encapsulated components that manage their own state. In this tutorial, I'll show you how easy it is to build a web application with ReactJS and add authentication to it. Check out the <a href="https://github.com/auth0-blog/reactjs-authentication-tutorial">repo</a> to get the code.</p> <hr /> <p><strong>ReactJS</strong> is a JavaScript library, built and maintained by Facebook. It was developed by <a href="https://twitter.com/jordwalke">Jordan Walke</a>, a software engineer at Facebook. It was open-sourced and announced to the developer community in March 2015. Since then, it has undergone tremendous growth and adoption in the developer community. In fact, as at the time of writing, <strong>ReactJS</strong> is the 5th most starred project of all time on GitHub.</p> <p>Currently, many web platforms use <strong>ReactJS</strong> to build their user interfaces. Such platforms include <em>Netflix</em>, <em>Instagram</em>, <em>Airbnb</em>, <em>KhanAcademy</em>, <em>Walmart</em> and more. The <a href="https://facebook.github.io/react">documentation</a> is very detailed, and there is a vibrant community of users. In addition, a plethora of <strong>ReactJS</strong> addons exist on GitHub for easy inclusion in your project for whatever functionality you are trying to build.</p> <h2>Understanding Key Concepts in ReactJS</h2> <p><strong>ReactJS</strong> was influenced by <strong>XHP</strong>, an augmentation of <a href="https://github.com/php/php-src">PHP</a> and <a href="http://hacklang.org">Hack</a> to allow XML syntax for the purpose of creating custom and reusable HTML elements. If you're coming from the world of <a href="https://jquery.com">jQuery</a> and don't have experience with frameworks like Angular, Ember, or VueJS, you may find <strong>ReactJS</strong> very confusing. There are many questions you might have to ask yourself, such as:</p> <ul> <li>Why are JavaScript and HTML together in one script?</li> <li>What is JSX? Why is the syntax so weird?</li> <li>What is a state?</li> <li>Why do we need props?</li> <li>What are and why do we need components in our apps?</li> </ul> <p>Don't worry, you'll have answers to your many questions soon! There are some key concepts you need to know when learning React. Once you have a basic understanding of these concepts, then you'll be able to create your first <strong>ReactJS</strong> app without banging your head on the wall.</p> <p>These key concepts are:</p> <ul> <li><strong>Components - The Types and API</strong></li> <li><strong>Props</strong></li> <li><strong>State</strong></li> <li><strong>JSX</strong></li> </ul> <p>I'll give a basic overview of these concepts to nourish your understanding of <strong>ReactJS</strong>.</p> <h3>Components - The Types and API</h3> <p>React is basically about components. A ReactJS app is just one big component made up of interoperable smaller components. Working with ReactJS means you are thinking in components most of the time.</p> <p>An example of a component is an HTML 5 tag, say <code>&lt;header&gt;</code>. A header can have attributes, it can be styled and also possess its own behaviour. In <strong>ReactJS</strong>, you'll be able to build your own custom component using <a href="https://auth0.com/blog/a-rundown-of-es6-features/"><strong>ES6</strong></a> like so:</p> <pre><code class="js"> class CustomComponent extends React.Component { render() { return '&lt;h3&gt; This is my custom component!!!&lt;/h3&gt;'; } } </code></pre> <p>So, your component will now be <code>&lt;CustomComponent&gt;&lt;/CustomComponent&gt;</code>.</p> <p>React provides some methods that are triggered at various points from creating a component up until the component is destroyed. This is called the <a href="https://facebook.github.io/react/docs/state-and-lifecycle.html">Component's Lifecycle</a>. You can declare methods to hook into the component's lifecycle to control the behaviour of components in your app. Some examples of these lifecycle hooks are <code>componentDidMount()</code>, <code>componentWillMount()</code>, <code>componentWillUnmount()</code>, <code>shouldComponentUpdate()</code>, <code>componentWillUpdate()</code> and more.</p> <ul> <li><strong>componentWillMount()</strong> : This method is called before the component is initially rendered. So it is called before the <code>render</code> method is executed. You can't perform any type of DOM manipulation here because the component isn't available in the DOM yet.</li> <li><strong>componentDidMount()</strong> : This method is called right after the component has been rendered. So it is called immediately after the <code>render</code> method has been executed. It's the best place to perform network and AJAX calls.</li> <li><strong>componentWillUnmount()</strong> : This method is called right before the component is removed from the DOM.</li> <li><strong>shouldComponentUpdate()</strong> : This method determines if a re-rendering should occur or not. It is never called on initial rendering and it's always called before the render method.</li> <li><strong>componentWillUpdate()</strong> : This method is called as soon as <code>shouldComponentUpdate</code> returns true. It is called just before the component is rendered with new data.</li> </ul> <p>There are also methods like <a href="https://facebook.github.io/react/docs/rendering-elements.html"><code>render</code></a> and <a href="https://facebook.github.io/react/docs/state-and-lifecycle.html"><code>setState</code></a> that you can use to render an element on the DOM and set the state of a component respectively.</p> <p>Take this example for a spin and watch how these lifecycle hooks work. Observe the sequence of logs in the browser console.</p> <pre><code class="js"> import React, { Component } from 'react'; import { render } from 'react-dom'; class Experiment extends Component { componentWillMount() { console.log("This will mount"); } componentDidMount() { console.log("This did mount"); } componentWillUnmount() { console.log("This will unmount"); } render() { console.log("I am just rendering like a boss"); return &lt;div&gt;I got rendered!&lt;/div&gt;; } } render( &lt;Experiment /&gt;, document.getElementById("root") ); </code></pre> <h3>Props</h3> <p><code>Props</code> is the short form for <code>properties</code>. Properties are attributes of a component. In fact, props are how components talk to each other. A tag in HTML such as <code>&lt;img&gt;</code> has an attribute, a.k.a <code>prop</code> called <code>src</code> that points to the location of an image.</p> <p>In React, you can have two components, <code>FatherComponent</code> and <code>SonComponent</code>. Let's see how they can talk to each other.</p> <pre><code class="js"> class FatherComponent extends React.Component { render() { return &lt;SonComponent quality="eye balls" /&gt;; } } </code></pre> <p><em>FatherComponent</em></p> <pre><code class="js"> class SonComponent extends React.Component { render() { return &lt;p&gt; I am a true son. I have my father's "{ this.props.quality }" . &lt;/p&gt;; } } </code></pre> <p><em>SonComponent</em></p> <p>Now, when the page is served and a <code>&lt;FatherComponent&gt;</code> is called, <code>I am a true son. I have my father's eyes</code> will be rendered on the page.</p> <h3>State</h3> <p>When developing <em>ReactJS</em> applications, it is important to know when and when not to use state in components. The question now is: <em>When do I use state?</em>, <em>When do I use props?</em> Props are data that the component depends on to render correctly. Most times, it comes from above, meaning it is passed down from a parent component to a child component. Like <code>props</code>, <code>state</code> holds information about the component but it is handled differently.For example, the number of times a button was clicked, user input from a form, etc. When state changes in a component, the component automatically re-renders and updates the DOM.</p> <p>Inside a component, state is managed using a <code>setState</code> function.</p> <pre><code class="js"> class Layout extends React.Component { constructor() { super(); this.state = { position: "right" }; } render() { return ( { this.state.position } ) } } </code></pre> <pre><code class="js"> class Button extends React.Component { constructor() { super(); this.state = { count: 0, }; } updateCount() { this.setState((prevState, props) =&gt; { return { count: prevState.count + 1 } }); } render() { return ( &lt;button onClick={() =&gt; this.updateCount()} &gt; Clicked {this.state.count} times &lt;/button&gt; ); } } </code></pre> <p>Now, this works great for simple applications like the one we'll build in this tutorial. For medium and large apps, it is recommended to use a state management library like <a href="http://redux.js.org">Redux</a> or <a href="https://github.com/mobxjs/mobx">MobX</a> to avoid big balls of messy code and also to help you track every event happening within your app.</p> <h3>JSX</h3> <p>Initially, looking at JSX seems awkward. JSX is the combination of HTML and JavaScript code in the same file. You can decide to name the extension of the filem<code>.jsx</code> or just <code>.js</code>. An example of JSX is:</p> <pre><code class="js"> class Layout extends React.Component { render() { return &lt;p&gt;Hello {this.props.layoutStructure ? 'Frontend layout' : 'Backend Layout'}&lt;/p&gt;; } } </code></pre> <p>You can check out more <a href="https://facebook.github.io/react/docs/introducing-jsx.html">information on JSX here</a>.</p> <p>Next, let's build an application with <em>ReactJS</em>.</p> <h2>Our App: Chuck Norris World</h2> <p><img src="https://cdn.auth0.com/blog/react/app.png" alt="Chuck Norris World" /></p> <p>The app we will build today is called Chuck Norris World. Our app is an eye into the world of Chuck Norris and his greatness. The Chuck Norris World app will display different jokes about the legend. A list of common food jokes will be available to the general public, while the celebrity jokes will only be accessible to registered members.</p> <p><strong>Note:</strong> These days, celebrities demand a lot of cash for jokes made at their expense, and Chuck Norris isn't helping matters. Always cracking jokes about them, sigh!</p> <h2>Build The Back-End</h2> <p>Let's build an API to serve the list of jokes to our app. We'll quickly build the API with <a href="https://nodejs.org">Node.js</a>. The API is simple. This is what we need:</p> <ul> <li>An endpoint to serve jokes about food - <code>/api/jokes/food</code>.</li> <li>An endpoint to serve jokes about celebrities - <code>/api/jokes/celebrity</code>.</li> <li>Secure the endpoint that serves celebrity jokes, so that it can only be accessed by registered users.</li> </ul> <p>Go ahead and fetch the <a href="https://github.com/auth0-blog/reactjs-authentication-tutorial/tree/master/server">Node.js backend from GitHub</a>.</p> <p>Your <code>server.js</code> should look like this:</p> <pre><code class="js"> 'use strict'; const express = require('express'); const app = express(); const jwt = require('express-jwt'); const cors = require('cors'); const bodyParser = require('body-parser'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(cors()); const authCheck = jwt({ secret: 'AUTH0_CLIENT_SECRET', audience: 'AUTH0_CLIENT_ID ' }); app.get('/api/jokes/food', (req, res) =&gt; { let foodJokes = [ { id: 99991, joke: "When Chuck Norris was a baby, he didn't suck his mother's breast. His mother served him whiskey, straight out of the bottle." }, { id: 99992, joke: 'When Chuck Norris makes a burrito, its main ingredient is real toes.' }, { id: 99993, joke: 'Chuck Norris eats steak for every single meal. Most times he forgets to kill the cow.' }, { id: 99994, joke: "Chuck Norris doesn't believe in ravioli. He stuffs a live turtle with beef and smothers it in pig's blood." }, { id: 99995, joke: "Chuck Norris recently had the idea to sell his urine as a canned beverage. We know this beverage as Red Bull." }, { id: 99996, joke: 'When Chuck Norris goes to out to eat, he orders a whole chicken, but he only eats its soul.' } ]; res.json(foodJokes); }) app.get('/api/jokes/celebrity', (req,res) =&gt; { let CelebrityJokes = [ { id: 88881, joke: 'As President Roosevelt said: "We have nothing to fear but fear itself. And Chuck Norris."' }, { id: 88882, joke: "Chuck Norris only lets Charlie Sheen think he is winning. Chuck won a long time ago." }, { id: 88883, joke: 'Everything King Midas touches turnes to gold. Everything Chuck Norris touches turns up dead.' }, { id: 88884, joke: 'Each time you rate this, Chuck Norris hits Obama with Charlie Sheen and says, "Who is winning now?!"' }, { id: 88885, joke: "For Charlie Sheen winning is just wishful thinking. For Chuck Norris it's a way of life." }, { id: 88886, joke: "Hellen Keller's favorite color is Chuck Norris." } ]; res.json(CelebrityJokes); }) app.listen(3333); console.log('Listening on localhost:3333'); </code></pre> <p><em>server.js</em></p> <p>Your <code>package.json</code> file should look like this:</p> <pre><code class="js"> { "name": "chuck-norris-jokes", "version": "0.0.1", "description": "", "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" &amp;&amp; exit 1", "start": "node server.js", "dev": "nodemon server.js" }, "author": "Auth0", "license": "MIT", "dependencies": { "body-parser": "^1.15.2", "cors": "^2.8.1", "express": "^4.14.0", "express-jwt": "^3.4.0" } } </code></pre> <blockquote><p><strong>Note:</strong> Make sure you have <a href="https://github.com/remy/nodemon"><code>nodemon</code></a> installed globally.</p></blockquote> <p><em>package.json</em></p> <p>Once you have cloned the project, run an <code>npm install</code>, then use <a href="https://www.getpostman.com">postman</a> to serve your routes like so:</p> <p><img src="https://cdn.auth0.com/blog/react/postman.png" alt="API serving food jokes" /> <em>API serving food jokes</em></p> <p><img src="https://cdn.auth0.com/blog/react/postmanfood.png" alt="API serving celebrity jokes" /> <em>API serving celebrity jokes</em></p> <p>The Food jokes endpoint should be <code>http://localhost:3333/api/jokes/food</code>.</p> <p>The Celebrity jokes endpoint should be <code>http://localhost:3333/api/jokes/celebrity</code>.</p> <p>Don't worry about the middleware in charge of securing our endpoint for now. We'll deal with that later. Now, let's build our frontend with ReactJS. Woot! Woot!</p> <h2>Build The Front-End With ReactJS</h2> <p>In the early days of <strong>ReactJS</strong>, there was no tool or common way to set up a <em>ReactJS</em> app. However, React is more mature now; plenty of boilerplates, starters, and open source tools are currently available to help you set up an app. There is one that stands out because of its simplicity. It's called the <a href="https://github.com/facebookincubator/create-react-app">Create-React-App (CRA) CLI</a> tool. It's being maintained by Facebook.</p> <blockquote><p><strong>Note:</strong> We have a custom React script that comes bundled with Auth0 authentication. So you can use create-react-app to boostrap an app with authentication support like this <code>create-react-app my-app --scripts-version auth0-react-scripts</code></p></blockquote> <p>Go ahead and install the CRA tool globally like so:</p> <pre><code class="bash"> npm install -g create-react-app </code></pre> <p>After installing globally, go ahead and scaffold a new <strong>ReactJS</strong> app like so:</p> <pre><code class="bash"> create-react-app chucknorrisworld </code></pre> <p>Then open <a href="http://localhost:3000"><code>http://localhost:3000</code></a> to see your app.</p> <p><img src="https://cdn.auth0.com/blog/react/ready-app.png" alt="App recently scaffolded and showing at Localhost" /></p> <p><strong>Note:</strong> <code>create-react-app</code> automatically invokes Yarn for installation. If you don't have Yarn installed, it falls back to use npm.</p> <p>Let's check out the structure of our newly scaffolded app.</p> <p><img src="https://cdn.auth0.com/blog/react/folder-structure.png" alt="Scaffolded App" /></p> <pre><code class="bash">my-app/ README.md node_modules/ - All the packages required for the react app resides here package.json - File that contains the names of all the packages residing in node_modules folder public/ index.html - Index file that declares the root div where the App component is been bound to favicon.ico - The app’s favicon src/ App.css - File that contains styles for the App component App.js - Basic App Component App.test.js - Test file that contains tests for the App Component index.css - File that contains style for root div index.js - Javascript file that binds the root div to the parent App Component logo.svg </code></pre> <p>We will work with this structure but make some few modifications. First, delete the <code>App.test.js</code> file.</p> <p><strong>Note:</strong> We are not writing any tests for this application. It's out of the scope of this tutorial. If you want to learn how to test your <strong>ReactJS</strong> applications, check out <a href="https://auth0.com/blog/testing-react-applications-with-jest/">testing react applications with Jest</a>.</p> <p>Make the following modifications like so:</p> <ul> <li>Create a folder called <code>components</code> inside the <code>src</code> directory. This will house our components.</li> <li>Create a <code>CelebrityJokes.js</code> file inside the <code>components</code> directory. This component will take care of fetching the celebrity jokes and displaying them to the user.</li> <li>Create a <code>FoodJokes.js</code> file inside the <code>components</code> directory. This component will take care of fetching the food jokes and displaying them to the user.</li> <li>Create a <code>Nav.js</code> file inside the <code>components</code> directory. This component will be in charge of our navigation throughout the app.</li> <li>Create a folder called <code>utils</code> inside the <code>src</code> directory. This will house our helper functions.</li> <li>Delete <code>App.js</code> file. Are you surprised? Don’t worry, we won’t need it.</li> </ul> <h2>Fetch the API Data</h2> <p>The first thing we need to do is to fetch the API data from our Node backend to display in our app. Make sure the Node server is running.</p> <p>Let's create a helper file to handle fetching the API. Create a <code>chucknorris-api.js</code> file inside the <code>utils</code> directory.</p> <p>Open up the file and add code to it like so:</p> <pre><code class="js"> import axios from 'axios'; const BASE_URL = 'http://localhost:3333'; export {getFoodData, getCelebrityData}; function getFoodData() { const url = `${BASE_URL}/api/jokes/food`; return axios.get(url).then(response =&gt; response.data); } function getCelebrityData() { const url = `${BASE_URL}/api/jokes/celebrity`; return axios.get(url).then(response =&gt; response.data); } </code></pre> <p><em>chucknorris-api.js</em></p> <p><strong>Note:</strong> Install <code>axios</code> in your app by running <code>npm install axios --save</code>.</p> <p>We are using a very good promise based http client, <a href="https://github.com/mzabriskie/axios">axios</a>. An alternative for this is <a href="https://github.com/visionmedia/superagent">superagent</a>.</p> <p>In the <code>getFoodData</code> and <code>getCelebrityData</code> functions, axios fetches data from the API endpoints. Then we do this: <code>export {getFoodData, getCelebrityData};</code> to make them ready for use in our components.</p> <h2>Build the Nav Component</h2> <p>The <code>Nav.js</code> file is our Nav component. Go ahead and add code to it like so:</p> <pre><code class="js"> import React, { Component } from 'react'; import { Link } from 'react-router'; import '../App.css'; class Nav extends Component { render() { return ( &lt;nav className="navbar navbar-default"&gt; &lt;div className="navbar-header"&gt; &lt;Link className="navbar-brand" to="/"&gt;Chuck Norris World&lt;/Link&gt; &lt;/div&gt; &lt;ul className="nav navbar-nav"&gt; &lt;li&gt; &lt;Link to="/"&gt;Food Jokes&lt;/Link&gt; &lt;/li&gt; &lt;li&gt; &lt;Link to="/special"&gt;Celebrity Jokes&lt;/Link&gt; &lt;/li&gt; &lt;/ul&gt; &lt;ul className="nav navbar-nav navbar-right"&gt; &lt;li&gt;&lt;button className="btn btn-info log"&gt;Log In&lt;/button&gt;&lt;/li&gt; &lt;li&gt;&lt;button className="btn btn-danger log"&gt;Log out &lt;/button&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/nav&gt; ); } } export default Nav; </code></pre> <p><strong>Note:</strong> Open up your terminal and install <code>react-router</code> like so: <code>npm install react-router@3.0.0 --save</code>. At the time of this writing, <code>react-router</code> is in 4.0 alpha, so you can explore its features.</p> <p>The <code>Link</code> Component from <code>react-router</code> enables seamless client-side transition between routes without any page reload.</p> <h2>Build the CelebrityJokes and FoodJokes Component</h2> <p>By default, these two components will look similar in functionalities. They both display data from different endpoints. Let's start with the <code>FoodJokes</code> component.</p> <pre><code class="js"> import React, { Component } from 'react'; import { Link } from 'react-router'; import Nav from './Nav'; import { getFoodData } from '../utils/chucknorris-api'; class FoodJokes extends Component { constructor() { super() this.state = { jokes: [] }; } getFoodJokes() { getFoodData().then((jokes) =&gt; { this.setState({ jokes }); }); } componentDidMount() { this.getFoodJokes(); } render() { const { jokes } = this.state; return ( &lt;div&gt; &lt;Nav /&gt; &lt;h3 className="text-center"&gt;Chuck Norris Food Jokes&lt;/h3&gt; &lt;hr/&gt; { jokes.map((joke, index) =&gt; ( &lt;div className="col-sm-6" key={index}&gt; &lt;div className="panel panel-primary"&gt; &lt;div className="panel-heading"&gt; &lt;h3 className="panel-title"&gt; &lt;span className="btn"&gt;#{ joke.id }&lt;/span&gt;&lt;/h3&gt; &lt;/div&gt; &lt;div className="panel-body"&gt; &lt;p&gt; { joke.joke } &lt;/p&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; ))} &lt;div className="col-sm-12"&gt; &lt;div className="jumbotron text-center"&gt; &lt;h2&gt;Get Access to Celebrity Jokes By Logging In&lt;/h2&gt; &lt;/div&gt; &lt;/div&gt; &lt;div className="col-sm-12"&gt; &lt;div className="jumbotron text-center"&gt; &lt;h2&gt;View Celebrity Jokes&lt;/h2&gt; &lt;Link className="btn btn-lg btn-success" to='/special'&gt; Celebrity Jokes &lt;/Link&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; ); } } export default FoodJokes; </code></pre> <p><em>FoodJokes.js</em></p> <blockquote><p><strong>Note:</strong> Learn why I use <a href="http://cheng.logdown.com/posts/2016/03/26/683329"><code>super()</code> in the class constructor</a>.</p></blockquote> <p>Let's analyze the code above. The <code>FoodJoke</code> component is pulling data from an API, so it needs a way of holding that data. That's where <code>state</code> comes in. In <strong>ReactJS</strong>, you can use <code>props</code> to pass data around and use <code>state</code> to hold/manage that data.</p> <p>In the constructor, we define the initial state as seen in the code below:</p> <pre><code class="js">... constructor() { super() this.state = { jokes: [] }; } ... </code></pre> <p>In the <code>getFoodJokes</code> method, we call the <code>getFoodData</code> method we exported from the <code>chucknorris-api.js</code> helper file and set state as seen below:</p> <pre><code class="js">... getFoodJokes() { getFoodData().then((jokes) =&gt; { this.setState({ jokes }); }); } ... </code></pre> <p>Now, we took advantage of one of the <strong>ReactJS</strong> lifecycle hooks, <code>componentDidMount</code>. Whatever is defined in this method is applied immediately after a component is mounted on the browser screen. So, we invoked the <code>getFoodJokes</code> method in the hook as seen below:</p> <pre><code class="js">... componentDidMount() { this.getFoodJokes(); } ... </code></pre> <p>All we are trying to do is tell <strong>ReactJS</strong> to load the data from the API immediately the <code>FoodJokes</code> component gets rendered.</p> <p>Finally, we rendered the component with the <strong>ReactJS</strong> <code>render</code> method. This is the method that does the actual rendering on the screen. As seen in the code below, we extracted the loaded jokes from the state into a <code>jokes</code> constant.</p> <p>We looped through the <code>jokes</code> constant which is now an array to display the contents on the screen.</p> <p><strong>Note:</strong> In <strong>ReactJS</strong>, when you loop through some form of data, you have to provide the <code>key</code> property and make sure it has a unique value, else an error will be thrown!</p> <pre><code class="js">... const { jokes } = this.state; ... { jokes.map((joke, index) =&gt; ( &lt;div className="col-sm-6" key={index}&gt; &lt;div className="panel panel-primary"&gt; &lt;div className="panel-heading"&gt; &lt;h3 className="panel-title"&gt; &lt;span className="btn"&gt;#{ joke.id }&lt;/span&gt;&lt;/h3&gt; &lt;/div&gt; &lt;div className="panel-body"&gt; &lt;p&gt; { joke.joke } &lt;/p&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; ))} ..... </code></pre> <p>Now, let's build the <code>CelebrityJokes</code> component in the same way:</p> <pre><code class="js"> import React, { Component } from 'react'; import { Link } from 'react-router'; import Nav from './Nav'; import { getCelebrityData } from '../utils/chucknorris-api'; class CelebrityJokes extends Component { constructor() { super(); this.state = { jokes: [] }; } getCelebrityJokes() { getCelebrityData().then((jokes) =&gt; { this.setState({ jokes }); }); } componentDidMount() { this.getCelebrityJokes(); } render() { const { jokes } = this.state; return ( &lt;div&gt; &lt;Nav /&gt; &lt;h3 className="text-center"&gt;Privileged Chuck Norris Celebrity Jokes&lt;/h3&gt; &lt;hr/&gt; { jokes.map((joke, index) =&gt; ( &lt;div className="col-sm-6" key={index}&gt; &lt;div className="panel panel-danger"&gt; &lt;div className="panel-heading"&gt; &lt;h3 className="panel-title"&gt;&lt;span className="btn"&gt;#{ joke.id }&lt;/span&gt;&lt;/h3&gt; &lt;/div&gt; &lt;div className="panel-body"&gt; &lt;p&gt; { joke.joke } &lt;/p&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; ))} &lt;div className="col-sm-12"&gt; &lt;div className="jumbotron text-center"&gt; &lt;h2&gt;View Food Jokes&lt;/h2&gt; &lt;Link className="btn btn-lg btn-success" to='/'&gt;Chuck Norris Food Jokes &lt;/Link&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; ); } } export default CelebrityJokes; </code></pre> <p><em>CelebrityJokes.js</em></p> <p>Grab your coffee at this point because you have successfully created the <code>Nav</code>, <code>CelebrityJokes</code>, and <code>FoodJokes</code> components. Whoop! Whoop!</p> <p>We need to take care of one more component so that our app can function. Can you guess? Yes, the root component!</p> <h2>Build the Root Component</h2> <p>This is the component where we get to define how routing should work in our application and also bind it to the <code>root</code> div that holds the whole app.</p> <p>Open up <code>index.js</code> and add code to it like so:</p> <pre><code class="js"> import React from 'react'; import ReactDOM from 'react-dom'; import CelebrityJokes from './components/CelebrityJokes'; import FoodJokes from './components/FoodJokes'; import { Router, Route, browserHistory } from 'react-router'; const Root = () =&gt; { return ( &lt;div className="container"&gt; &lt;Router history={browserHistory}&gt; &lt;Route path="/" component={FoodJokes}/&gt; &lt;Route path="/special" component={CelebrityJokes}/&gt; &lt;/Router&gt; &lt;/div&gt; ) } ReactDOM.render(&lt;Root /&gt;, document.getElementById('root')); </code></pre> <p><em>index.js</em></p> <p>You might quickly notice that we are not defining a class here, rather we just defined a <code>Root</code> function. <strong>ReactJS</strong> allows you to do that. Then, we imported the Router from <code>react-router</code>.</p> <pre><code class="js">... &lt;Router history={browserHistory}&gt; &lt;Route path="/" component={FoodJokes}/&gt; &lt;Route path="/special" component={CelebrityJokes}/&gt; &lt;/Router&gt; ... </code></pre> <p>The routing is simple. We have defined it to display the <code>FoodJokes</code> component once a user hits the <code>/</code> route. It displays the <code>CelebrityJokes</code> component once a user hits the <code>/special</code> route. <a href="https://medium.com/@dabit3/beginner-s-guide-to-react-router-53094349669#.7kmmo5n9a">The Beginner's guide to react router</a> will give you a better understanding of how routing works in <strong>ReactJS</strong>.</p> <p>This <code>ReactDOM.render(&lt;Root /&gt;, document.getElementById('root'));</code> renders the root component in the <code>root</code> div, which is the starting point of our <strong>ReactJS</strong> application.</p> <p>We imported all the required components like so:</p> <pre><code class="js">import React from 'react'; import ReactDOM from 'react-dom'; import CelebrityJokes from './components/CelebrityJokes'; import FoodJokes from './components/FoodJokes'; import { Router, Route, browserHistory } from 'react-router'; </code></pre> <p>Just a few things before we check our application in the browser:</p> <ul> <li>Open up <code>public/index.html</code> and add <a href="http://getbootstrap.com">bootstrap</a>. Now the content of the html file should look like this:</li> </ul> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="cp">&lt;!doctype html&gt;</span> <span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">&quot;en&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;head&gt;</span> <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">&quot;utf-8&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;viewport&quot;</span> <span class="na">content=</span><span class="s">&quot;width=device-width, initial-scale=1&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;shortcut icon&quot;</span> <span class="na">href=</span><span class="s">&quot;%PUBLIC_URL%/favicon.ico&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;link</span> <span class="na">href=</span><span class="s">&quot;https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css&quot;</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span><span class="nt">&gt;</span> <span class="c">&lt;!--</span> <span class="c"> Notice the use of %PUBLIC_URL% in the tag above.</span> <span class="c"> It will be replaced with the URL of the `public` folder during the build.</span> <span class="c"> Only files inside the `public` folder can be referenced from the HTML.</span> <span class="c"> Unlike &quot;/favicon.ico&quot; or &quot;favicon.ico&quot;, &quot;%PUBLIC_URL%/favicon.ico&quot; will</span> <span class="c"> work correctly both with client-side routing and a non-root public URL.</span> <span class="c"> Learn how to configure a non-root public URL by running `npm run build`.</span> <span class="c"> --&gt;</span> <span class="nt">&lt;title&gt;</span>React App<span class="nt">&lt;/title&gt;</span> <span class="nt">&lt;/head&gt;</span> <span class="nt">&lt;body&gt;</span> <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&quot;root&quot;</span><span class="nt">&gt;&lt;/div&gt;</span> <span class="c">&lt;!--</span> <span class="c"> This HTML file is a template.</span> <span class="c"> If you open it directly in the browser, you will see an empty page.</span> <span class="c"> You can add webfonts, meta tags, or analytics to this file.</span> <span class="c"> The build step will place the bundled scripts into the &lt;body&gt; tag.</span> <span class="c"> To begin the development, run `npm start`.</span> <span class="c"> To create a production bundle, use `npm run build`.</span> <span class="c"> --&gt;</span> <span class="nt">&lt;/body&gt;</span> <span class="nt">&lt;/html&gt;</span></code></pre></div> <ul> <li>Open up <code>App.css</code> and add this style like so:</li> </ul> <div class="highlight"><pre><code class="language-css" data-lang="css"><span class="nc">.navbar-right</span> <span class="p">{</span> <span class="k">margin-right</span><span class="o">:</span> <span class="m">0px</span> <span class="cp">!important</span><span class="p">}</span> <span class="nc">.log</span> <span class="p">{</span> <span class="k">margin</span><span class="o">:</span> <span class="m">5px</span> <span class="m">10px</span> <span class="m">0</span> <span class="m">0</span><span class="p">;</span> <span class="p">}</span></code></pre></div> <p>Feel free to check out your application in the browser. Right now, you should have something like this:</p> <p><img src="https://cdn.auth0.com/blog/react/homepage.png" alt="Homepage" /> <em>Homepage</em></p> <p><img src="https://cdn.auth0.com/blog/react/celebritypage.png" alt="Celebritypage" /> <em>CelebrityPage</em></p> <p><img src="https://cdn.auth0.com/blog/react/chuck_norris_world.gif" alt="Chuck Norris World Demo" /> <em>Current Application</em></p> <h2>Adding Authentication to Your ReactJS App</h2> <p>The majority of the apps we use on a daily basis have a means of authenticating users. I'll show you how to easily add authentication to our <strong>ReactJS</strong> application. We'll use <a href="https://auth0.com/">Auth0</a> as our authentication service.</p> <p>Auth0 allows us to issue <a href="https://jwt.io">JSON Web Tokens (JWTs)</a>. If you don't already have an Auth0 account, <a href="javascript:signup()">sign up</a> for a free one now.</p> <p>Log into your Auth0 <a href="https://manage.auth0.com">management dashboard</a> and navigate to the client app you wish to use. Get the <strong>Domain</strong>, <strong>Client Id</strong>, and <strong>Client Secret</strong> of this app. We'll need them soon.</p> <h3>Secure The Node API</h3> <p>We need to secure the API so that the celebrity endpoint will only be accessible to authenticated users. We can secure it easily with Auth0.</p> <p>Open up your <code>server.js</code> file and replace the <code>AUTH0_CLIENT_ID</code> and <code>AUTH0_CLIENT_SECRET</code> variables with your <code>client id</code> and <code>client secret</code> respectively. Then add the <code>authCheck</code> middleware to the celebrity endpoint like so:</p> <pre><code class="js"> ... const authCheck = jwt({ secret: 'AUTH0_CLIENT_SECRET', audience: 'AUTH0_CLIENT_ID ' }); .... app.get('/api/jokes/celebrity', authCheck, (req,res)=&gt;{ let CelebrityJokes = [ { id: 88881, joke: 'As President Roosevelt said: "We have nothing to fear but fear itself. And Chuck Norris."' }, { id: 88882, joke: "Chuck Norris only let's Charlie Sheen think he is winning. Chuck won a long time ago." }, { id: 88883, joke: 'Everything King Midas touches turnes to gold. Everything Chuck Norris touches turns up dead.' }, { id: 88884, joke: 'Each time you rate this, Chuck Norris hits Obama with Charlie Sheen and says, "Who is winning now?!"' }, { id: 88885, joke: "For Charlie Sheen winning is just wishful thinking. For Chuck Norris it's a way of life." }, { id: 88886, joke: "Hellen Keller's favorite color is Chuck Norris." } ]; res.json(CelebrityJokes); }) app.listen(3333); console.log('Listening on localhost:3333'); </code></pre> <p><strong>Note:</strong> You should load these values from environment variables for security reasons. No one should have access to your Auth0 secret.</p> <p>Try accessing the <code>http://localhost:3333/api/jokes/celebrity</code> endpoint again from Postman. You should be denied access like so:</p> <p><img src="https://cdn.auth0.com/blog/react/unauthorized.png" alt="Unauthorized Access" /> <em>Unauthorized Access</em></p> <p>Next, let's add authentication to our front-end.</p> <h3>Adding Authentication to our ReactJS Front-end</h3> <p>We'll create an authentication service to handle everything about authentication in our app. Go ahead and create an <code>AuthService.js</code> file inside the <code>utils</code> directory.</p> <p>Before we add code, you need to install <code>jwt-decode</code> and <code>auth0-lock</code> node packages like so:</p> <pre><code class="bash"> npm install jwt-decode auth0-lock --save </code></pre> <p>Open up the <code>AuthService.js</code> file and add code to it like so:</p> <pre><code class="js"> import decode from 'jwt-decode'; import { browserHistory } from 'react-router'; import Auth0Lock from 'auth0-lock'; const ID_TOKEN_KEY = 'id_token'; const lock = new Auth0Lock('AUTH0_CLIENT_ID', 'AUTH0_DOMAIN', { auth: { redirectUrl: `${window.location.origin}`, responseType: 'token' } } ); lock.on('authenticated', authResult =&gt; { setIdToken(authResult.idToken); browserHistory.push('/special'); }); export function login(options) { lock.show(options); return { hide() { lock.hide(); } } } export function logout() { clearIdToken(); browserHistory.replace('/'); } export function requireAuth(nextState, replace) { if (!isLoggedIn()) { replace({pathname: '/'}); } } function setIdToken(idToken) { localStorage.setItem(ID_TOKEN_KEY, idToken); } function getIdToken() { return localStorage.getItem(ID_TOKEN_KEY); } function clearIdToken() { localStorage.removeItem(ID_TOKEN_KEY); } export function isLoggedIn() { const idToken = getIdToken(); return !!idToken &amp;&amp; !isTokenExpired(idToken); } function getTokenExpirationDate(encodedToken) { const token = decode(encodedToken); if (!token.exp) { return null; } const date = new Date(0); date.setUTCSeconds(token.exp); return date; } function isTokenExpired(token) { const expirationDate = getTokenExpirationDate(token); return expirationDate &lt; new Date(); } </code></pre> <p>In the code above, we created an instance of <code>Auth0 Lock</code> and passed in our credentials. We also listened on the <code>authenticated</code> event. It grabs the <code>id_token</code> returned from the Auth0 server and stores it in localStorage. The <code>logout</code> function deletes the token and directs us back to the homepage.</p> <p>We also checked whether the token has expired via the <code>getTokenExpirationDate</code> and <code>isTokenExpired</code> methods. The <code>isLoggedIn</code> method returns <code>true</code> or <code>false</code> based on the presence and validity of a user <code>id_token</code>.</p> <p>Finally, we implemented a middleware, the <code>requireAuth</code> method. We'll use this method to protect the <code>/special</code> route from being accessed for non-loggedIn users.</p> <p>Let's go update the <code>Nav</code> component to hide/show the <code>login</code> and <code>logout</code> buttons based on the user's authentication status.</p> <p>Now, your <code>Nav</code> component should look like this:</p> <pre><code class="js"> import React, { Component } from 'react'; import { Link } from 'react-router'; import { login, logout, isLoggedIn } from '../utils/AuthService'; import '../App.css'; class Nav extends Component { render() { return ( &lt;nav className="navbar navbar-default"&gt; &lt;div className="navbar-header"&gt; &lt;Link className="navbar-brand" to="/"&gt;Chuck Norris World&lt;/Link&gt; &lt;/div&gt; &lt;ul className="nav navbar-nav"&gt; &lt;li&gt; &lt;Link to="/"&gt;Food Jokes&lt;/Link&gt; &lt;/li&gt; &lt;li&gt; { ( isLoggedIn() ) ? &lt;Link to="/special"&gt;Celebrity Jokes&lt;/Link&gt; : '' } &lt;/li&gt; &lt;/ul&gt; &lt;ul className="nav navbar-nav navbar-right"&gt; &lt;li&gt; { (isLoggedIn()) ? ( &lt;button className="btn btn-danger log" onClick={() =&gt; logout()}&gt;Log out &lt;/button&gt; ) : ( &lt;button className="btn btn-info log" onClick={() =&gt; login()}&gt;Log In&lt;/button&gt; ) } &lt;/li&gt; &lt;/ul&gt; &lt;/nav&gt; ); } } export default Nav; </code></pre> <p><em>Nav.js</em></p> <blockquote><p><strong>Note:</strong> We used an arrow function to wrap and execute the onClick handlers like so: <code>{() =&gt; login()}</code> . Check out how to <a href="https://medium.com/@machnicki/handle-events-in-react-with-arrow-functions-ede88184bbb#.ekwwbituw">handle events in react with arrow function</a> to understand why we used arrow functions.</p></blockquote> <p>We imported <code>login</code>, <code>logout</code> and <code>isLoggedIn</code> functions from the <code>AuthService</code>. Then, we attached the <code>login()</code> and <code>logout()</code> functions to the <code>login</code> and <code>logout</code> buttons respectively.</p> <p>We also hid the <code>/special</code> link by checking the authentication status of the user via the <code>isLoggedIn()</code> function.</p> <p>Open up the <code>FoodJokes</code> Component and modify it like so:</p> <pre><code class="js"> import React, { Component } from 'react'; import { Link } from 'react-router'; import Nav from './Nav'; import { isLoggedIn } from '../utils/AuthService'; import { getFoodData } from '../utils/chucknorris-api'; class FoodJokes extends Component { constructor() { super() this.state = { jokes: [] }; } getFoodJokes() { getFoodData().then((jokes) =&gt; { this.setState({ jokes }); }); } componentDidMount() { this.getFoodJokes(); } render() { const { jokes } = this.state; return ( &lt;div&gt; &lt;Nav /&gt; &lt;h3 className="text-center"&gt;Chuck Norris Food Jokes&lt;/h3&gt; &lt;hr/&gt; { jokes.map((joke, index) =&gt; ( &lt;div className="col-sm-6" key={index}&gt; &lt;div className="panel panel-primary"&gt; &lt;div className="panel-heading"&gt; &lt;h3 className="panel-title"&gt; &lt;span className="btn"&gt;#{ joke.id }&lt;/span&gt;&lt;/h3&gt; &lt;/div&gt; &lt;div className="panel-body"&gt; &lt;p&gt; { joke.joke } &lt;/p&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; ))} &lt;div className="col-sm-12"&gt; { isLoggedIn() ? &lt;div className="jumbotron text-center"&gt; &lt;h2&gt;View Celebrity Jokes&lt;/h2&gt; &lt;Link className="btn btn-lg btn-success" to='/special'&gt; Celebrity Jokes &lt;/Link&gt; &lt;/div&gt; : &lt;div className="jumbotron text-center"&gt;&lt;h2&gt;Get Access to Celebrity Jokes By Logging In&lt;/h2&gt;&lt;/div&gt; } &lt;/div&gt; &lt;/div&gt; ); } } export default FoodJokes; </code></pre> <p>We are enabling the link to celebrity jokes based on the login status of a user via the <code>isLoggedIn()</code> method.</p> <h3>Add some values to Auth0 Dashboard</h3> <p>Just before you try to log in or sign up, head over to your <a href="https://manage.auth0.com/#/">Auth0 dashboard</a> and add <code>http://localhost:3000</code> to the <strong>Allowed Callback URLs</strong> and <strong>Allowed Origins (CORS)</strong>.</p> <p><img src="https://cdn.auth0.com/blog/react/allowedcallback" alt="Allowed Callback" /> <em>Allowed Callback Urls</em></p> <p><img src="https://cdn.auth0.com/blog/react/allowedorigins.png" alt="Allowed Origins" /> <em>Allowed Origins</em></p> <h3>Secure The Special Route</h3> <p>We need to ensure that no one can go to the browser and just type <code>/special</code> to access the celebrity route.</p> <p>Open up <code>index.js</code> and add an <code>onEnter</code> prop with a value of <code>requireAuth</code> to the <code>/special</code> route like so:</p> <pre><code class="js">.... .... import { requireAuth } from './utils/AuthService'; const Root = () =&gt; { return ( &lt;div className="container"&gt; &lt;Router history={browserHistory}&gt; &lt;Route path="/" component={FoodJokes}/&gt; &lt;Route path="/special" component={CelebrityJokes} onEnter={requireAuth} /&gt; &lt;/Router&gt; &lt;/div&gt; ) } </code></pre> <p><em>index.js</em></p> <p>Now, try to log in.</p> <p><img src="https://cdn.auth0.com/blog/react/login.png" alt="Lock Login Widget" /> <em>Lock Login Widget</em></p> <p><img src="https://cdn.auth0.com/blog/react/loggedinbutunauthorized" alt="Logged In and Unauthorized to see the celebrity content" /> <em>Logged In, but unauthorized to see the celebrity content</em></p> <p>Oops! We have successfully logged in but the content of the celebrity jokes is not showing up and in the console, we are getting a <code>401 Unauthorized</code> error. Why?</p> <p>It's simple! We secured our endpoint earlier, but right now we are not passing the JWT to the backend yet. We need to send the JWT along with our request as a header to enable the secured endpoint's recognition of the logged-in user.</p> <h3>Updating the AuthService &amp; ChuckNorris API helper</h3> <p>Open up <code>utils/AuthService.js</code> and make the <code>getIdToken()</code> function exportable like so:</p> <pre><code class="js">... ... export function getIdToken() { return localStorage.getItem(ID_TOKEN_KEY); } ... </code></pre> <p>Adding an <code>export</code> just before the function makes it exportable.</p> <p>Go ahead and open up the <code>utils/chucknorris-api.js</code> file. We will tweak the <code>getCelebrityData</code> function a bit. Currently, it initiates a <code>GET</code> request only to fetch data from the API.</p> <p>Now, we will pass an option to send an <code>Authorization</code> header with a Bearer token along with the <code>GET</code> request like so:</p> <pre><code class="js"> function getCelebrityData() { const url = `${BASE_URL}/api/jokes/celebrity`; return axios.get(url, { headers: { Authorization: `Bearer ${getIdToken()}` }}).then(response =&gt; response.data); } </code></pre> <p>The <code>/api/jokes/celebrity</code> endpoint will receive the token in the header and validate the user. If it is valid, the content will be provided to us.</p> <p>Now, try to log in again.</p> <p><img src="https://cdn.auth0.com/blog/react/working_chuck_norris_app.gif" alt="Working Chuck Norris World App" /> <em>Working Chuck Norris World App</em></p> <p>Everything is working fine. Pat yourself on the back. You have just successfully built a <strong>ReactJS</strong> app and added authentication to it!</p> <h2>Conclusion</h2> <p><strong>ReactJS</strong> is an awesome front-end library to employ in building your user interfaces. It takes advantage of the Virtual DOM, it is fast and it has a bubbling community. There are several React plugins/addons that the community provides to allow you do almost anything in <strong>ReactJS</strong>.</p> <p>In addition, Auth0 can help secure your <strong>ReactJS</strong> apps with more than just username-password authentication. It provides features like <a href="https://auth0.com/docs/multifactor-authentication">multifactor auth</a>, <a href="https://auth0.com/docs/anomaly-detection">anomaly detection</a>, <a href="https://auth0.com/docs/identityproviders">enterprise federation</a>, <a href="https://auth0.com/docs/sso">single sign on (SSO)</a>, and more. <a href="javascript:signup()">Sign up</a> today so you can focus on building features unique to your app.</p> Introducing Auth0 Hooks 2017-02-17T08:30:00+00:00 https://auth0.com/blog/introducing-auth0-hooks/ Tomasz Janczuk https://twitter.com/tjanczuk?lang=en <p>Auth0 Hooks are a new extensibility mechanism in Auth0 that allows you to customize the behavior of our platform using Node.js.</p> <hr /> <h2>Developers love code and extensibility</h2> <p>Customization flexibility has always been an integral part of the Auth0 platform. Until now, you could use <a href="https://auth0.com/docs/rules">Auth0 Rules</a> to execute arbitrary Node.js code during an authorization transaction. Today, we are introducing <a href="https://auth0.com/docs/auth0-hooks">Auth0 Hooks</a>, a new and improved mechanism to extend the Auth0 platform using code.</p> <p><img src="https://cdn.auth0.com/hooks/assets/wt-editor-auth0-hooks.png" alt="Auth0 Hooks in Webtask Editor" /></p> <h2>Better developer experience</h2> <p>While Auth0 Hooks are building on the same underlying <a href="https://webtask.io">Webtask</a> technology we have developed to run Auth0 Rules, several aspects of the developer experience are improved:</p> <ul> <li>Using the <a href="https://auth0.com/docs/auth0-hooks/dashboard">management dashboard</a> you can create, move in and out of production, and edit hooks for selected extensibility points in the Auth0 platform.</li> </ul> <p><img src="https://cdn.auth0.com/hooks/assets/manage-hooks.png" alt="Auth0 Hooks dashboard" /></p> <ul> <li>You edit hooks in the Webtask Editor, which offers a much richer featureset compared to the experience you are used to with Auth0 rules.</li> <li>Syntax completion allows you write the code faster without referring to documentation.</li> <li>Integrated secret management improves the security of your code by providing a mechanism to securely store secrets while making them conveniently available in code.</li> <li>Integrated runner allows you to test your code without leaving the webtask editor.</li> <li>Real-time logs simplify debugging by streaming the output generated by your code.</li> <li>GitHub integration allows you synchronize your hook with code stored in a github repository. Updating your hook is as simple as pushing to GitHub.</li> <li>Using the <a href="https://auth0.com/docs/auth0-hooks/cli">Auth0 CLI</a> you can scaffold, create, activate, and deactive hooks from the command line.</li> </ul> <h2>What can you do today</h2> <p>The initial release of Auth0 Hooks supports customizing the behavior of Auth0 at three new extensibility points:</p> <ul> <li><a href="https://auth0.com/docs/auth0-hooks/extensibility-points/client-credentials-exchange">Client Credentials Exchange</a> allows you to change the scopes and add custom claims to issued access tokens.</li> <li><a href="https://auth0.com/docs/auth0-hooks/extensibility-points/pre-user-registration">Pre User Registration</a> allows you to intercept creation of a new database user to enforce custom password policy, or employ application specific logic to prevent the signup.</li> <li><a href="https://auth0.com/docs/auth0-hooks/extensibility-points/post-user-registration">Post User Registration</a> allows you to perform any actions as a result of a succcessful creation of a new database user, e.g. send a message to Slack, or create a record in your CRM system.</li> </ul> <p>This is just the beginning. We are going to be adding many more extensibility points in the Auth0 platform using the Auth0 Hooks mechanism in the future.</p> <h2>Auth0 Hooks vs Auth0 Rules</h2> <p>Introduction of Auth0 Hooks does not affect any existing Auth0 Rules. Your rules continue to work unchanged.</p> <p>Auth0 Hooks provide a foundation for a new extensibility mechanism in Auth0. All future extensibility points in the platfrom will build on top of Auth0 Hooks. We are also planning to add support in Auth0 Hooks for the same things you use Auth0 Rules for today.</p> <h2>Differences with Auth0 Rules</h2> <p>If you have been using Auth0 Rules before, these are some of the key differences in the development experience when moving on to Auth0 Hooks:</p> <ul> <li>In Auth0 Rules, you are editing code on the Auth0 management dashboard. When using Auth0 Hooks, you edit code in the Webtask Editor.</li> <li>When using Auth0 Rules, you are specifying rule configuration common to all rules on the Auth0 management dashboard. Auth0 Hooks allow you to specify secret configuration directly in the Webtask Editor, and separately for each hook.</li> <li>When developing Auth0 Rules, you can dry run a rule from within the Auth0 management dashboard. Auth0 Hooks can be tested from within the Webtask Editor using the integrated runner and access to real-time logs.</li> <li>There is no command line tool to manipulate Auth0 Rules. Auth0 Hooks come with the <a href="https://auth0.com/docs/auth0-hooks/cli">Auth0 CLI</a> tool, and can also be manipulated using the lower level <a href="https://webtask.io/cli">Webtask CLI</a> tool.</li> <li>Auth0 management HTTP APIs offer a way to manipulate Auth0 Rules using any HTTP client. Auth0 Hooks are managed using <a href="https://webtask.io/docs/101">Webtask management APIs</a>.</li> </ul> <h2>Learn more</h2> <p>Check out the <a href="https://auth0.com/docs/auth0-hooks">Auth0 Hooks documentation</a> or head over directly to the <a href="https://manage.auth0.com/#/hooks">Auth0 Hooks management dashboard</a> to create your first hook.</p> Announcing the Guardian Whitelabel SDK 2017-02-16T08:30:00+00:00 https://auth0.com/blog/announcing-guardian-whitelabel-sdk/ Prosper Otemuyiwa http://twitter.com/unicodeveloper?lang=en <p>On November 23, 2016, we tagged the first release of <a href="https://github.com/auth0/Guardian.swift">Guardian for iOS</a> and <a href="https://github.com/auth0/Guardian.Android">Android</a>, a whitelabel SDK to help users, developers, and organizations build their own authenticator and Guardian-like applications. Read on to find out how it works and how you can use it in your projects!</p> <blockquote class="tweet-quote"> <a href="https://twitter.com/intent/tweet?text=&quot;The Guardian Whitelabel SDK helps you build your own authenticator and Guardian-like applications.&quot; via @auth0 http://auth0.com/blog/announcing-guardian-whitelabel-sdk/"> <p>"The Guardian Whitelabel SDK helps you build your own authenticator and Guardian-like applications."</p> <p class="tweet-link">TWEET THIS <img src="https://cdn.auth0.com/blog/resources/twitter.svg"></p> </a> </blockquote> <script> $(function() { $('.tweet-quote').on('click', function() { metricsLib.track('blog:share:twitter_quote'); }); }); </script> <h2>White-label Multifactor</h2> <p>You can use the Guardian Mobile SDKs - available for <a href="https://auth0.com/docs/multifactor-authentication/developer/libraries/ios">iOS</a> and <a href="https://auth0.com/docs/multifactor-authentication/developer/libraries/android">Android</a> to build your own white-label multifactor authentication application with complete control over the branding and look-and-feel.</p> <p><img src="https://auth0.com/pages/guardian/assets/sdk.png" alt="White label Multifactor" /></p> <h2>Guardian</h2> <p><a href="https://auth0.com/docs/multifactor-authentication/guardian">Guardian</a> is Auth0's multifactor authentication solution that provides a simple and secure way to implement Multifactor Authentication. It also supports <a href="https://auth0.com/docs/multifactor-authentication/administrator/push-notifications">push notifications</a>, removing the need for one time pass codes for a truly frictionless multifactor experience.</p> <p><video autoplay loop width="600"> <source src="https://cdn.auth0.com/blog/guardian/guardian-2.m4v"/> </video></p> <p>The Guardian app can be downloaded from the <a href="https://itunes.apple.com/us/app/auth0-guardian/id1093447833">App Store</a> or from <a href="https://play.google.com/store/apps/details?id=com.auth0.guardian">Google Play</a>.</p> <p>With the Guardian SDK(<a href="https://github.com/auth0/Guardian.swift">iOS</a> and <a href="https://github.com/auth0/Guardian.Android">Android</a>), you can build your own custom mobile applications that works like <em>Guardian</em> or integrate some Guardian functionalities, such as receiving <em>Push Notifications</em> in your existing mobile applications.</p> <p>A typical scenario could be: While building a banking app, you can make use of the Guardian SDK in your existing mobile app to receive and confirm push notifications when someone performs an ATM transaction.</p> <h2>How can I use it?</h2> <p>Take a look at the <a href="https://auth0.com/docs/multifactor-authentication/developer/libraries/ios">iOs</a> and <a href="https://auth0.com/docs/multifactor-authentication/developer/libraries/android">Android</a> docs. You can also just enable push notifications and SMS by toggling the buttons below from the Auth0 <a href="management.auth0.com">dashboard</a>.</p> <p><img src="https://cdn.auth0.com/blog/guardian/enable.png" alt="Enable Push Notifications and SMS" /> <em>Push Notifications and SMS</em></p> <h2>Conclusion</h2> <p>The Guardian Mobile SDK opens up a myriad of opportunities for developers and organizations wishing to leverage an already secure, tested and existing solution for building and enhancing their mobile apps. Try it today!</p> Angular Testing In Depth: HTTP Services 2017-02-15T08:23:00+00:00 https://auth0.com/blog/angular-testing-in-depth-http-services/ Gábor Soós https://twitter.com/blacksonic86 <div class="alert alert-info alert-icon"> <i class="icon-budicon-664"></i> <strong>Get the "Migrating an Angular 1 App to Angular 2 book" for Free.</strong> Spread the word and <a href="https://auth0.com/e-books/migrating-to-angular2">download it now!</a> </div> <p>When we write a web application, most of the time it has a backend. The most straightforward way to communicate with the backend is with HTTP requests. These requests are crucial for the application, so we need to test them. More importantly, these tests need to be isolated from the outside world. In this article I will show you how to test your requests properly and elegantly.</p> <p>This article is the second part of a series in which I share my experiences testing different building blocks of an Angular application. It relies heavily on Dependency Injection based testing and it is recommended that you read <a href="https://auth0.com/blog/angular-2-testing-in-depth-services/">the first part</a> if you are not familiar with the concepts.</p> <ul> <li><a href="https://auth0.com/blog/angular-2-testing-in-depth-services/">Services</a></li> <li>HTTP Services (this article)</li> <li>Components</li> <li>Pipes</li> <li>Routing</li> </ul> <h3>Testing our first request</h3> <p align="center"> <img src="https://github.com/blacksonic/articles/raw/master/img/angular2-testing-http-services/github-logo.png" alt="Angular Testing Framework"/> </p> <p>To get started we will test a basic request, the GET request. It will call a parameterized url without a body or additional headers. The <a href="https://developer.github.com/v3/">Github API</a> has an endpoint for retrieving public profile information about users. The profile information is returned in JSON format.</p> <pre><code class="typescript">import { Injectable } from '@angular/core'; import { Http, Response } from '@angular/http'; import 'rxjs/add/operator/map'; @Injectable() export class GithubService { constructor(private http: Http) {} getProfile(userName: string) { return this.http .get(`https://api.github.com/users/${userName}`) .map((response: Response) =&gt; response.json()); } } </code></pre> <p>The <code>getProfile</code> method sends a GET request to the API and returns the response. Every request made with the <code>HttpModule</code> returns an <code>Observable.</code> The returned value will always be a <code>Response</code> object, which can return the response body. With the help of the <code>json</code> or <code>text</code> method we can transform the value of the Observable.</p> <p>The first thing we have to do is to set up the test dependencies. The <code>Http</code> dependency is required. If we don't provide it, we will get this error message: <code>No provider for Http!</code>.</p> <pre><code class="typescript">beforeEach(() =&gt; { TestBed.configureTestingModule({ providers: [GithubService], imports: [HttpModule] }); }); </code></pre> <p>The problem with the real <code>HttpModule</code> is that we will end up sending real HTTP requests. It is an absolutely terrible idea to do this with unit tests, because it breaks the test's isolation from the outside world. Under no circumstances will the result of the test be guaranteed. For example, the network can go down and our well-crafted tests will no longer work.</p> <p>Instead, Angular has a built-in way to fake HTTP requests.</p> <pre><code class="typescript">import { MockBackend, MockConnection } from '@angular/http/testing'; import { Http, BaseRequestOptions, Response, ResponseOptions, RequestMethod } from '@angular/http'; ... beforeEach(() =&gt; { TestBed.configureTestingModule({ providers: [ GithubService, MockBackend, BaseRequestOptions, { provide: Http, useFactory: (mockBackend: MockBackend, defaultOptions: RequestOptions) =&gt; { return new Http(mockBackend, defaultOptions); }, deps: [MockBackend, BaseRequestOptions] } ] }); }); </code></pre> <p>Instead of providing <code>Http</code> as a module, it is better to use the factory provider and pass the <code>MockBackend</code> instance to the <code>Http</code> constructor. This way the fake backend captures every request and can respond accordingly.</p> <p>Before writing the first test it is also important to get an instance of the <code>MockBackend,</code> because without it we won't be able to respond to requests.</p> <pre><code class="typescript">beforeEach(inject([GithubService, MockBackend], (github, mockBackend) =&gt; { subject = github; backend = mockBackend; })); </code></pre> <p>Let's write the first test that checks the result of the request.</p> <pre><code class="typescript">it('should get profile data of user', (done) =&gt; { let profileInfo = { login: 'sonic', id: 325, name: 'Tester' }; backend.connections.subscribe((connection: MockConnection) =&gt; { let options = new ResponseOptions({ body: profileInfo }); connection.mockRespond(new Response(options)); }); subject.getProfile('blacksonic').subscribe((response) =&gt; { expect(response).toEqual(profileInfo); done(); }); }); </code></pre> <p>Requests made are available through the <code>connections</code> property of the fake backend as an <code>Observable.</code> When it receives the request through the <code>subscribe</code> method we can respond with a JSON object.</p> <p>In our example only the response body is set. In addition, you can set the status and the headers of the request.</p> <p>Another new element is the <code>done</code> callback that is passed into the test function. It is needed when writing asynchronous tests. This way the test doesn't end when the execution of the function ends. It will wait until the <code>done</code> callback is called. Of course, there is a timeout for hanging tests that don't call this <code>done</code> method within a given interval.</p> <p>HTTP requests are asynchronous by nature, but the fake backend we use responds to them synchronously (it calls the <code>subscribe</code> method synchronously). You may wonder what makes the test asynchronous, then.</p> <p>The answer is false positive tests. If we comment out the response to the request, the test will still pass, even though we have an assertion. The problem here is that the <code>subscribe</code> callback never gets executed if we don't respond to the request.</p> <pre><code class="typescript">it('should get profile data of user', () =&gt; { // backend.connections.subscribe... subject.getProfile('blacksonic').subscribe((response) =&gt; { expect(response).toEqual(profileInfo); }); }); </code></pre> <h3>Checking the request</h3> <p>Until now we haven't made any assertions for the request. For example, what was the called url, or what was the method of the request? To make the test more strict we have to check these parameters.</p> <pre><code class="typescript">backend.connections.subscribe((connection: MockConnection) =&gt; { expect(connection.request.url).toEqual('https://api.github.com/users/blacksonic'); expect(connection.request.method).toEqual(RequestMethod.Get); ... }); </code></pre> <p>The original <code>Request</code> object resides on the <code>MockConnection</code> object. With its <code>url</code> and <code>method</code> property, we can add the assertions easily.</p> <h3>Digging deeper</h3> <p>GET requests are good for retrieving data, but we'll make use of other HTTP verbs to send data. One example is POST. User authentication is a perfect fit for POST requests. When modifying data stored on the server we need to restrict access to it. This is usually done with a POST request on the login page.</p> <p align="center"> <img src="https://github.com/blacksonic/articles/raw/master/img/angular2-testing-http-services/auth0-logo.png" alt="Angular Testing Framework"/> </p> <p>Auth0 provides a good solution for handling user authentication. It has a feature to authenticate users based on username and password. To demonstrate how to test POST requests, we will send a request to the Auth0 API. We won't be using their recommended package here, because it would abstract out the actual request, but for real-world scenarios I would recommend using it.</p> <pre><code class="typescript">@Injectable() export class Auth0Service { constructor(private http: Http) {} login(username: string, password: string) { let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers }); return this.http .post( 'https://blacksonic.eu.auth0.com.auth0.com/usernamepassword/login', { username, password, client_id: 'YOUR_CLIENT_ID' }, options ) .map((response: Response) =&gt; response.text()); } } </code></pre> <p>The main difference between this example and the previous one is that here we are sending a JSON payload to the server and appending additional headers onto it. We don't have to manually <code>JSON.stringify</code> the payload --- the request methods will take care of it. The response will be in text format, so this time we don't have to convert anything to JSON.</p> <p>Let's look at the test to see how we can check every detail of the request.</p> <pre><code class="typescript">it('should be called with proper arguments', (done) =&gt; { backend.connections.subscribe((connection: MockConnection) =&gt; { expect(connection.request.url).toEqual('https://blacksonic.eu.auth0.com.auth0.com/usernamepassword/login'); expect(connection.request.method).toEqual(RequestMethod.Post); expect(connection.request.headers.get('Content-Type')).toEqual('application/json'); expect(connection.request.getBody()).toEqual(JSON.stringify( { username: 'blacksonic', password: 'secret', client_id: 'YOUR_CLIENT_ID' }, null, 2 )); ... }); subject.login('blacksonic', 'secret').subscribe((response) =&gt; { expect(response).toEqual('&lt;form /&gt;'); done(); }); }); </code></pre> <p>The headers are also available on the <code>Request</code> object and can be checked one by one. The payload can be retrieved with the <code>getBody</code> method. This method always returns the body converted to a string, which will we see in the network traffic. When we send JSON it will contain the output of the <code>JSON.stringify</code> method: printed with spaces and an indentation of two.</p> <h3>Refactoring</h3> <p>The previous setup works, but it has multiple problems.</p> <ul> <li>For every service we test, the provider configuration will be exactly the same.</li> <li>The subscription to the outgoing connection responds the same immediately, regardless of the url.</li> <li>The assertions are verbose and hard to read.</li> </ul> <p>Those who have tested their HTTP services in Angularjs may remember how simple the setup was for those tests. Angularjs provided convenient methods for setting expectations on requests.</p> <p>Angular doesn't have those built-in functionalities, but very similar ones are present in the <a href="https://github.com/blacksonic/ngx-http-test">ngx-http-test</a> library.</p> <p>It can solve the problems mentioned earlier. Let's look at the test with the library for the Github profile fetch.</p> <pre><code class="typescript">... import { FakeBackend } from 'ngx-http-test'; describe('GithubServiceRefactored', () =&gt; { ... beforeEach(() =&gt; { TestBed.configureTestingModule({ providers: [ GithubService, FakeBackend.getProviders() ] }); }); beforeEach(inject([GithubService, FakeBackend], (github, fakeBackend) =&gt; { subject = github; backend = fakeBackend; })); it('should get profile data of user', (done) =&gt; { backend .expectGet('https://api.github.com/users/blacksonic') .respond(profileInfo); subject.getProfile('blacksonic').subscribe((response) =&gt; { expect(response).toEqual(profileInfo); done(); }); }); }); </code></pre> <p>The setup becomes a function call to <code>FakeBackend.getProviders()</code>. Setting the expectation hides the subscription and gives more readable methods like <code>expectGET</code>.</p> <p>The login test also becomes less verbose.</p> <pre><code class="typescript">it('should be called with proper arguments', (done) =&gt; { backend.expectPost( 'https://blacksonic.eu.auth0.com.auth0.com/usernamepassword/login', { username: 'blacksonic', password: 'secret', client_id: 'YOUR_CLIENT_ID' }, { 'Content-Type': 'application/json' } ).respond(responseForm); subject.login('blacksonic', 'secret').subscribe((response) =&gt; { expect(response).toEqual('&lt;/form&gt;'); done(); }); }); </code></pre> <h3>Conclusion: What we've learned about Angular HTTP testing</h3> <p>In this tutorial, we managed to:</p> <ul> <li>setup tests and fake an HTTP backend</li> <li>write assertions for requests</li> <li>refactor the tests to be more readable</li> </ul> <p>Angular has the tools to test HTTP requests, but still lacks the readable assertion methods that were present in Angularjs. Until such methods are implemented, the <a href="https://github.com/blacksonic/ngx-http-test">ngx-http-test</a> library can be used.</p> <p>To see the tests in action check out <a href="https://github.com/blacksonic/angular-testing-ground" title="Angular testing ground">this GitHub repository</a>.</p> Glossary of Modern JavaScript Concepts: Part 1 2017-02-14T08:30:00+00:00 https://auth0.com/blog/glossary-of-modern-javascript-concepts/ Kim Maida https://twitter.com/KimMaida <p><strong>TL;DR:</strong> In the first part of the Glossary of Modern JS Concepts series, we'll gain an understanding of <em>functional programming</em>, <em>reactive programming</em>, and <em>functional reactive programming</em>. To do so, we'll learn about purity, statefulness and statelessness, immutability and mutability, imperative and declarative programming, higher-order functions, observables, and the FP, RP, and FRP paradigms.</p> <hr /> <h2>Introduction</h2> <p>Modern JavaScript has experienced massive proliferation over recent years and shows no signs of slowing. Numerous concepts appearing in JS blogs and documentation are still unfamiliar to many front-end developers. In this post series, we'll learn intermediate and advanced concepts in the current front-end programming landscape and explore how they apply to modern JavaScript.</p> <hr /> <h2>Concepts</h2> <p>In this article, we'll address concepts that are crucial to understanding <strong>functional programming, reactive programming, and functional reactive programming and their use with JavaScript</strong>.</p> <p>You can jump straight into each concept here, or continue reading to learn about them in order.</p> <ul> <li><a href="#purity" target="_self">Purity: Pure Functions, Impure Functions, Side Effects</a></li> <li><a href="#state" target="_self">State: Stateful and Stateless</a></li> <li><a href="#immutable-mutable" target="_self">Immutability and Mutability</a></li> <li><a href="#imperative-declarative" target="_self">Imperative and Declarative Programming</a></li> <li><a href="#higher-order-functions" target="_self">Higher-order Functions</a></li> <li><a href="#functional-programming" target="_self">Functional Programming</a></li> <li><a href="#observables" target="_self">Observables: Hot and Cold</a></li> <li><a href="#reactive-programming" target="_self">Reactive Programming</a></li> <li><a href="#functional-reactive-programming" target="_self">Functional Reactive Programming</a></li> </ul> <hr /> <h2><span id="purity"></span>Purity: Pure Functions, Impure Functions, Side Effects</h2> <h3>Pure Functions</h3> <p>A <strong>pure function</strong>'s <em>return value</em> is determined only by its <em>input values</em> (arguments) with no side effects. When given the same argument, the result will always be the same. Here is an example:</p> <pre><code class="js">function half(x) { return x / 2; } </code></pre> <p>The <code>half(x)</code> function takes a number <code>x</code> and returns a value of half of <code>x</code>. If we pass an argument of <code>8</code> to this function, the function will always return <code>4</code>. When invoked, a pure function can be replaced by its result. For example, we could replace <code>half(8)</code> with <code>4</code> wherever used in our code with no change to the final outcome. This is called <a href="https://en.wikipedia.org/wiki/Referential_transparency"><em>referential transparency</em></a>.</p> <p>Pure functions only depend on what's passed to them. For example, a pure function cannot reference variables from a parent scope unless they are explicitly passed into the function as arguments. Even then, the function can <em>not modify</em> the parent scope.</p> <pre><code class="js">var someNum = 8; // this is NOT a pure function function impureHalf() { return someNum / 2; } </code></pre> <p>In summary:</p> <ul> <li>Pure functions must take arguments.</li> <li>The same input (arguments) will always produce the same output (return).</li> <li>Pure functions rely only on local state and do not mutate external state (<em>note:</em> <code>console.log</code> changes global state).</li> <li>Pure functions do not produce <a href="https://en.wikipedia.org/wiki/Side_effect_%28computer_science%29">side effects</a>.</li> <li>Pure functions cannot call impure functions.</li> </ul> <h3>Impure Functions</h3> <p>An <strong>impure function</strong> mutates state outside its scope. Any function that has <em>side effects</em> (see below) is impure. Procedural functions with no utilized return value are also impure.</p> <p>Consider the following examples:</p> <pre><code class="js">// impure function producing a side effect function showAlert() { alert('This is a side effect!'); } // impure function mutating external state var globalVal = 1; function incrementGlobalVal(x) { globalVal += x; } // impure function calling pure functions procedurally function proceduralFn() { const result1 = pureFnFirst(1); const result2 = pureFnLast(2); console.log(`Done with ${result1} and ${result2}!`); } // impure function that resembles a pure function, // but returns different results given the same inputs function getRandomRange(min, max) { return Math.random() * (max - min) + min; } </code></pre> <h3>Side Effects in JavaScript</h3> <p>When a function or expression modifies state outside its own context, the result is a <strong>side effect</strong>. Examples of side effects include making a call to an API, manipulating the DOM, raising an alert dialog, writing to a database, etc. If a function produces side effects, it is considered <em>impure</em>. Functions that cause side effects are less predictable and harder to test since they result in changes outside their local scope.</p> <h3>Purity Takeaways</h3> <p>Plenty of quality code consists of <em>impure</em> functions that procedurally invoke <em>pure</em> functions. This still produces advantages for testing and immutability. Referential transparency also enables <a href="https://www.interviewcake.com/concept/python/memoization"><em>memoization</em></a>: caching and storing function call results and <a href="https://www.sitepoint.com/implementing-memoization-in-javascript/">reusing the cached results</a> when the same inputs are used again. It can be a challenge to determine when functions are truly pure.</p> <p>To learn more about <strong>purity</strong>, check out the following resources:</p> <ul> <li><a href="https://toddmotto.com/pure-versus-impure-functions">Pure versus impure functions</a></li> <li><a href="https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976#.kt48h2bfa">Master the JavaScript Interview: What is a Pure Function?</a></li> <li><a href="https://www.sitepoint.com/functional-programming-pure-functions/">Functional Programming: Pure Functions</a></li> </ul> <hr /> <h2><span id="state"></span>State</h2> <p><strong>State</strong> refers to the information a program has access to and can operate on at a point in time. This includes data stored in memory as well as OS memory, input/output ports, database, etc. For example, the contents of variables in an application at any given instant are representative of the application's <em>state</em>.</p> <h3>Stateful</h3> <p><strong>Stateful</strong> programs, apps, or components store data in memory about the current state. They can modify the state as well as access its history. The following example is <em>stateful</em>:</p> <pre><code class="js">// stateful var number = 1; function increment() { return number++; } increment(); // global variable modified: number = 2 </code></pre> <h3>Stateless</h3> <p><strong>Stateless</strong> functions or components perform tasks as though running them for the first time, every time. This means they do not reference or utilize any information from earlier in their execution. Statelessness enables <em>referential transparency</em>. Functions depend only on their arguments and do not access or need knowledge of anything outside their scope. <a href="#purity" target="_self">Pure functions</a> are stateless. See the following example:</p> <pre><code class="js">// stateless var number = 1; function increment(n) { return n + 1; } increment(number); // global variable NOT modified: returns 2 </code></pre> <p>Stateless applications <em>do</em> still manage state. However, they return their current state without <em>mutating</em> previous state. This is a tenet of <a href="#functional-programming">functional programming</a>.</p> <h3>State Takeaways</h3> <p>State management is important for any complex application. Stateful functions or components modify state and store history, but are more difficult to test and debug. Stateless functions rely only on their inputs to produce outputs. A stateless program returns new state rather than <em>modifying</em> existing state.</p> <p>To learn more about <strong>state</strong>, check out the following resources:</p> <ul> <li><a href="https://en.wikipedia.org/wiki/State_(computer_science)">State</a></li> <li><a href="http://stackoverflow.com/questions/844536/advantages-of-stateless-programming">Advantages of stateless programming</a></li> <li><a href="https://toddmotto.com/stateful-stateless-components">Stateful and stateless components, the missing manual</a></li> <li><a href="http://redux.js.org/">Redux: predictable state container for JavaScript apps</a></li> </ul> <hr /> <h2><span id="immutable-mutable"></span>Immutability and Mutability</h2> <p>The concepts of <strong>immutability and mutability</strong> are slightly more nebulous in JavaScript than in some other programming languages. However, you will hear a lot about immutability when reading about <a href="#functional-programming" target="_self">functional programming</a> in JS. It's important to know what these terms mean classically and also how they are referenced and implemented in JavaScript. The definitions are simple enough:</p> <h3>Immutable</h3> <p>If an object is <strong>immutable</strong>, its value cannot be modified after creation.</p> <h3>Mutable</h3> <p>If an object is <strong>mutable</strong>, its value can be modified after creation.</p> <h3>By Design: Immutability and Mutability in JavaScript</h3> <p>In JavaScript, strings and number literals are <em>immutable by design</em>. This is easily understandable if we consider how we operate on them:</p> <pre><code class="js">var str = 'Hello!'; var anotherStr = str.substring(2); // result: str = 'Hello!' (unchanged) // result: anotherStr = 'llo!' (new string) </code></pre> <p>Using the <code>.substring()</code> method on our <code>Hello!</code> string does <em>not</em> modify the original string. Instead, it creates a <em>new</em> string. We could reassign the <code>str</code> <em>variable value</em> to something else, but once we've created our <code>Hello!</code> string, it will always be <code>Hello!</code>.</p> <p>Number literals are immutable as well. The following will always have the same result:</p> <pre><code class="js">var three = 1 + 2; // result: three = 3 </code></pre> <p>Under no circumstances could <code>1 + 2</code> evaluate to anything other than <code>3</code>.</p> <p>This demonstrates that immutability by design does exist in JavaScript. However, JS developers are aware that the language allows most things to be changed. For example, objects and arrays are <em>mutable by design</em>. Consider the following:</p> <pre><code class="js">var arr = [1, 2, 3]; arr.push(4); // result: arr = [1, 2, 3, 4] var obj = { greeting: 'Hello' }; obj.name = 'Jon'; // result: obj = { greeting: 'Hello', name: 'Jon' } </code></pre> <p>In these examples, the <em>original</em> objects are mutated. New objects are not returned.</p> <p>To learn more about mutability in other languages, check out <a href="https://www.interviewcake.com/concept/java/mutable">Mutable vs Immutable Objects</a>.</p> <h3>In Practice: Immutability in JavaScript</h3> <p><a href="#functional-programming" target="_self">Functional programming</a> in JavaScript has gained a lot of momentum. But by design, JS is a very mutable, multi-paradigm language. Functional programming emphasizes <em>immutability</em>. Other functional languages will raise errors when a developer tries to mutate an immutable object. So how can we reconcile the innate mutability of JS when writing functional or functional reactive JS?</p> <p>When we talk about functional programming in JS, the word "immutable" is used a lot, but it's the responsibility of the developer to write their code with immutability <em>in mind</em>. For example, <a href="https://egghead.io/lessons/javascript-redux-the-single-immutable-state-tree">Redux relies on a single, immutable state tree</a>. However, <em>JavaScript itself</em> is capable of mutating the state object. To implement an immutable state tree, we need to <a href="https://egghead.io/lessons/javascript-redux-avoiding-array-mutations-with-concat-slice-and-spread">return a <em>new</em></a> <a href="https://egghead.io/lessons/javascript-redux-avoiding-object-mutations-with-object-assign-and-spread">state object</a> each time the state changes.</p> <p>JavaScript objects <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze">can also be frozen</a> with <code>Object.freeze(obj)</code> <a href="http://adripofjavascript.com/blog/drips/immutable-objects-with-object-freeze.html">to make them immutable</a>. Note that this is <em>shallow</em>, meaning object values within a frozen object can still be mutated. To further ensure immutability, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze">functions like Mozilla's deepFreeze()</a> and <a href="https://www.npmjs.com/package/deep-freeze">npm deep-freeze</a> can recursively freeze objects. Freezing is most practical when used in <em>tests</em> rather than in application JS. Tests will alert developers when mutations occur so they can be corrected or avoided in the actual build without <code>Object.freeze</code> cluttering up the core code.</p> <p>There are also libraries available to support immutability in JS. <a href="http://swannodette.github.io/mori/">Mori</a> delivers persistent data structures based on Clojure. <a href="https://facebook.github.io/immutable-js/">Immutable.js</a> by Facebook also provides <a href="https://auth0.com/blog/intro-to-immutable-js/">immutable collections for JS</a>. Utility libraries like <a href="http://underscorejs.org">Underscore.js</a> and <a href="http://www.lodash.com">lodash</a> provide methods and modules to promote a more immutable <a href="https://github.com/lodash/lodash/wiki/FP-Guide">functional programming <em>style</em></a>.</p> <h3>Immutability and Mutability Takeaways</h3> <p>Overall, JavaScript is a very mutable language. Some styles of JS coding <em>rely</em> on this innate mutability. However, when writing functional JS, implementing immutability requires mindfulness. JS will not natively throw errors when you modify something unintentionally. Testing and libraries can assist, but working with immutability in JS takes practice and methodology.</p> <p>Immutability has advantages. It results in code that is simpler to reason about. It also enables <a href="https://en.wikipedia.org/wiki/Persistence_(computer_science)"><em>persistency</em></a>, the ability to keep older versions of a data structure and copy only the parts that have changed.</p> <p>The disadvantage of immutability is that many algorithms and operations cannot be implemented efficiently.</p> <p>To learn more about <strong>immutability and mutability</strong>, check out the following resources:</p> <ul> <li><a href="https://www.sitepoint.com/immutability-javascript/">Immutability in JavaScript</a></li> <li><a href="http://adripofjavascript.com/blog/drips/immutable-objects-with-object-freeze.html">Immutable Objects with Object Freeze</a></li> <li><a href="https://www.interviewcake.com/concept/java/mutable">Mutable vs Immutable Objects</a></li> <li><a href="http://jlongster.com/Using-Immutable-Data-Structures-in-JavaScript">Using Immutable Data Stuctures in JavaScript</a></li> <li><a href="https://egghead.io/courses/getting-started-with-redux">Getting Started with Redux</a> (includes examples for addressing immutable state)</li> </ul> <hr /> <h2><span id="imperative-declarative"></span>Imperative and Declarative Programming</h2> <p>While some languages were designed to be <strong>imperative</strong> (C, PHP) or <strong>declarative</strong> (SQL, HTML), JavaScript (and others like <a href="http://openjdk.java.net/projects/lambda/">Java</a> and <a href="https://msdn.microsoft.com/en-us/library/bb534803(v=vs.110).aspx">C#</a>) can support both programming paradigms.</p> <p>Most developers familiar with even the most basic JavaScript have written imperative code: instructions informing the computer <em>how</em> to achieve a desired result. If you've written a <code>for</code> loop, you've written imperative JS.</p> <p>Declarative code tells the computer <em>what</em> you want to achieve rather than how, and the computer takes care of how to achieve the end result without explicit description from the developer. If you've used <code>Array.map</code>, you've written declarative JS.</p> <h3>Imperative Programming</h3> <p><strong>Imperative programming</strong> describes <em>how</em> a program's logic works in explicit commands with statements that modify the program state.</p> <p>Consider a function that increments every number in an array of integers. An imperative JavaScript example of this might be:</p> <pre><code class="js">function incrementArray(arr) { let resultArr = []; for (let i = 0; i &lt; arr.length; i++) { resultArr.push(arr[i] + 1); } return resultArr; } </code></pre> <p>This function shows exactly <em>how</em> the function's logic works: we iterate over the array and explicitly increase each number, pushing it to a new array. We then return the resulting array. This is a step-by-step description of the function's logic.</p> <h3>Declarative Programming</h3> <p><strong>Declarative programming</strong> describes <em>what</em> a program's logic accomplishes <em>without</em> describing how.</p> <p>A very straightforward example of declarative programming can be demonstrated with <a href="https://www.khanacademy.org/computing/computer-programming/sql">SQL</a>. We can query a database table (<code>People</code>) for people with the last name <code>Smith</code> like so:</p> <pre><code class="sql">SELECT * FROM People WHERE LastName = 'Smith' </code></pre> <p>This code is easy to read and describes <em>what</em> we want to accomplish. There is no description of <em>how</em> the result should be achieved. The computer takes care of that.</p> <p>Now consider the <code>incrementArray()</code> function we implemented imperatively above. Let's implement this declaratively now:</p> <pre><code class="js">function incrementArray(arr) { return arr.map(item =&gt; item + 1); } </code></pre> <p>We show <em>what</em> we want to achieve, but not how it works. The <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"><code>Array.map()</code> method</a> returns a new array with the results of running the callback on each item from the passed array. This approach does not modify existing values, nor does it include any sequential logic showing <em>how</em> it creates the new array.</p> <blockquote><p><strong>Note:</strong> JavaScript's <a href="https://www.sitepoint.com/map-reduce-functional-javascript/"><code>map</code>, <code>reduce</code>,</a> <a href="https://danmartensen.svbtle.com/javascripts-map-reduce-and-filter">and <code>filter</code></a> are declarative, <a href="#functional-programming" target="_self">functional</a> array methods. Utility libraries like <a href="https://lodash.com/">lodash</a> provide methods like <a href="https://lodash.com/docs/4.17.4#takeWhile"><code>takeWhile</code></a>, <a href="https://lodash.com/docs/4.17.4#uniq"><code>uniq</code></a>, <a href="https://lodash.com/docs/4.17.4#zip"><code>zip</code></a>, and more in addition to <code>map</code>, <code>reduce</code>, and <code>filter</code>.</p></blockquote> <h3>Imperative and Declarative Programming Takeaways</h3> <p>As a language, JavaScript allows both <strong>imperative and declarative programming</strong> paradigms. Much of the JS code we read and write is imperative. However, with the rise of <a href="#functional-programming" target="_self">functional programming</a> in JS, declarative approaches are becoming more common.</p> <p>Declarative programming has obvious advantages with regard to brevity and readability, but at the same time it can feel magical. Many JavaScript beginners can benefit from gaining experience writing imperative JS before diving too deep into declarative programming.</p> <p>To learn more about <strong>imperative and declarative programming</strong>, check out the following resources:</p> <ul> <li><a href="https://tylermcginnis.com/imperative-vs-declarative-programming/">Imperative vs Declarative Programming</a></li> <li><a href="http://softwareengineering.stackexchange.com/questions/117092/whats-the-difference-between-imperative-procedural-and-structured-programming">What's the Difference Between Imperative, Procedural, and Structured Programming?</a></li> <li><a href="http://www.redotheweb.com/2015/09/18/declarative-imperative-js.html">Imperative and (Functional) Declarative JS In Practice</a></li> <li><a href="https://danmartensen.svbtle.com/javascripts-map-reduce-and-filter">JavaScript's Map, Reduce, and Filter</a></li> </ul> <hr /> <h2><span id="higher-order-functions"></span>Higher-order Functions</h2> <p>A <strong>higher-order function</strong> is a function that:</p> <ul> <li>accepts another function as an argument, or</li> <li>returns a function as a result.</li> </ul> <p>In JavaScript, functions are <a href="http://helephant.com/2008/08/19/functions-are-first-class-objects-in-javascript/"><em>first-class objects</em></a>. They can be stored and passed around as <em>values</em>: we can assign a function to a variable or pass a function to another function.</p> <pre><code class="js">const double = function(x) { return x * 2; } const timesTwo = double; timesTwo(4); // result: returns 8 </code></pre> <p>One example of taking a function as an argument is a <em>callback</em>. Callbacks can be inline anonymous functions or named functions:</p> <pre><code class="js">const myBtn = document.getElementById('myButton'); // anonymous callback function myBtn.addEventListener('click', function(e) { console.log(`Click event: ${e}`); }); // named callback function function btnHandler(e) { console.log(`Click event: ${e}`); } myBtn.addEventListener('click', btnHandler); </code></pre> <p>We can also pass a function as an argument to any other function we create and then execute that argument:</p> <pre><code class="js">function sayHi() { alert('Hi!'); } function greet(greeting) { greeting(); } greet(sayHi); // alerts "Hi!" </code></pre> <blockquote><p><strong>Note:</strong> When <em>passing a named function as an argument</em>, as in the two examples above, we don't use parentheses <code>()</code>. This way we're passing the function as an object. Parentheses <em>execute</em> the function and pass the result instead of the function itself.</p></blockquote> <p>Higher-order functions can also return another function:</p> <pre><code class="js">function whenMeetingJohn() { return function() { alert('Hi!'); } } var atLunchToday = whenMeetingJohn(); atLunchToday(); // alerts "Hi!" </code></pre> <h3>Higher-order Function Takeaways</h3> <p>The nature of JavaScript functions as first-class objects make them prime for facilitating <a href="#functional-programming" target="_self">functional programming</a>.</p> <p>To learn more about <strong>higher-order functions</strong>, check out the following resources:</p> <ul> <li><a href="http://helephant.com/2008/08/19/functions-are-first-class-objects-in-javascript/">Functions are first class objects in JavaScript</a></li> <li><a href="https://www.sitepoint.com/higher-order-functions-javascript/">Higher-Order Functions in JavaScript</a></li> <li><a href="https://www.youtube.com/watch?v=BMUiFMZr7vk">Higher-order functions - Part 1 of Functional Programming in JavaScript</a></li> <li><a href="http://eloquentjavascript.net/05_higher_order.html">Eloquent JavaScript - Higher-order Functions</a></li> <li><a href="https://medium.com/functional-javascript/higher-order-functions-78084829fff4#.dwg58papp">Higher Order Functions</a></li> </ul> <hr /> <h2><span id="functional-programming"></span>Functional Programming</h2> <p>Now we've learned about purity, statelessness, immutability, declarative programming, and higher-order functions. These are all concepts that are important in understanding the functional programming paradigm.</p> <h3>In Practice: Functional Programming with JavaScript</h3> <p><strong>Functional programming</strong> encompasses the above concepts in the following ways:</p> <ul> <li>Core functionality is implemented using pure functions without side effects.</li> <li>Data is immutable.</li> <li>Functional programs are stateless.</li> <li>Imperative container code manages side effects and executes declarative, pure core code.*</li> </ul> <blockquote><p>*If we tried to write a JavaScript web application composed of nothing but pure functions with no side effects, it couldn't interact with its environment and therefore wouldn't be particularly useful.</p></blockquote> <p>Let's explore an example. Say we have some text copy and we want to get its word count. We also want to find keywords that are longer than five characters. Using functional programming, our resulting code might look something like this:</p> <pre><code class="js">const fpCopy = `Functional programming is powerful and enjoyable to write. It's very cool!`; // remove punctuation from string const stripPunctuation = (str) =&gt; str.replace(/[.,\/#!$%\^&amp;\*;:{}=\-_`~()]/g, ''); // split passed string on spaces to create an array const getArr = (str) =&gt; str.split(' '); // count items in the passed array const getWordCount = (arr) =&gt; arr.length; // find items in the passed array longer than 5 characters // make items lower case const getKeywords = (arr) =&gt; arr .filter(item =&gt; item.length &gt; 5) .map(item =&gt; item.toLowerCase()); // process copy to prep the string, create an array, count words, and get keywords function processCopy(str, prepFn, arrFn, countFn, kwFn) { const copyArray = arrFn(prepFn(str)); console.log(`Word count: ${countFn(copyArray)}`); console.log(`Keywords: ${kwFn(copyArray)}`); } processCopy(fpCopy, stripPunctuation, getArr, getWordCount, getKeywords); // result: Word count: 11 // result: Keywords: functional,programming,powerful,enjoyable </code></pre> <p>This code is available to run at this <a href="https://jsfiddle.net/kmaida/xxc7g0ve/">JSFiddle: Functional Programming with JavaScript</a>. It's broken into digestible, declarative functions with clear purpose. If we step through it and read the comments, no further explanation of the code should be necessary. Each <em>core</em> function is modular and relies only on its inputs (<a href="#purity" target="_self">pure</a>). The last function processes the core to generate the collective outputs. This function, <code>processCopy()</code>, is the impure container that executes the core and manages side effects. We've used a <a href="#higher-order-functions" target="_self">higher-order function</a> that accepts the other functions as arguments to maintain the functional style.</p> <h3>Functional Programming Takeaways</h3> <p>Immutable data and statelessness mean that the program's existing state is not modified. Instead, new values are returned. Pure functions are used for core functionality. In order to implement the program and handle necessary side effects, impure functions can call pure functions imperatively.</p> <p>To learn more about <strong>functional programming</strong>, check out the following resources:</p> <ul> <li><a href="https://auth0.com/blog/intro-to-immutable-js/">Introduction to Immutable.js and Functional Programming Concepts</a></li> <li><a href="http://www.defmacro.org/ramblings/fp.html">Functional Programming For The Rest of Us</a></li> <li><a href="http://stephen-young.me.uk/2013/01/20/functional-programming-with-javascript.html">Functional Programming with JavaScript</a></li> <li><a href="https://www.smashingmagazine.com/2014/07/dont-be-scared-of-functional-programming/">Don't be Scared of Functional Programming</a></li> <li><a href="https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-1-1f15e387e536#.q8a7nwjat">So You Want to be a Functional Programmer</a></li> <li><a href="https://github.com/lodash/lodash/wiki/FP-Guide">lodash - Functional Programming Guide</a></li> <li><a href="http://stackoverflow.com/questions/17826380/what-is-difference-between-functional-and-imperative-programming-languages">What is the difference between functional and imperative programming languages?</a></li> <li><a href="http://eloquentjavascript.net/1st_edition/chapter6.html">Eloquent JavaScript, 1st Edition - Functional Programming</a></li> <li><a href="http://tobyho.com/2015/11/09/functional-programming-by-example/">Functional Programming by Example</a></li> <li><a href="https://www.youtube.com/watch?v=BMUiFMZr7vk&amp;list=PL0zVEGEvSaeEd9hlmCXrk5yUyqUag-n84">Functional Programming in JavaScript - Video Series</a></li> <li><a href="https://medium.com/functional-javascript/introduction-to-functional-javascript-45a9dca6c64a#.2qjh0i04y">Introduction to Functional JavaScript</a></li> <li><a href="http://stackoverflow.com/questions/18172947/how-to-perform-side-effects-in-pure-functional-programming">How to perform side effects in pure functional programming</a></li> <li><a href="https://davidwalsh.name/preventing-sideeffects-javascript">Preventing Side Effects in JavaScript</a></li> </ul> <hr /> <h2><span id="observables"></span>Observables</h2> <p><strong>Observables</strong> are similar to arrays, except instead of being stored in memory, items arrive asynchronously over time (also called <em>streams</em>). We can <em>subscribe</em> to observables and react to events emitted by them. JavaScript observables are an implementation of the <a href="http://stackoverflow.com/a/15596243"><em>observer pattern</em></a>. <a href="http://reactivex.io/">Reactive Extensions</a> (commonly known as Rx*) provides an observables library for JS via <a href="https://github.com/ReactiveX/rxjs">RxJS</a>.</p> <p>To demonstrate the concept of observables, let's consider a simple example: resizing the browser window. It's easy to understand observables in this context. Resizing the browser window emits a stream of events over a period of time as the window is dragged to its desired size. We can create an observable and subscribe to it to react to the stream of resize events:</p> <pre><code class="js">// create window resize stream // throttle resize events const resize$ = Rx.Observable .fromEvent(window, 'resize') .throttleTime(350); // subscribe to the resize$ observable // log window width x height const subscription = resize$.subscribe((event) =&gt; { let t = event.target; console.log(`${t.innerWidth}px x ${t.innerHeight}px`); }); </code></pre> <p>The example code above shows that as the window size changes, we can throttle the observable stream and subscribe to the changes to respond to new values in the collection. This is an example of a <em>hot observable</em>.</p> <h3>Hot Observables</h3> <p>User interface events like button clicks, mouse movement, etc. are <em>hot</em>. <strong>Hot observables</strong> will always push even if we're not specifically reacting to them with a subscription. The window resize example above is a hot observable: the <code>resize$</code> observable fires whether or not <code>subscription</code> exists.</p> <h3>Cold Observables</h3> <p>A <strong>cold observable</strong> begins pushing <em>only</em> when we subscribe to it. If we subscribe again, it will start over.</p> <p>Let's create an observable collection of numbers ranging from <code>1</code> to <code>5</code>:</p> <pre><code class="js">// create source number stream const source$ = Rx.Observable.range(1, 5); // subscribe to source$ observable const subscription = source$.subscribe( (value) =&gt; { console.log(`Next: ${value}`); }, // onNext (event) =&gt; { console.log(`Error: ${event}`); }, // onError () =&gt; { console.log('Completed!'); } // onCompleted ); </code></pre> <p>We can <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/subscribe.md"><code>subscribe()</code></a> to the <code>source$</code> observable we just created. Upon subscription, the values are sent in sequence to the observer. The <code>onNext</code> callback logs the values: <code>Next: 1</code>, <code>Next: 2</code>, etc. until completion: <code>Completed!</code>. The cold <code>source$</code> observable we created doesn't push unless we <em>subscribe</em> to it.</p> <h3>Observables Takeaways</h3> <p>Observables are streams. We can observe any stream: from resize events to existing arrays to API responses. We can create observables from almost anything. A <em>promise</em> is an observable with a single emitted value, but observables can return many values over time.</p> <p>We can operate on observables in many ways. <a href="https://github.com/Reactive-Extensions/RxJS/tree/master/doc/api/core/operators">RxJS utilizes numerous operator methods</a>. Observables are often visualized using points on a line, as demonstrated on the <a href="http://rxmarbles.com">RxMarbles</a> site. Since the stream consists of asynchronous events over <em>time</em>, it's easy to conceptualize this in a linear fashion and use such visualizations to understand Rx* operators. For example, the following RxMarbles image illustrates the <a href="http://rxmarbles.com/#filter">filter operator</a>:</p> <p><img src="https://cdn.auth0.com/blog/jsglossary/rxmarbles.png" alt="reactive programming with Rx observables: filter operator from rxmarbles.com" /></p> <p>To learn more about <strong>observables</strong>, check out the following resources:</p> <ul> <li><a href="http://reactivex.io/documentation/observable.html">Reactive Extensions: Observable</a></li> <li><a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md">Creating and Subscribing to Simple Observable Sequences</a></li> <li><a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754#request-and-response">The introduction to Reactive Programming you've been missing: Request and Response</a></li> <li><a href="https://egghead.io/lessons/javascript-introducing-the-observable">Introducing the Observable</a></li> <li><a href="http://rxmarbles.com/">RxMarbles</a></li> <li><a href="https://xgrommx.github.io/rx-book/content/observable/index.html">Rx Book - Observable</a></li> <li><a href="https://egghead.io/lessons/javascript-introducing-the-observable">Introducing the Observable</a></li> </ul> <hr /> <h2><span id="reactive-programming"></span>Reactive Programming</h2> <p><strong>Reactive programming</strong> is concerned with propagating and responding to incoming events over time, <a href="#imperative-declarative" target="_self">declaratively</a> (describing <em>what</em> to do rather than <em>how</em>).</p> <p>Reactive programming is often associated with <a href="http://reactivex.io/">Reactive Extensions</a>, an API for asynchronous programming with <a href="#observables" target="_self">observable streams</a>. Reactive Extensions (abbreviated Rx*) <a href="http://reactivex.io/languages.html">provides libraries for a variety of languages</a>, including JavaScript (<a href="https://github.com/Reactive-Extensions/RxJS">RxJS</a>).</p> <h3>In Practice: Reactive Programming with JavaScript</h3> <p>Here is an example of reactive programming with observables. Let's say we have an input where the user can enter a six-character confirmation code and we want to print out the latest valid code attempt. Our HTML might look like this:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- HTML --&gt;</span> <span class="nt">&lt;input</span> <span class="na">id=</span><span class="s">&quot;confirmation-code&quot;</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;p&gt;</span> <span class="nt">&lt;strong&gt;</span>Valid code attempt:<span class="nt">&lt;/strong&gt;</span> <span class="nt">&lt;code</span> <span class="na">id=</span><span class="s">&quot;attempted-code&quot;</span><span class="nt">&gt;&lt;/code&gt;</span> <span class="nt">&lt;/p&gt;</span></code></pre></div> <p>We'll use RxJS and create a stream of input events to implement our functionality, like so:</p> <pre><code class="js">// JS const confCodeInput = document.getElementById('confirmation-code'); const attemptedCode = document.getElementById('attempted-code'); const confCodes$ = Rx.Observable .fromEvent(confCodeInput, 'input') .map(e =&gt; e.target.value) .filter(code =&gt; code.length === 6); const subscription = confCodes$.subscribe( (value) =&gt; attemptedCode.innerText = value, (event) =&gt; { console.warn(`Error: ${event}`); }, () =&gt; { console.info('Completed!'); } ); </code></pre> <p>This code can be run at this <a href="https://jsfiddle.net/kmaida/v1ozuwgu/">JSFiddle: Reactive Programming with JavaScript</a>. We'll observe <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/fromevent.md">events from</a> the <code>confCodeInput</code> input element. Then we'll use the <a href="http://reactivex.io/documentation/operators/map.html"><code>map</code> operator</a> to get the <code>value</code> from each input event. Next, we'll <a href="http://reactivex.io/documentation/operators/filter.html"><code>filter</code></a> any results that are not six characters so they won't appear in the returned stream. Finally, we'll <a href="http://reactivex.io/documentation/operators/subscribe.html"><code>subscribe</code></a> to our <code>confCodes$</code> observable and print out the latest valid confirmation code attempt. Note that this was done in response to events over time, declaratively: this is the crux of reactive programming.</p> <h3>Reactive Programming Takeaways</h3> <p>The reactive programming paradigm involves observing and reacting to events in asynchronous data streams. RxJS is used in <a href="https://medium.com/google-developer-experts/angular-introduction-to-reactive-extensions-rxjs-a86a7430a61f#.41aap1i8a">Angular</a> and is gaining popularity as a JavaScript solution for reactive programming.</p> <p>To learn more about <strong>reactive programming</strong>, check out the following resources:</p> <ul> <li><a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754">The introduction to Reactive Programming you've been missing</a></li> <li><a href="http://www.introtorx.com/">Introduction to Rx</a></li> <li><a href="http://www.reactivemanifesto.org/">The Reactive Manifesto</a></li> <li><a href="https://auth0.com/blog/understanding-reactive-programming-and-rxjs/">Understanding Reactive Programming and RxJS</a></li> <li><a href="http://paulstovell.com/blog/reactive-programming">Reactive Programming</a></li> <li><a href="https://davidwalsh.name/modernization-reactivity">Modernization of Reactivity</a></li> <li><a href="https://github.com/Reactive-Extensions/RxJS/tree/master/doc/api/core">Reactive-Extensions RxJS API Core</a></li> </ul> <hr /> <h2><span id="functional-reactive-programming"></span>Functional Reactive Programming</h2> <p>In simple terms, functional reactive programming could be summarized as declaratively responding to events or behaviors over time. To understand the tenets of FRP in more depth, let's take a look at FRP's formulation. Then we'll examine its use in relation to JavaScript.</p> <h3>What is Functional Reactive Programming?</h3> <p>A <a href="http://stackoverflow.com/a/5386908">more complete definition</a> from <a href="https://twitter.com/conal">Conal Elliot, FRP's formulator</a>, would be that <strong>functional reactive programming</strong> is "<a href="https://en.wikibooks.org/wiki/Haskell/Denotational_semantics">denotative</a> and temporally continuous". Elliot mentions that he prefers to describe this programming paradigm as <em>denotative continuous-time programming</em> as opposed to "functional reactive programming".</p> <p><strong>Functional reactive programming</strong>, at its most basic, original definition, has two fundamental properties:</p> <ul> <li><strong>denotative</strong>: the meaning of each function or type is precise, simple, and implementation-independent ("functional" references this)</li> <li><strong>continuous time</strong>: <a href="https://en.wikipedia.org/wiki/Discrete_time_and_continuous_time#Continuous_time">variables have a particular value for a very short time: between any two points are an infinite number of other points</a>; provides transformation flexibility, efficiency, modularity, and accuracy ("reactive" references this)</li> </ul> <p>Again, when we put it simply: <a href="https://www.quora.com/What-is-Functional-Reactive-Programming"><strong>functional reactive programming</strong> is programming declaratively with time-varying values</a>.</p> <p>To understand <em>continuous time / temporal continuity</em>, consider an analogy using vector graphics. Vector graphics have an <em>infinite resolution</em>. Unlike bitmap graphics (discrete resolution), vector graphics scale indefinitely. They never pixellate or become indistinct when particularly large or small the way bitmap graphics do.</p> <blockquote><p>"FRP expressions describe entire evolutions of values over time, representing these evolutions directly as first-class values."</p> <p>—<em>Conal Elliot</em></p></blockquote> <p>Functional reactive programming should be:</p> <ul> <li>dynamic: can react over time <em>or</em> to input changes</li> <li>time-varying: reactive <em>behaviors</em> can change continually while reactive <em>values</em> change discretely</li> <li>efficient: minimize amount of processing necessary when inputs change</li> <li>historically aware: pure functions map state from a previous point in time to the next point in time; state changes concern the local element and not the global program state</li> </ul> <p>Conal Elliot's slides on the <a href="http://conal.net/talks/essence-and-origins-of-frp-lambdajam-2015.pdf">Essence and Origins of FRP can be viewed here</a>. The programming language <a href="https://wiki.haskell.org/Functional_Reactive_Programming">Haskell</a> lends itself to true FRP due to its functional, pure, and lazy nature. Evan Czaplicki, the creator of <a href="http://elm-lang.org">Elm</a>, gives a great overview of FRP in his talk <a href="https://www.youtube.com/watch?v=Agu6jipKfYw">Controlling Time and Space: Understanding the Many Formulations of FRP</a>.</p> <p>In fact, let's talk briefly about <a href="http://people.seas.harvard.edu/~chong/pubs/pldi13-elm.pdf">Evan Czapliki</a>'s <a href="https://auth0.com/blog/creating-your-first-elm-app-part-1/">Elm</a>. Elm is a functional, typed language for building web applications. It compiles to JavaScript, CSS, and HTML. <a href="https://guide.elm-lang.org/architecture/">The Elm Architecture</a> was the inspiration for the <a href="http://redux.js.org/">Redux</a> state container for JS apps. <a href="https://www.youtube.com/watch?v=Agu6jipKfYw">Elm was originally considered a true functional reactive programming language</a>, but as of version 0.17, it implemented <em>subscriptions</em> instead of signals in the interest of making the language easier to learn and use. In doing so, Elm <a href="http://elm-lang.org/blog/farewell-to-frp">bid farewell to FRP</a>.</p> <h3>In Practice: Functional Reactive Programming and JavaScript</h3> <p>The traditional definition of FRP can be difficult to grasp, especially for developers who don't have experience with languages like Haskell or Elm. However, the term has come up more frequently in the front-end ecosystem, so let's shed some light on its application in JavaScript.</p> <p>In order to reconcile what you may have read about FRP in JS, it's important to understand that <a href="https://www.sitepoint.com/functional-reactive-programming-rxjs/">Rx*</a>, <a href="https://baconjs.github.io/">Bacon.js</a>, <a href="http://blog.angular-university.io/functional-reactive-programming-for-angular-2-developers-rxjs-and-observables/">Angular</a>, and others are <em>not</em> consistent with the two primary fundamentals of Conal Elliot's definition of FRP. <a href="https://stackoverflow.com/questions/5875929/specification-for-a-functional-reactive-programming-language#comment36554089_5878525">Elliot states that Rx* and Bacon.js are not FRP. Instead, they are "compositional event systems <em>inspired</em> by FRP"</a>.</p> <p>Functional reactive programming, <em>as it relates specifically to JavaScript implementations</em>, refers to programming in a <a href="#functional-programming" target="_self">functional</a> style while creating and reacting to <a href="#observables" target="_self">streams</a>. This is fairly far from Elliot's original formulation (which <a href="http://conal.net/talks/essence-and-origins-of-frp-lambdajam-2015.pdf">specifically <em>excludes</em> streams as a component</a>), but is nevertheless inspired by traditional FRP.</p> <p>It's also crucial to understand that JavaScript inherently interacts with the user and UI, the DOM, and often a backend. <a href="#purity" target="_self">Side effects</a> and <a href="#imperative-declarative" target="_self">imperative</a> code are par for the course, even when taking a <a href="#functional-programming" target="_self">functional</a> or functional reactive approach. <em>Without</em> imperative or impure code, a JS web application with a UI wouldn't be much use because it couldn't interact with its environment.</p> <p>Let's take a look at an example to demonstrate the basic principles of <em>FRP-inspired</em> JavaScript. This sample uses RxJS and prints out mouse movements over a period of ten seconds:</p> <pre><code class="js">// create a time observable that adds an item every 1 second // map so resulting stream contains event values const time$ = Rx.Observable .timer(0, 1000) .timeInterval() .map(e =&gt; e.value); // create a mouse movement observable // throttle to every 350ms // map so resulting stream pushes objects with x and y coordinates const move$ = Rx.Observable .fromEvent(document, 'mousemove') .throttleTime(350) .map(e =&gt; { return {x: e.clientX, y: e.clientY} }); // merge time + mouse movement streams // complete after 10 seconds const source$ = Rx.Observable .merge(time$, move$) .takeUntil(Rx.Observable.timer(10000)); // subscribe to merged source$ observable // if value is a number, createTimeset() // if value is a coordinates object, addPoint() const subscription = source$.subscribe( // onNext (x) =&gt; { if (typeof x === 'number') { createTimeset(x); } else { addPoint(x); } }, // onError (err) =&gt; { console.warn('Error:', err); }, // onCompleted () =&gt; { console.info('Completed'); } ); // add element to DOM to list out points touched in a particular second function createTimeset(n) { const elem = document.createElement('div'); const num = n + 1; elem.id = 't' + num; elem.innerHTML = `&lt;strong&gt;${num}&lt;/strong&gt;: `; document.body.appendChild(elem); } // add points touched to latest time in stream function addPoint(pointObj) { // add point to last appended element const numberElem = document.getElementsByTagName('body')[0].lastChild; numberElem.innerHTML += ` (${pointObj.x}, ${pointObj.y}) `; } </code></pre> <p>You can check out this code in action in this <a href="https://jsfiddle.net/kmaida/3v8yw02s/">JSFiddle: FRP-inspired JavaScript</a>. Run the fiddle and move your mouse over the result area of the screen as it counts up to 10 seconds. You should see mouse coordinates appear along with the counter. This indicates where your mouse was during each 1-second time interval.</p> <p>Let's briefly discuss this implementation step-by-step.</p> <p>First, we'll create an <a href="#observables" target="_self">observable</a> called <code>time$</code>. This is a timer that adds a value to the collection every <code>1000ms</code> (every second). We need to <code>map</code> the timer event to extract its <code>value</code> and push it in the resulting stream.</p> <p>Next, we'll create a <code>move$</code> observable from the <code>document.mousemove</code> event. Mouse movement is <em>continuous</em>. At any point in the sequence, there are an infinite number of points in between. We'll throttle this so the resulting stream is more manageable. Then we can <code>map</code> the event to return an object with <code>x</code> and <code>y</code> values to represent mouse coordinates.</p> <p>Next we want to <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/merge.md">merge</a> the <code>time$</code> and <code>move$</code> streams. This is a <em>combining operator</em>. This way we can plot which mouse movements occurred during each time interval. We'll call the resulting observable <code>source$</code>. We'll also limit the <code>source$</code> observable so that it completes after ten seconds (<code>10000ms</code>).</p> <p>Now that we have our merged stream of time and movement, we'll create a <code>subscription</code> to the <code>source$</code> observable so we can react to it. In our <code>onNext</code> callback, we'll check to see if the value is a <code>number</code> or not. If it is, we want to call a function called <code>createTimeset()</code>. If it's a coordinates object, we'll call <code>addPoint()</code>. In the <code>onError</code> and <code>onCompleted</code> callbacks, we'll simply log some information.</p> <p>Let's look at the <code>createTimeset(n)</code> function. We'll create a new <code>div</code> element for each second interval, label it, and append it to the DOM.</p> <p>In the <code>addPoint(pointObj)</code> function, we'll print out the latest coordinates in the most recent timeset <code>div</code>. This will associate each set of coordinates with its corresponding time interval. We can now read where the mouse has been over time.</p> <blockquote><p><strong>Note:</strong> These functions are <a href="#purity" target="_self">impure</a>: they have no return value and they also produce side effects. The side effects are DOM manipulations. As mentioned earlier, the JavaScript we need to write for our apps frequently interacts with scope outside its functions.</p></blockquote> <h3>Functional Reactive Programming Takeaways</h3> <p>FRP encodes actions that react to events using pure functions that map state from a previous point in time to the next point in time. FRP in JavaScript doesn't adhere to the two primary fundamentals of Conal Elliot's FRP, but there is certainly value in abstractions of the original concept. JavaScript relies heavily on side effects and imperative programming, but we can certainly take advantage of the power of FRP concepts to improve our JS.</p> <p>Finally, consider this quote from the <a href="http://eloquentjavascript.net/1st_edition/">first edition of Eloquent JavaScript</a> (the <a href="http://eloquentjavascript.net">second edition is available here</a>):</p> <blockquote><p>"Fu-Tzu had written a small program that was full of global state and dubious shortcuts. Reading it, a student asked 'You warned us against these techniques, yet I find them in your program. How can this be?'</p> <p>Fu-Tzu said 'There is no need to fetch a water hose when the house is not on fire.' {This is not to be read as an encouragement of sloppy programming, but rather as a warning against neurotic adherence to rules of thumb.}"</p> <p>—<em>Marijn Haverbeke, <a href="http://eloquentjavascript.net/1st_edition/chapter6.html">Eloquent JavaScript, 1st Edition, Chapter 6</a></em></p></blockquote> <p>To learn more about <strong>functional reactive programming (FRP)</strong>, check out the following resources:</p> <ul> <li><a href="https://www.youtube.com/watch?v=vLmaZxegahk">Functional Reactive Programming for Beginners</a></li> <li><a href="https://sideeffects.xyz/2015/the-functional-reactive-misconception/">The Functional Reactive Misconception</a></li> <li><a href="http://stackoverflow.com/questions/1028250/what-is-functional-reactive-programming/1030631#1030631">What is Functional Reactive Programming?</a></li> <li><a href="https://wiki.haskell.org/Functional_Reactive_Programming">Haskell - Functional Reactive Programming</a></li> <li><a href="http://conal.net/fran/tutorial.htm">Composing Reactive Animations</a></li> <li><a href="https://stackoverflow.com/questions/5875929/specification-for-a-functional-reactive-programming-language#5878525">Specification for a functional reactive programming language</a></li> <li><a href="https://github.com/conal/talk-2015-more-elegant-frp">A more elegant specification for FRP</a></li> <li><a href="https://www.youtube.com/watch?v=vLmaZxegahk">Functional Reactive Programming for Beginners</a></li> <li><a href="http://elm-lang.org/blog/farewell-to-frp">Elm - A Farewell to FRP</a></li> <li><a href="http://conal.net/blog/posts/early-inspirations-and-new-directions-in-functional-reactive-programming">Early inspirations and new directions in functional reactive programming</a></li> <li><a href="https://blogs.janestreet.com/breaking-down-frp/">Breaking Down FRP</a></li> <li><a href="https://twitter.com/ReactiveX/status/483625917491970048">Rx* is not FRP</a></li> </ul> <hr /> <h2>Conclusion</h2> <p>We'll conclude with another excellent quote from the first edition of <a href="http://eloquentjavascript.net/1st_edition/">Eloquent JavaScript</a>:</p> <blockquote><p>"A student had been sitting motionless behind his computer for hours, frowning darkly. He was trying to write a beautiful solution to a difficult problem, but could not find the right approach. Fu-Tzu hit him on the back of his head and shouted '<em>Type something!</em>' The student started writing an ugly solution. After he had finished, he suddenly understood the beautiful solution."</p> <p>—<em>Marijn Haverbeke, <a href="http://eloquentjavascript.net/1st_edition/chapter6.html">Eloquent JavaScript, 1st Edition, Chapter 6</a></em></p></blockquote> <p>The concepts necessary for understanding <a href="#functional-programming" target="_self">functional programming</a>, <a href="#reactive-programming" target="_self">reactive programming</a>, and <a href="#functional-reactive-programming" target="_self">functional reactive programming</a> can be difficult to grasp, let alone <em>master</em>. Writing code that takes advantage of a paradigm's fundamentals is the initial step, even if it isn't entirely faithful at first. Practice illuminates the path ahead and also reveals potential revisions.</p> <p>With this glossary as a starting point, you can begin taking advantage of these concepts and programming paradigms to increase your JavaScript expertise. If anything is still unclear regarding these topics, please consult the links in each section for additional resources. We'll cover more concepts in the next Modern JS Glossary post!</p> Making use of RxJS in Angular 2017-02-13T10:00:00+00:00 https://auth0.com/blog/making-use-of-rxjs-angular/ Wojciech Kwiatek https://twitter.com/WojciechKwiatek <hr /> <p><strong>TL;DR</strong> Angular, <a href="http://angularjs.blogspot.com/2017/01/branding-guidelines-for-angular-and.html">previously known as Angular 2</a>, incorporates RxJS and uses it internally. We can make use of some RxJS goodies and introduce FRP to write more robust code in our apps.</p> <hr /> <p>If you're new to RxJS, I recommend reading <a href="https://auth0.com/blog/understanding-reactive-programming-and-rxjs/">Understanding Reactive Programming and RxJS</a> before proceeding.</p> <p>RxJS is all about streams, operators to modify them, and observables.</p> <h2>Functional Reactive Programming (FRP)</h2> <p>FRP has recently become a buzzword. To give you a deeper understanding on that topic, there is an awesome post from Andre Stalz -- <a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754">The introduction to Reactive Programming you've been missing</a>. What is the key takeaway from the this comprehensive post? Reactive programming is actually programming with asynchronous data streams. But where does the word <em>functional</em> come into play? Functional is about how we can modify these streams to create new sets of data. A stream can be used as an input to another stream. We have a bunch of operators in RxJS to do things like this. So, can we do some of FRP with RxJS? The short answer is: yes! And we'll do so with Angular.</p> <h2>RxJS in Angular</h2> <p>To get started with RxJS in Angular, all we need to do is import the operators we want to use. TRxJS is itself an Angular dependency so it's ready to use out of the box.</p> <h3>Passing observables to the view</h3> <p>We are about to start with some observables created ad hoc. Let's create an observable from the JavaScript array:</p> <pre><code class="ts">const items = Observable.of([1, 2, 3]) </code></pre> <p>Now, we can use the created observable as a component's property and pass it into the view. Angular introduced a new filter, which will be a perfect fit here. It's called <code>async</code>. Its purpose is to unwrap promises and observables. In the case of an observable it'll pass the last value of the observable:</p> <pre><code class="ts">import { Component } from '@angular/core' import { Observable } from 'rxjs/Rx' @Component({ selector: 'my-app', template: ` &lt;ul&gt; &lt;li *ngFor="let item of items | async"&gt; &lt;/li&gt; &lt;/ul&gt; ` }) export class AppComponent { public items = Observable.of([1, 2, 3]) } </code></pre> <p>We should see a list of elements in the browser.</p> <p>This is our <em>hello world</em> example to see how async works and how we can use it.</p> <h3>Http</h3> <p>Angular relies on RxJS for some of its internal features. One of the most well-known services is <em>Http</em>. In Angular 1.x, <em>Http</em> was a promise-based service. In Angular 2+, it's based on observables. This means that we can also make use of the <code>async</code> pipe here. Let's try to create a real-world example with a service. We want to fetch a list of repos authored by Auth0 on GitHub:</p> <pre><code class="ts">import { Injectable } from '@angular/core' import { Http } from '@angular/http' import { Observable } from 'rxjs/Rx' import 'rxjs/add/operator/map' @Injectable() export class RepoService { constructor(private _http: Http) {} getReposForUser(user: string): Observable&lt;any&gt; { return this._http .get(`https://api.github.com/users/${user}/repos`) .map((res: any) =&gt; res.json()) } } </code></pre> <p>Here, we have the service, which exposes the <code>getReposForUser</code> method to make an http call. Note the return type of the method -- it's an <code>Observable&lt;any&gt;</code>. Now, we can add it into the module and use it in the component:</p> <pre><code class="ts">import { RepoService } from './repo.service.js' @Component({ selector: 'my-app', template: ` `, }) export class AppComponent { public repos: Observable&lt;any&gt; constructor(repoService: RepoService) { this.repos = repoService.getReposForUser('auth0') console.log(this.repos) } } </code></pre> <p>Something important has just happened. You can take a look into the <em>Network</em> tab of your developer tools in the browser. No call was made. Let's add the <code>for</code> loop with the <code>async</code> pipe:</p> <pre><code class="ts">@Component({ selector: 'my-app', template: ` &lt;ul&gt; &lt;li *ngFor="let repo of repos | async"&gt; &lt;/li&gt; &lt;/ul&gt; `, }) export class AppComponent { public repos: Observable&lt;any&gt; constructor(repoService: RepoService) { this.repos = repoService.getReposForUser('auth0') } } </code></pre> <p>Now the call for repositories is fired, and we can see that the list of repos has been fetched correctly. Why is that?</p> <h2>Hot and Cold Observables</h2> <p>The <code>http.get</code> observable above is <strong>cold</strong>: that means each subscriber sees the same events from the beginning. It's independent of any other subscriber. It also means that if there's no subscriber, no value is emitted! See this one in action:</p> <pre><code class="ts">export class AppComponent { public repos: Observable&lt;any&gt; constructor(repoService: RepoService) { this.repos = repoService.getReposForUser('auth0') this.repos.subscribe() this.repos.subscribe() } } </code></pre> <p>Now you'll be able to see three calls. You can now see one more thing -- <code>async</code> makes a subscription under the hood.</p> <p>On the other hand, we have <strong>hot</strong> observables. The difference is, no matter how many subscribers there are, the observable starts just once. And we can make our observable hot, instead of cold, by using the <code>share</code> operator:</p> <pre><code class="ts">// ... import 'rxjs/add/operator/share' @Injectable() export class RepoService { constructor(private http: Http) {} getReposForUser(user: string): Observable&lt;any&gt; { return this.http .get(`https://api.github.com/users/${user}/repos`) .map((res: any) =&gt; res.json()) .share() } } </code></pre> <p>Now you should see just one call. If you want to go deeper with the topic, here is a <a href="http://medium.com/@benlesh/hot-vs-cold-observables-f8094ed53339">Hot vs Cold Observables</a> article by Ben Lesh.</p> <h2>Programming the reactive way in Angular</h2> <h3>Handling events</h3> <p>We've covered how you've probably used RxJS observables for <em>Http</em> in Angular, even if you weren't aware of it. However, there are many more things you can do with streams, even if Angular doesn't require you to do so. Now we move on to the <em>on click</em> events. The traditional, imperative way of handling click events in Angular is as follows:</p> <pre><code class="ts">@Component({ selector: 'my-app', template: ` &lt;button (click)="handleButtonClick(1)"&gt; Up Vote &lt;/button&gt; `, }) export class AppComponent { handleButtonClick(value: number) { console.log(value) } } </code></pre> <p>We can create a stream of click events using RxJS <code>Subject</code>. <em>Subject</em> is both an observer and an observable at the same time. It means it can emit value (using <code>.next()</code>), and you can subscribe to it (using <code>subscribe</code>).</p> <p>Here, you can see the same case achieved with functional approach using RxJS:</p> <pre><code class="ts">@Component({ selector: 'my-app', template: ` &lt;button (click)="counter$.next(1)"&gt; Up Vote &lt;/button&gt; `, }) export class AppComponent { public counter$: Observable&lt;number&gt; = new Subject&lt;number&gt;() constructor() { this.counter$.subscribe(console.log.bind(console)) } } </code></pre> <p>It's not much different than the previous one, though. Let's try to add some more logic there. Like making sum of clicks and printing some text instead of just number.</p> <pre><code class="ts">@Component({ selector: 'my-app', template: ` &lt;button (click)="counter$.next(1)"&gt; Up Vote &lt;/button&gt; `, }) export class AppComponent { public counter$: Observable&lt;string&gt; = new Subject&lt;number&gt;() .scan((acc: number, current: number): number =&gt; acc + current) .map((value: number): string =&gt; `Sum of clicks: ${value}`) constructor() { this.counter$.subscribe(console.log.bind(console)) } } </code></pre> <p>The key point is that <em>we define how the clicks stream will behave.</em> We say that we don't really need clicks but only the sum of them with some prepended text. And this sum will be our stream, not the pure click events. And we subscribe to the stream of summed values. In other words, <em>the key of functional programming is to make the code declarative, not imperative.</em></p> <h3>Communication between components</h3> <p>Let's briefly address communication between Angular components using an RxJS approach. It's actually about dumb components in the RxJS approach of an Angular world. Last time I described the <a href="https://auth0.com/blog/understanding-angular-2-change-detection/">change detection of Angular</a> and what we can do with it to fine-tune the app. We'll add the component with <code>clicks$</code> stream as the input.</p> <pre><code class="ts">import { ChangeDetectionStrategy, Component, Input } from '@angular/core' @Component({ selector: 'my-score', template: 'Summary: ', changeDetection: ChangeDetectionStrategy.OnPush }) export class ScoreComponent { @Input() public score: number } </code></pre> <p>Note that the component has <code>ChangeDetectionStrategy.OnPush</code> turned on, so this means that we assume that the new reference will come as the input. The component accepts a numeric parameter, but there is no reference to streams. We can handle this with the <code>async</code> pipe:</p> <pre><code class="ts">@Component({ selector: 'my-app', template: ` &lt;button (click)="counter$.next(1)"&gt; Up Vote &lt;/button&gt; &lt;my-score [score]="counter$ | async"&gt;&lt;/my-score&gt; `, }) export class AppComponent { public counter$: Observable&lt;number&gt; = new Subject&lt;number&gt;() .scan((acc: number, current: number): number =&gt; acc + current) } </code></pre> <h3>Forms</h3> <p>Another place when you can use the power of RxJS is forms. We can use all of the knowledge that we have gained up to this point and see how we can create a reactive login form.</p> <p>First, let's start with adding <code>ReactiveFormsModule</code> from <code>@angular/forms</code> to the module. Then we can make use of the reactive forms introduced in Angular. Here's how it can look:</p> <pre><code class="ts">import { FormBuilder, FormGroup } from '@angular/forms' @Component({ selector: 'my-app', template: ` &lt;form [formGroup]="loginForm" &gt; &lt;label&gt;Login:&lt;/label&gt; &lt;input formControlName="login" type="text" &gt; &lt;label&gt;Password:&lt;/label&gt; &lt;input formControlName="password" type="password" &gt; &lt;button type="submit"&gt;Submit&lt;/button&gt; &lt;/form&gt; `, }) export class AppComponent implements OnInit { public loginForm: FormGroup constructor(private formBuilder: FormBuilder) {} ngOnInit() { this.loginForm = this.formBuilder.group({ login: '', password: '', }) } } </code></pre> <p>We now have a few additional blocks: - <code>formControlName</code> -- added to match names from templates to the appropriate fields in the controller - <code>formBuilder.group</code> -- creates the form - <code>[formGroup]</code> -- connects the template and the controller</p> <p>We can now use the <code>valueChanges</code> observable:</p> <pre><code class="ts">// ... this.loginForm.valueChanges.subscribe(console.log.bind(console)) // ... </code></pre> <p>Now, each changed field will emit an event and will be logged to the console. This offers many possibilities since we can take advantage of any operator that RxJS provides. In this example, let's focus on submitting the form in a reactive way. We can put <code>(submit)</code> on the form:</p> <pre><code class="ts">@Component({ selector: 'my-app', template: ` &lt;form [formGroup]="loginForm" (submit)="submit$.next()" &gt; &lt;!-- ... --&gt; ` }) // ... export class AppComponent { public loginForm: FormGroup private submit$: Observable&lt;any&gt; = new Subject() // ... </code></pre> <p>We now have a stream of submit events and a stream of values. All that remains is to combine these streams. The resulting stream will emit the current state of the fields when the form is submitted. The desired behavior can be achieved by using the <a href="http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-withLatestFrom">withLatestFrom</a> operator of RxJS. The combined stream is as follows:</p> <pre><code class="ts">// ... this.submit$ .withLatestFrom(this.loginForm.valueChanges, (_, values) =&gt; values) .subscribe(values =&gt; { console.log('submitted values', values) }) // ... </code></pre> <p>We now have combined streams, and the logic is consolidated. It can be written in a single line. Just to recap, here is the final code for the form component:</p> <pre><code class="ts">@Component({ selector: 'my-app', template: ` &lt;form [formGroup]="loginForm" (submit)="submit$.next()" &gt; &lt;label&gt;Login:&lt;/label&gt; &lt;input formControlName="login" type="text" &gt; &lt;label&gt;Password:&lt;/label&gt; &lt;input formControlName="password" type="password" &gt; &lt;button type="submit"&gt;Submit&lt;/button&gt; &lt;/form&gt; `, }) export class AppComponent { public loginForm: FormGroup private submit$: Observable&lt;any&gt; = new Subject() constructor(private formBuilder: FormBuilder) {} ngOnInit() { this.loginForm = this.formBuilder.group({ login: '', password: '', }) this.submit$ .withLatestFrom(this.loginForm.valueChanges, (_, values) =&gt; values) .subscribe(values =&gt; { console.log('submitted values', values) }) } } </code></pre> <h2>Conclusion</h2> <p>Angular has a lot more features than meets the eye. RxJS is, in my personal opinion, one of the best of them. It can rocket the app to the next level in term of maintainability and clarity. The future is more declarative, less imperative code.</p> <p>RxJS can appear intimidating at first, but once you’re familiar with its functionality and operators, it supplies many benefits (such as defining logic at the declaration time). All of this is to say, the code is easier to understand compared to imperative code. RxJS requires a different mode of thinking, but it is very worthwhile to learn and use.</p> Build The Ultimate Account Based Marketing Machine with Account Selection 2017-02-10T08:30:00+00:00 https://auth0.com/blog/ultimate-account-based-marketing-machine-with-account-selection/ Brandon Redlinger https://twitter.com/Brandon_Lee_09 <p>David Ogilvy was far ahead of this time. He was known as the King of Madison Avenue. Though often viewed by his peers as eccentric (and even bizarre – he was known to wear capes to board meetings), he got many things right. One particular quote that still stands out and is applicable in today’s B2B word is this:</p> <blockquote><p>“Don’t count the people you reach; reach the people that count.”</p></blockquote> <p>Traditional demand gen has been about reaching more people. However, when taking an account based approach, being able to reach the right people is one of the core principles. Selecting accounts is a combination of art and science, intuition and logic. Companies combine gut feel, historical performance, and sometimes predictive data science to develop an Ideal Customer Profile, tier their accounts, then allocate their resources properly to work said accounts. Get this wrong, and you’ll be burning money. Get this right, and you’ll be printing money at will. That’s why this is the foundation for every good Account Based Marketing program. In fact, it goes beyond that – it’s the core of <a href="http://www.engagio.com/hello-account-based-everything-and-goodbye-account-based-marketing/">Account Based Everything (ABE)</a>.</p> <h2>How Should You Select Your Target Accounts?</h2> <p>The process of choosing target accounts comes down to a specific definition (ICP) of companies that best match your goals. This definition includes the key dimensions that define high-value accounts that are most likely to buy, including things like:</p> <ul> <li>Firmographics</li> <li>Technographics</li> <li>Pain points</li> <li>Behaviors</li> <li>Intent data</li> <li>Strategy</li> </ul> <p>One way to decide on your ICP is to reverse engineer your existing best customers to see what they have in common. Another is to analyze the best customers of your closest competitors: where are they winning and why?</p> <p>Once you know the specific profile of an ideal account, it’s time to actually pick the accounts; to name the companies you’ll be targeting. On this front, there’s a <a href="http://www.engagio.com/account-selection-maturity-model/">maturity spectrum</a>, with increasing accuracy and sophistication as you move up.</p> <p><img src="https://cdn.auth0.com/blog/ultimate-abm-machine/abm-tiers.png" alt="Maturity Spectrum" /></p> <p>The accuracy and completeness of your account selection improves as you move up the maturity spectrum. Do what you need to do – but be advised: time, money and effort spent on rigorous account selection will be repaid many times over in the number and quality of opportunities you generate.</p> <p>“Data is a never ending problem. Prospectors have a clear idea of which companies should be a good t, and which shouldn’t.” - Aaron Ross, Predictable Revenue</p> <h2>How Should You Tier Your Target Accounts?</h2> <p>Not all accounts are the same, so you'll also need to organize your target accounts into tiers, based on how valuable they might be (and how much research and personalization will go into each one.) We take a tiered approach where Tier 1 is a classic ABE/ABM approach, Tier 2 is a lighter approach, and Tier 3 is a hybrid approach.</p> <p><strong>Tier 1</strong> – These accounts get the “full” Account Based Everything treatment – meaning each one gets deep research, a customized plan, personalized content, bespoke campaigns, and lots of one-to-one attention. You map out each buying center, understand where there may be revenue potential, build out the organization chart and see which contacts you know and which you need to know, research key business priorities and individual motivations, and identify relationships and connections to the account. You publish detailed account dossiers, maintain them quarterly, and even have internal chat groups or forums dedicated to each account.</p> <p><strong>Tier 2</strong> – These accounts also get individual research, but perhaps it’s limited to a few key talking points for each account. These accounts may not get completely personalized Plays and custom content, but they should still get highly relevant touches based on their industry and persona. Instead of one-to-one campaigns, these accounts get one-to-few campaigns. Instead of fully bespoke content, perhaps you take content written for their industry and customize it with their logo on the cover and a personalized first and last paragraph.</p> <p><strong>Tier 3</strong> – This style covers all the accounts that you want to target but don’t have the resources for personalization and customization. ITSMA calls this Programmatic ABM. It’s basically traditional marketing with account-level targeting. The key difference from demand gen is that instead of scoring leads, you track account-level engagement and wait until the account hits a sufficient threshold to label them a <a href="http://www.engagio.com/what-is-a-marketing-qualified-account-mqa/">Marketing Qualified Account (MQA)</a>.</p> <h2>How Many Accounts Should You Have in Each Tier?</h2> <p>When determining who you’ll target in your Account Based Everything program, an important decision is how many accounts you should be targeting within each tier of your program.</p> <p><img src="https://cdn.auth0.com/blog/ultimate-abm-machine/abm-accounts.png" alt="ABM Accounts Funnel" /></p> <p>Like most decisions related to strategy, there is no one-size-fits-all answer. The number of accounts you choose to target for each Tier in your ABE program – and the number of accounts per AE and SDR – will depend on things like:</p> <ul> <li>Your expected deal sizes</li> <li>The length of the sales cycle</li> <li>Your available sales resources</li> <li>Your current level of engagement with major prospects</li> <li>The intensiveness of your account based strategy</li> </ul> <h2>How Should You Allocate Your Resources?</h2> <p>We think the best way to select target accounts is by looking at how many resources you have to invest. This depends on how you handle the different tiers or styles of ABE.</p> <p>A given enterprise Account Executive may only be handle a few Tier 1 accounts, but a corporate rep could probably handle a few hundred Tier 3 target accounts at a time. <strong>The right number of accounts is the number that your team can handle in a tier-appropriate way</strong>.</p> <p>We know one company where management felt their reps could have 100 named accounts at a time – but they gave each one 150 accounts so the reps wouldn’t feel like their territories were too small.</p> <p>Across a sample of Engagio customers, the median number of accounts per account owner is 50. Quite a few Engagio customers have a lower number, 20 to 30 accounts per account owner, and quite a few have 100 or more accounts per owner.</p> <p><img src="https://cdn.auth0.com/blog/ultimate-abm-machine/engagio-customer-sample.png" alt="Engagio Customer Sample" /></p> <p>As you can see, there’s a lot that goes into establishing the base for your Account Based Everything program. We’ve just scratched the surface of the first step. To learn more about the WHO (and the WHAT and the WHERE) of Account Based Sales Development, download <a href="http://www.engagio.com/clear-and-complete-guide-to-account-based-sales-development/">The Clear &amp; Complete Guide to Account Based Sales Development</a>.</p> <p>How many accounts does your team manage, on average? How did you make this decision?</p> <div class="alert alert-info"> <strong>About Brandon Redlinger:</strong><br /> Brandon Redlinger is the Director of Growth at <a href="http://www.engagio.com/" target="_blank">Engagio</a>, the Account Based Everything platform that orchestrates human connections. He is passionate about the intersection between tech and psychology, especially as it applies to growing businesses. You can follow him on Twitter <a href="https://twitter.com/Brandon_Lee_09" target="_blank">@brandon_lee_09</a> or connect with him on <a href="https://www.linkedin.com/in/brandonredlinger" target="_blank">LinkedIn</a>. </div> Migrating a PHP 5 App to PHP 7 (Tools & Implementation) - Part 3 2017-02-09T08:30:00+00:00 https://auth0.com/blog/migrating-a-php5-app-to-7-part-three/ Prosper Otemuyiwa http://twitter.com/unicodeveloper?lang=en <p><strong>TL;DR:</strong> Many PHP applications are still running on PHP 5.x, not ready to take full advantage of the awesome features that PHP 7 offers. A lot of developers have not made the switch because of certain fears of compatibility issues, migration challenges and the strange awkward feeling that migrating will take away a big chunk of their time. In the <a href="https://auth0.com/blog/migrating-a-php5-app-to-php7-part-one">first part of this tutorial</a> we learned how to set up a PHP 7 development environment. In <a href="https://auth0.com/blog/migrating-a-php5-app-to-php7-part-two">the second part of this tutorial</a>, we discussed extensively about all the new features PHP 7 offers and the language constructs and features that have been either removed or deprecated. This time, we'll show you how you can leverage all the new PHP 7 features when migrating and also the tools that will help to make the process painless!</p> <hr /> <p>You need to be aware that for the most part, PHP 5.x code can run on PHP 7. In PHP 7, there are some backwards incompatible changes, so applications built with PHP 5.x that use functions and language constructs that have been removed or have the internal implementation changed drastically will spit out errors while trying to run on PHP 7.</p> <h2>Tools to Aid Migration</h2> <p>One of the most frustating part of our jobs as software developers is having to work on large old codebases. In a situation where you are tasked with migrating a large PHP 5.x application that has probably been in existence for about 10 years, how would you go about it?</p> <p>The easiest and most obvious way of migrating is to initially clone the app on your local machine, install PHP 7 and run the app. You can walk through the errors and deperaction warnings shown in the terminal, and manually fix them step-by-step by incorporating PHP 7 features. This can be very challenging and time consuming. Why can't we automate this process?</p> <p>Currently there is no tool out there that performs a 100% automatic conversion of your PHP 5.x codebase to PHP 7, but these tools below will help in making your migration painless.</p> <h3>PHP 7 MAR</h3> <p><a href="https://github.com/Alexia/php7mar">php7mar</a> is a command-line tool that generates reports on PHP 5.x codebase based on PHP 7 compatibility. The reports contain line numbers, issues noted, and suggested fixes along with documentation links.</p> <p><strong>Note:</strong> The tool does not fix code. It only gives you reports about all the PHP files in your codebase. Happy fixing!</p> <h3>PHP 7 Compatibility Checker</h3> <p><a href="https://github.com/sstalle/php7cc">php7cc</a> is a command-line tool designed to make migration from PHP 5.3 - 5.6 to PHP 7 really easy. php7cc reports:</p> <ul> <li><strong>Errors:</strong> Fatal, Syntax, Notice. These are highlighted in red.</li> <li><strong>Warnings:</strong> These are highlighted in yellow.</li> </ul> <h3>Phan</h3> <p><a href="https://github.com/etsy/phan">phan</a> is a static analyzer for PHP that attempts to prove incorrectness rather than correctness. Phan looks for common issues and verifies type compatibility on various operations when type information is available or can be deduced. Phan checks for lots of things including PHP7/PHP5 backward compatibility.</p> <h3>phpto7aid</h3> <p><a href="https://github.com/gisostallenberg/php-to-7-aid">phpto7aid</a> is a tool that is used to identify PHP 5 code that will not work in PHP 7. It tries to aid you as much as possible in resolving these issues, by either providing the exact solution or giving hints on how to solve the issue.</p> <h3>PhpStorm PHP 7 Compatibility Inspection</h3> <p><a href="https://www.jetbrains.com/phpstorm">PhpStorm</a> is a very smart PHP IDE, developed by <a href="https://www.jetbrains.com">Jetbrains</a>.</p> <p><img src="https://cdn.auth0.com/blog/php/phpstorm_debugging.png" alt="PHPStorm" /> <em>Source: Jetbrains.com</em></p> <p>PhpStorm 10 comes with a <em>PHP 7 Compatibility Inspection</em> tool that can show you exactly what code is going to cause errors if you are running PHP7.</p> <p><img src="https://cdn.auth0.com/blog/php/PHP7-Readiness-Inline-2.png" alt="PHP 7 Readiness" /> <em>Source: Jetbrains.com</em></p> <p>The image below shows a typical example of an application that has classes with names that are reserved in PHP 7. Selecting <strong>Run Inspection By Name</strong> option from the <strong>Code</strong> menu, and then selecting the <strong>PHP 7 Compatibility</strong> section will give you results like this one below:</p> <p><img src="https://cdn.auth0.com/blog/php/PHP7-Readiness-Results.png" alt="PHP 7 Readiness Results" /> <em>Source: Jetbrains.com</em></p> <h2>Building a PHP5 App</h2> <p>We will build the first simple PHP 5 app very quickly. This is the scope of the app:</p> <ul> <li>A user will be able to register on the app.</li> <li>A user will be able to log into the app.</li> <li>A user will be assigned a random Star Wars Code Name.</li> <li>A user will be able to log out of the app.</li> </ul> <p>Building this app will require us to set up a database to store the users, write our registration and login code and manage the users session. Now, we won't employ the use of any framework because we don't want any form of overhead. Ordinarily, building this app would take a lot of time and setup but there is a service we can use to eliminate the hassle. Oh, yeah, Auth0 to the rescue!</p> <h3>Create and Configure Auth0 Client</h3> <p>First thing we'll need to do is <a href="javascript:signup()">sign up for a free Auth0 account</a> and configure a new client.</p> <p>Now head over to <a href="https://manage.auth0.com/#/clients">clients tab</a> and create a new one choosing 'Regular web Application' as the client type. Let's name it as something like 'Basic PHP WebApp'.</p> <p>Now that we have our client created, we need to take note of three properties: <code>Domain</code>, <code>Client ID</code> and <code>Client Secret</code>. All of them can be found on the <code>Settings</code> tab of the client that we've just created.</p> <p>The last configuration that we need to do, before updating our code, is to add <code>http://localhost:3000</code> as an <code>Allowed Callback URLs</code> on our Auth0 client.</p> <h3>Build the App</h3> <p>Create a <code>composer.json</code> file in a new directory and add this to it like so:</p> <pre><code class="js"> { "name": "basic php webapp", "description": "Basic sample for securing a WebApp with Auth0", "require": { "vlucas/phpdotenv": "2.3.0", "auth0/auth0-php": "~4.0" }, "license": "MIT" } </code></pre> <p><em>composer.json</em></p> <p>All we need is the <code>phpdotenv</code> package for reading environment variables and the <code>auth0-php</code> package that makes it easy to use the Auth0 service.</p> <p>Create a <code>public</code> folder inside the directory and add two files, <code>app.css</code> and <code>app.js</code> in it.</p> <pre><code class="css"> body { font-family: "proxima-nova", sans-serif; text-align: center; font-size: 300%; font-weight: 100; } input[type=checkbox], input[type=radio] { position: absolute; opacity: 0; } input[type=checkbox] + label, input[type=radio] + label { display: inline-block; } input[type=checkbox] + label:before, input[type=radio] + label:before { content: ""; display: inline-block; vertical-align: -0.2em; width: 1em; height: 1em; border: 0.15em solid #0074d9; border-radius: 0.2em; margin-right: 0.3em; background-color: white; } input[type=radio] + label:before { border-radius: 50%; } input[type=radio]:checked + label:before, input[type=checkbox]:checked + label:before { background-color: #0074d9; box-shadow: inset 0 0 0 0.15em white; } input[type=radio]:focus + label:before, input[type=checkbox]:focus + label:before { outline: 0; } .btn { font-size: 140%; text-transform: uppercase; letter-spacing: 1px; border: 0; background-color: #16214D; color: white; } .btn:hover { background-color: #44C7F4; } .btn:focus { outline: none !important; } .btn.btn-lg { padding: 20px 30px; } .btn:disabled { background-color: #333; color: #666; } h1, h2, h3 { font-weight: 100; } #logo img { width: 300px; margin-bottom: 60px; } .home-description { font-weight: 100; margin: 100px 0; } h2 { margin-top: 30px; margin-bottom: 40px; font-size: 200%; } label { font-size: 100%; font-weight: 300; } .btn-next { margin-top: 30px; } .answer { width: 70%; margin: auto; text-align: left; padding-left: 10%; margin-bottom: 20px; } .login-page .login-box { padding: 5px 0; } </code></pre> <p><em>app.css</em></p> <pre><code class="js"> $(document).ready(function() { var lock = new Auth0Lock(AUTH0_CLIENT_ID, AUTH0_DOMAIN, { auth: { redirectUrl: AUTH0_CALLBACK_URL , responseType: 'code' , params: { scope: 'openid' } }}); $('.btn-login').click(function(e) { e.preventDefault(); lock.show(); }); }); </code></pre> <p><em>app.js</em></p> <p>Go ahead and create a <code>.htaccess</code> file inside the directory like so:</p> <pre><code class="bash"> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . index.php [L] </code></pre> <p>Create a <code>.env</code> file. This file will contain our Auth0 credentials.</p> <pre><code class="bash"> AUTH0_DOMAIN='blahabababababa.auth0.com' AUTH0_CLIENT_ID='xxxxxxxxx' AUTH0_CLIENT_SECRET='xxxxxxxxx' AUTH0_CALLBACK_URL='http://localhost:3000' </code></pre> <p><strong>Note:</strong> Replace these values with the <code>client_id</code>, <code>client_secret</code> and <code>domain</code> from your Auth0 dashboard.</p> <p>Add the value of <code>callback_url</code> to the <strong>Allowed Callback URLs</strong> in your <em>Settings</em> on the dashboard.</p> <p><img src="https://cdn.auth0.com/blog/app/callbackurl.png" alt="Auth0 Dashboard showcasing Callback Url" /> <em>Auth0 dashboard: Allowed Callback Urls</em></p> <p>Also, do not forget to add the same value to the <strong>Allowed Origins(CORS)</strong> in your <em>Settings</em> on the dashboard.</p> <p><img src="https://cdn.auth0.com/blog/app/cors.png" alt="Auth0 Dashboard showcasing Allowed Origin Cors" /> <em>Auth0 dashboard: Allowed Origin CORS</em></p> <p>We need a file to invoke the <code>dotenv</code> library and load the values that we have deposited in the <code>.env</code> file. Create a new file, <em>dotenv-loader.php</em> like so:</p> <pre><code class="php"> &lt;?php // Read .env try { $dotenv = new Dotenv\Dotenv(__DIR__); $dotenv-&gt;load(); } catch(InvalidArgumentException $ex) { // Ignore if no dotenv } </code></pre> <p><em>dotenv-loader.php</em></p> <p>Finally, let's create the <code>index.php</code> file where all our app logic will reside. Like I mentioned earlier, it's just a basic app so don't be worried about separation of concerns.</p> <p>This is how the file should look like:</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="cp">&lt;?php</span> <span class="cp">// Require composer autoloader</span> <span class="cp">require __DIR__ . &#39;/vendor/autoload.php&#39;;</span> <span class="cp">require __DIR__ . &#39;/dotenv-loader.php&#39;;</span> <span class="cp">use Auth0\SDK\API\Authentication;</span> <span class="cp">$domain = getenv(&#39;AUTH0_DOMAIN&#39;);</span> <span class="cp">$client_id = getenv(&#39;AUTH0_CLIENT_ID&#39;);</span> <span class="cp">$client_secret = getenv(&#39;AUTH0_CLIENT_SECRET&#39;);</span> <span class="cp">$redirect_uri = getenv(&#39;AUTH0_CALLBACK_URL&#39;);</span> <span class="cp">$auth0 = new Authentication($domain, $client_id);</span> <span class="cp">$auth0Oauth = $auth0-&gt;get_oauth_client($client_secret, $redirect_uri, [</span> <span class="cp"> &#39;persist_id_token&#39; =&gt; true,</span> <span class="cp"> &#39;persist_refresh_token&#39; =&gt; true,</span> <span class="cp">]);</span> <span class="cp">$starWarsNames = [&#39;Darth Vader&#39;, &#39;Ahsoka Tano&#39;, &#39;Kylo Ren&#39;, &#39;Obi-Wan Kenobi&#39;, &#39;R2-D2&#39;, &#39;Snoke&#39;];</span> <span class="cp">$userInfo = $auth0Oauth-&gt;getUser();</span> <span class="cp">if (isset($_REQUEST[&#39;logout&#39;])) {</span> <span class="cp"> $auth0Oauth-&gt;logout();</span> <span class="cp"> session_destroy();</span> <span class="cp"> header(&quot;Location: /&quot;);</span> <span class="cp">}</span> <span class="cp">?&gt;</span> <span class="nt">&lt;html&gt;</span> <span class="nt">&lt;head&gt;</span> <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;http://code.jquery.com/jquery-3.0.0.min.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;&lt;/script&gt;</span> <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;https://cdn.auth0.com/js/lock/10.0/lock.min.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span> <span class="nt">&lt;script </span><span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span> <span class="na">src=</span><span class="s">&quot;//use.typekit.net/iws6ohy.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span> <span class="nt">&lt;script </span><span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;</span><span class="k">try</span><span class="p">{</span><span class="nx">Typekit</span><span class="p">.</span><span class="nx">load</span><span class="p">();}</span><span class="k">catch</span><span class="p">(</span><span class="nx">e</span><span class="p">){}</span><span class="nt">&lt;/script&gt;</span> <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;viewport&quot;</span> <span class="na">content=</span><span class="s">&quot;width=device-width, initial-scale=1&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;icon&quot;</span> <span class="na">type=</span><span class="s">&quot;image/png&quot;</span> <span class="na">href=</span><span class="s">&quot;/favicon-32x32.png&quot;</span> <span class="na">sizes=</span><span class="s">&quot;32x32&quot;</span><span class="nt">&gt;</span> <span class="c">&lt;!-- font awesome from BootstrapCDN --&gt;</span> <span class="nt">&lt;link</span> <span class="na">href=</span><span class="s">&quot;//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css&quot;</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;link</span> <span class="na">href=</span><span class="s">&quot;//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&quot;</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;script&gt;</span> <span class="kd">var</span> <span class="nx">AUTH0_CLIENT_ID</span> <span class="o">=</span> <span class="s1">&#39;&lt;?php echo getenv(&quot;AUTH0_CLIENT_ID&quot;) ?&gt;&#39;</span><span class="p">;</span> <span class="kd">var</span> <span class="nx">AUTH0_DOMAIN</span> <span class="o">=</span> <span class="s1">&#39;&lt;?php echo getenv(&quot;AUTH0_DOMAIN&quot;) ?&gt;&#39;</span><span class="p">;</span> <span class="kd">var</span> <span class="nx">AUTH0_CALLBACK_URL</span> <span class="o">=</span> <span class="s1">&#39;&lt;?php echo getenv(&quot;AUTH0_CALLBACK_URL&quot;) ?&gt;&#39;</span><span class="p">;</span> <span class="nt">&lt;/script&gt;</span> <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;public/app.js&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;/script&gt;</span> <span class="nt">&lt;link</span> <span class="na">href=</span><span class="s">&quot;public/app.css&quot;</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;/head&gt;</span> <span class="nt">&lt;body</span> <span class="na">class=</span><span class="s">&quot;home&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;container&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;login-page clearfix&quot;</span><span class="nt">&gt;</span> <span class="cp">&lt;?php if(!$userInfo): ?&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;login-box auth0-box before&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;https://cdn.auth0.com/blog/app/star_warsapp.png&quot;</span> <span class="nt">/&gt;</span> <span class="nt">&lt;p&gt;</span>Heard you don&#39;t want to migrate to PHP 7? Dare us!<span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;a</span> <span class="na">class=</span><span class="s">&quot;btn btn-primary btn-login&quot;</span><span class="nt">&gt;</span>SignIn<span class="nt">&lt;/a&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="cp">&lt;?php else: ?&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;logged-in-box auth0-box logged-in&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;h1</span> <span class="na">id=</span><span class="s">&quot;logo&quot;</span><span class="nt">&gt;</span>Star Wars Welcomes You to the Family!<span class="nt">&lt;/h1&gt;</span> <span class="nt">&lt;img</span> <span class="na">class=</span><span class="s">&quot;avatar&quot;</span> <span class="na">width=</span><span class="s">&quot;200&quot;</span> <span class="na">src=</span><span class="s">&quot;&lt;?php echo $userInfo[&#39;picture&#39;] ?&gt;&quot;</span><span class="nt">/&gt;</span> <span class="nt">&lt;h2&gt;</span>Welcome <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">&quot;nickname&quot;</span><span class="nt">&gt;</span><span class="cp">&lt;?php echo $userInfo[&#39;nickname&#39;] ?&gt;</span><span class="nt">&lt;/span&gt;&lt;/h2&gt;</span> <span class="nt">&lt;h2&gt;</span> Assigned Codename : <span class="nt">&lt;b&gt;</span><span class="cp">&lt;?php echo $starWarsNames[rand(0, 6)]; ?&gt;</span><span class="nt">&lt;/b&gt;</span> <span class="nt">&lt;/h2&gt;</span> <span class="nt">&lt;a</span> <span class="na">class=</span><span class="s">&quot;btn btn-primary btn-lg&quot;</span> <span class="na">href=</span><span class="s">&quot;?logout&quot;</span><span class="nt">&gt;</span>Logout<span class="nt">&lt;/a&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="cp">&lt;?php endif ?&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="nt">&lt;/body&gt;</span> <span class="nt">&lt;/html&gt;</span></code></pre></div> <p>Relax, let's analyze the code together.</p> <pre><code class="php"> // Require composer autoloader require __DIR__ . '/vendor/autoload.php'; require __DIR__ . '/dotenv-loader.php'; </code></pre> <p>This is where we require the dotenv loader and composer autoloader. The autoloader makes it possible for us to import any class from the PHP packages installed in the app.</p> <pre><code class="php"> use Auth0\SDK\API\Authentication; $domain = getenv('AUTH0_DOMAIN'); $client_id = getenv('AUTH0_CLIENT_ID'); $client_secret = getenv('AUTH0_CLIENT_SECRET'); $redirect_uri = getenv('AUTH0_CALLBACK_URL'); $auth0 = new Authentication($domain, $client_id); $auth0Oauth = $auth0-&gt;get_oauth_client($client_secret, $redirect_uri, [ 'persist_id_token' =&gt; true, 'persist_refresh_token' =&gt; true, ]); $starWarsNames = ['Darth Vader', 'Ahsoka Tano', 'Kylo Ren', 'Obi-Wan Kenobi', 'R2-D2', 'Snoke']; $userInfo = $auth0Oauth-&gt;getUser(); </code></pre> <p><code>Auth0\SDK\API\Authentication</code> is the Auth0 authentication class. It has the methods to retrieve a user's profile when logged in. <code>$domain</code>, <code>$client_id</code>, <code>$client_secret</code>, <code>$redirect_uri</code> are variables that will house the values gotten from the <code>.env</code> file with the aid of the <code>getenv</code> method.</p> <p>Then, we moved on to instantiating the <code>Authentication</code> class.</p> <p>The <code>$auth0-&gt;get_oauth_client()</code> method by default stores user information in the PHP session, and we also instructed it to save the <code>access_token</code> and <code>id_token</code>.</p> <p><code>$starWarsNames</code> array contains some characters from Star Wars. Later in the code, a user will be assigned a random code name from this array.</p> <p><code>$auth0Oauth-&gt;getUser()</code> retrieves the user information.</p> <pre><code class="php"> if (isset($_REQUEST['logout'])) { $auth0Oauth-&gt;logout(); session_destroy(); header("Location: /"); } </code></pre> <p>This checks if the user submitted a request to log out, clears the session and redirects the user back to the homepage.</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;http://code.jquery.com/jquery-3.0.0.min.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;&lt;/script&gt;</span> <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;https://cdn.auth0.com/js/lock/10.0/lock.min.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span></code></pre></div> <p>We are making use of <a href="https://auth0.com/docs/libraries/lock">Auth0 Lock widget</a>, and we also using jQuery to call the lock methods and handle button click event.</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c">&lt;!-- font awesome from BootstrapCDN --&gt;</span> <span class="nt">&lt;link</span> <span class="na">href=</span><span class="s">&quot;//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css&quot;</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;link</span> <span class="na">href=</span><span class="s">&quot;//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&quot;</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span><span class="nt">&gt;</span></code></pre></div> <p>Pulled in bootstrap and font-awesome for beautification.</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;script&gt;</span> <span class="kd">var</span> <span class="nx">AUTH0_CLIENT_ID</span> <span class="o">=</span> <span class="s1">&#39;&lt;?php echo getenv(&quot;AUTH0_CLIENT_ID&quot;) ?&gt;&#39;</span><span class="p">;</span> <span class="kd">var</span> <span class="nx">AUTH0_DOMAIN</span> <span class="o">=</span> <span class="s1">&#39;&lt;?php echo getenv(&quot;AUTH0_DOMAIN&quot;) ?&gt;&#39;</span><span class="p">;</span> <span class="kd">var</span> <span class="nx">AUTH0_CALLBACK_URL</span> <span class="o">=</span> <span class="s1">&#39;&lt;?php echo getenv(&quot;AUTH0_CALLBACK_URL&quot;) ?&gt;&#39;</span><span class="p">;</span> <span class="nt">&lt;/script&gt;</span></code></pre></div> <p>Here, we are feeding the Auth0 credentials to JavaScript variables.</p> <div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;container&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;login-page clearfix&quot;</span><span class="nt">&gt;</span> <span class="cp">&lt;?php if(!$userInfo): ?&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;login-box auth0-box before&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;https://cdn.auth0.com/blog/app/star_warsapp.png&quot;</span> <span class="nt">/&gt;</span> <span class="nt">&lt;p&gt;</span>Heard you don&#39;t want to migrate to PHP 7? Dare us!<span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;a</span> <span class="na">class=</span><span class="s">&quot;btn btn-primary btn-login&quot;</span><span class="nt">&gt;</span>SignIn<span class="nt">&lt;/a&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="cp">&lt;?php else: ?&gt;</span> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;logged-in-box auth0-box logged-in&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;h1</span> <span class="na">id=</span><span class="s">&quot;logo&quot;</span><span class="nt">&gt;</span>Star Wars Welcomes You to the Family!<span class="nt">&lt;/h1&gt;</span> <span class="nt">&lt;img</span> <span class="na">class=</span><span class="s">&quot;avatar&quot;</span> <span class="na">width=</span><span class="s">&quot;200&quot;</span> <span class="na">src=</span><span class="s">&quot;&lt;?php echo $userInfo[&#39;picture&#39;] ?&gt;&quot;</span><span class="nt">/&gt;</span> <span class="nt">&lt;h2&gt;</span>Welcome <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">&quot;nickname&quot;</span><span class="nt">&gt;</span><span class="cp">&lt;?php echo $userInfo[&#39;nickname&#39;] ?&gt;</span><span class="nt">&lt;/span&gt;&lt;/h2&gt;</span> <span class="nt">&lt;h2&gt;</span> Assigned Codename : <span class="nt">&lt;b&gt;</span><span class="cp">&lt;?php echo $starWarsNames[rand(0, 6)]; ?&gt;</span><span class="nt">&lt;/b&gt;</span> <span class="nt">&lt;/h2&gt;</span> <span class="nt">&lt;a</span> <span class="na">class=</span><span class="s">&quot;btn btn-primary btn-lg&quot;</span> <span class="na">href=</span><span class="s">&quot;?logout&quot;</span><span class="nt">&gt;</span>Logout<span class="nt">&lt;/a&gt;</span> <span class="nt">&lt;/div&gt;</span> <span class="cp">&lt;?php endif ?&gt;</span> <span class="nt">&lt;/div&gt;</span></code></pre></div> <p>In the code above, if the <code>$userInfo</code> is not set, then it means the user has not logged in yet, so we display the signin button. If the user has signed in, then we grab the user's info and display it along with the <code>logout</code> button.</p> <h3>Run The App</h3> <p>Go to your terminal and run <code>composer install</code> to install the dependencies. Next, run your PHP 5.x server. If your PHP server is accessible from the terminal, then you can run it via <code>php -S localhost:3000</code>.</p> <p>Open your browser and test the app. The index page should look like this:</p> <p><img src="https://cdn.auth0.com/blog/app/header.png" alt="Index" /> <em>Index Page</em></p> <p>Now, signup &amp; signin.</p> <p><img src="https://cdn.auth0.com/blog/app/signin.png" alt="Signing In" /> <em>Sign In</em></p> <p>When you are logged in, you should be assigned a Star Wars codename like so:</p> <p><img src="https://cdn.auth0.com/blog/app/loggedin.png" alt="Logged In" /> <em>Logged In</em></p> <p>Our app is now running successfully on a PHP 5.x server. You can grab the <a href="https://github.com/auth0-blog/starwars-phpapp">source code from Github</a> to ensure that everything works as expected.</p> <h3>Migrating our PHP5 App to PHP7</h3> <p>We are currently running a PHP 5.x app. Let's migrate it to PHP 7. The good thing is that most times you might not have to change anything in the codebase. Let's see if that holds true for this app.</p> <p>Upgrade your server to at least PHP 7.0.0 and run this app again.</p> <p><img src="https://cdn.auth0.com/blog/app/php7status.png" alt="PHP 7 Server running" /> <em>PHP 7 Server running</em></p> <p><img src="https://cdn.auth0.com/blog/app/php7_running_app.gif" alt="Running on PHP 7" /> <em>App running on PHP 7 without any errors</em></p> <p>Awesome, now our first app is running on PHP 7 successfully!</p> <h2>Work with Second App</h2> <p>The second PHP app we will go through is an API. It is a simple Chuck Norris API. It has been built already with PHP 5 in mind.</p> <p>Clone it from <a href="https://github.com/auth0-blog/basic-api">Github</a> and run <code>composer install</code> to install all the dependencies. Then run the app on a PHP 5.x server.</p> <p>Open up <a href="https://www.getpostman.com">Postman</a> and test the API like so:</p> <p>Run <code>http://localhost:3000/jokes/categories</code> like so:</p> <p><img src="https://cdn.auth0.com/blog/app/categories.png" alt="Categories API" /> <em>API showing categories</em></p> <p>Run <code>http://localhost:3000/jokes/random</code> like so:</p> <p><img src="https://cdn.auth0.com/blog/app/randomjokes.png" alt="Random Jokes" /> <em>API showing random jokes</em></p> <p>The app is working fine, no errors!</p> <h3>Use PHP 7 features in Second App</h3> <p>Let's refactor this app and integrate some PHP 7 features.</p> <p>This is the directory structure of our API app at the moment:</p> <pre><code class="bash"> ----basic-api | ----src | | | ----Main.php | ----vendor | ----.gitignore | ----.htaccess | ----composer.json | ----composer.lock | ----index.php | ----README.md </code></pre> <p>This is how our <code>Main.php</code> file looks like right now:</p> <pre><code class="php"> &lt;?php namespace App; use Exception; class Main { public function getCategories() { return $this-&gt;getCategoryData(); } private function getCategoryData() { return [ "explicit", "dev", "movie", "food", "celebrity", "science", "political", "sport", "religion", "animal", "music", "history", "travel", "career", "money", "fashion" ]; } public function getRandomJokes($randomNumber) { if( !is_integer($randomNumber)) { throw new Exception("The random number should be an integer. Please try again."); } $jokes = [ "Jon Skeet’s code doesn’t follow a coding convention. It is the coding convention.", "Jon Skeet can divide by Zero.", "Jon Skeet points to null, null quakes in fear.", "Jon Skeet is the traveling salesman. Only he knows the shortest route.", "When Jon pushes a value onto a stack, it stays pushed.", "Drivers think twice before they dare interrupt Jon’s code.", "Jon Skeet does not sleep…. He waits.", "Jon Skeet can stop an infinite loop just by thinking about it.", "Jon Skeet uses Visual Studio to burn CDs.", "Jon Skeet has the key to Open Source. He just doesn’t want to close it." ]; return $jokes[$randomNumber]; } } </code></pre> <p>Let's start by adding PHP 7 return type declarations to the methods in this class like so:</p> <pre><code class="php"> &lt;?php namespace App; class Main { public function getCategories(): array { return $this-&gt;getCategoryData(); } private function getCategoryData(): array { return [ "explicit", "dev", "movie", "food", "celebrity", "science", "political", "sport", "religion", "animal", "music", "history", "travel", "career", "money", "fashion" ]; } public function getRandomJokes($randomNumber): string { if( !is_integer($randomNumber)) { throw new Exception("The random number should be an integer. Please try again."); } $jokes = [ "Jon Skeet’s code doesn’t follow a coding convention. It is the coding convention.", "Jon Skeet can divide by Zero.", "Jon Skeet points to null, null quakes in fear.", "Jon Skeet is the traveling salesman. Only he knows the shortest route.", "When Jon pushes a value onto a stack, it stays pushed.", "Drivers think twice before they dare interrupt Jon’s code.", "Jon Skeet does not sleep…. He waits.", "Jon Skeet can stop an infinite loop just by thinking about it.", "Jon Skeet uses Visual Studio to burn CDs.", "Jon Skeet has the key to Open Source. He just doesn’t want to close it." ]; return $jokes[$randomNumber]; } } </code></pre> <p><em>PHP 7 Return Type Declarations added in Main.php</em></p> <p>Another PHP 7 feature we can add is <em>function parameter typehinting</em>. We have a method, <code>getRandomJokes($randomNumber)</code> that accepts a <code>$randomNumber</code> which is an integer.</p> <p>Let's refactor that method, <code>getRandomJokes()</code>. We'll eliminate the <code>if</code> condition and just typehint the <code>$randomNumber</code> parameter like so:</p> <pre><code class="php"> public function getRandomJokes(int $randomNumber): string { $jokes = [ "Jon Skeet’s code doesn’t follow a coding convention. It is the coding convention.", "Jon Skeet can divide by Zero.", "Jon Skeet points to null, null quakes in fear.", "Jon Skeet is the traveling salesman. Only he knows the shortest route.", "When Jon pushes a value onto a stack, it stays pushed.", "Drivers think twice before they dare interrupt Jon’s code.", "Jon Skeet does not sleep…. He waits.", "Jon Skeet can stop an infinite loop just by thinking about it.", "Jon Skeet uses Visual Studio to burn CDs.", "Jon Skeet has the key to Open Source. He just doesn’t want to close it." ]; return $jokes[$randomNumber]; } </code></pre> <p>Now if you try to pass in a value asides an integer like so:</p> <pre><code class="php"> $router-&gt;get('/jokes/random', function() use ($app){ echo json_encode($app-&gt;getRandomJokes("dsdsds")); }); </code></pre> <p><em>index.php</em></p> <p>PHP 7 will throw a Type Error like so:</p> <p><img src="https://cdn.auth0.com/blog/app/typeerror.png" alt="Type Error" /> <em>PHP 7 TypeError</em></p> <p>We have been able to add some PHP 7 features. The app also runs on a PHP 7 server and everything just works fine!</p> <p>The source code of the PHP 7 version of the API can be found on the <a href="https://github.com/auth0-blog/basic-api/tree/php7"><code>php7 branch</code> on GitHub</a>.</p> <h2>Performance</h2> <p>PHP 7 runs on the new Zend engine 3.0, thus making your apps see up to 2x faster performance and 50% better memory consumption than PHP 5.6. It also allows you to serve more concurrent users without adding any hardware.</p> <p><a href="https://twitter.com/rasmus">Rasmus Ledorf</a>, <em>Creator of PHP</em> and inventor of the SQL LIMIT clause did some benchmarking with a few popular PHP projects with the various versions of PHP from PHP 5.4 up until PHP 7.0 and also benchmarked against HHVM 3.6.1.</p> <p>Let's take a good look at the benchmarks. The test box specs Rasmus used are:</p> <ul> <li>Gigabyte Z87X-UD3H i7-4771 4 cores @ 3.50GHz w/ 16G of Ram @ 1600MHz</li> <li>Hyperthreading enabled for a total of 8 virtual cores</li> <li>Toshiba THNSNHH256GBST SSD</li> <li>Linux debian 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt9-2 (2015-04-13) x86_64 GNU/Linux</li> <li>MySQL 5.6.24</li> <li>Nginx-1.6.2 + php-fpm for all tests unless indicated otherwise</li> <li>Quiet local 100Mbps network</li> <li>Siege benchmark tool run from a separate machine</li> </ul> <p><img src="https://cdn.auth0.com/blog/benchmark/zencart.png" alt="ZenCart 1.5.4" /> <em>ZenCart 1.5.4</em></p> <p><img src="https://cdn.auth0.com/blog/benchmark/moodle.png" alt="Moodle 2.9-dev" /> <em>Moodle 2.9-dev</em></p> <p><img src="https://cdn.auth0.com/blog/benchmark/cachet.png" alt="Cachet" /> <em>Cachet</em></p> <p><img src="https://cdn.auth0.com/blog/benchmark/traq.png" alt="Traq 3.5.2" /> <em>Traq 3.5.2</em></p> <p><img src="https://cdn.auth0.com/blog/benchmark/geeklog.png" alt="Geeklog 2.1.0" /> <em>Geeklog 2.1.0</em></p> <p><img src="https://cdn.auth0.com/blog/benchmark/wardrobecms.png" alt="Wardrobe CMS 1.2.0" /> <em>Wardrobe CMS 1.2.0</em></p> <p><img src="https://cdn.auth0.com/blog/benchmark/opencart.png" alt="Opencart 2.0.2.0" /> <em>Opencart 2.0.2.0</em></p> <p><img src="https://cdn.auth0.com/blog/benchmark/mediawiki.png" alt="MediaWiki 1.24.1" /> <em>MediaWiki 1.24.1</em></p> <p><img src="https://cdn.auth0.com/blog/benchmark/phpBB.png" alt="phpBB 3.1.3" /> <em>phpBB 3.1.3</em></p> <p><img src="https://cdn.auth0.com/blog/benchmark/wordpress.png" alt="Wordpress 4.1.1" /> <em>Wordpress 4.1.1</em></p> <p><img src="https://cdn.auth0.com/blog/benchmark/drupal.png" alt="Drupal 8" /> <em>Drupal 8</em></p> <p>From the results above, you can see that we can make double the amount of requests in less time in PHP 7 than PHP 5.</p> <p>These specs can be found in the <code>Speeding Up The Web With PHP 7</code> talk he gave at Fluent Conf, 2015.</p> <p>Check out the following benchmarks:</p> <ul> <li><a href="https://github.com/martin-helmich/php7-benchmarks">php7-benchmarks</a></li> <li><a href="https://kinsta.com/blog/the-definitive-php-7-final-version-hhvm-benchmark">php7 final version vs hhvm benchmark</a></li> <li><a href="http://blog.wpoven.com/2016/04/14/hhvm-vs-php-7-performance-showdown-wordpress-nginx">hhvm vs php7 performance show down - Wordpress, Nginx</a></li> </ul> <h2>Conclusion</h2> <p>We have successfully covered how to upgrade your development and server environments from PHP 5 to PHP 7, gone through the features PHP 7 offers and also migrated two apps from PHP 5 to PHP 7.</p> <p>Woot! Woot! It's been quite a journey highlighting everything PHP 7 has to offer. PHP has grown tremendously over the years from a toy language to a full-blown fast and enterprise language.</p> <p>The <a href="http://php.net/manual/en/index.php">PHP Manual</a> and <a href="https://wiki.php.net/RFC">RFC</a> documents remain the most complete go-to reference for any of the new PHP 7 features. You can always leverage them for more information.</p> Is Multifactor Authentication The Best Way To Secure Your Accounts? Myths And Reality 2017-02-08T12:31:00+00:00 https://auth0.com/blog/is-multifactor-authentication-the-best-way-to-secure-your-accounts-myths-and-reality/ Diego Poza https://twitter.com/diegopoza <h2>Intro</h2> <p>In recent years, multifactor authentication has become quite the buzzword in information security. Products from Twitter to Instagram have implemented their own two-step login processes, responding to widespread user demand for better security and the ever-present reality of hackers cracking accounts and selling them across the internet.</p> <p>All this popularity has also led to the creation and perpetuation of various myths about multifactor authentication — what it is, what it's for — that can mislead developers and users alike.</p> <p>Going with multifactor authentication is almost always going to be an improvement over not. But it's table stakes now. Sophisticated attackers aren't deterred by poorly configured multifactor authentication systems. To keep internal and user information secure, you need to know what you're doing.</p> <h2>Myth #1: There are only a few different forms of MFA</h2> <p>An authentication <a href="https://auth0.com/identity-glossary">factor</a> is a vector through which identity can be confirmed or denied, from fingerprint scanners to passwords, from USB sticks to PIN codes. The commonly used term “multifactor authentication” simply refers to an authentication scheme that uses <strong>more than one</strong> of these methods.</p> <p>It was once true that most MFA systems operated basically the same way. Today, however, there's a great variety of factors you can request from your users, from push notification receipt to SMS to email to fingerprint.</p> <h3>Reality: MFA is extremely customizable</h3> <p><img src="https://cdn.auth0.com/blog/mfa-myths/mfa-alternatives.png" alt="MFA alternatives" /></p> <p>There are three entire genres of factor—knowledge, possession, and inherence:</p> <ul> <li><strong>Knowledge:</strong> Something only a particular user knows, such as a password or the answer to a secret question.</li> <li><strong>Possession:</strong> Something only a particular user has, such as a USB stick or identifying badge.</li> <li><strong>Inherence:</strong> Someone only a particular user is, such as determined through a fingerprint scanner or GPS recognition system.</li> </ul> <p>Every multifactor authentication system out there is built upon some combination of these three basic factors. A simple password/secret question system would be made up of two separate knowledge factors, while one that asked you for an <a href="https://www.rsa.com/en-us/products-services/identity-access-management/securid/hardware-tokens">RSA hardware token</a> in addition to your password would be made up of both knowledge and possession factors.</p> <p>A passwordless login system relies upon you being in possession of, and able to access, your email inbox. And so on. There are so many different forms of authentication out there now that you can freely choose whether you want something that maximizes ease of use, something that maximizes security through obscurity, or something in between.</p> <h2>Myth #2: Your use case for MFA doesn't matter</h2> <p><a href="https://en.wikipedia.org/wiki/RSA_Security">RSA</a> and <a href="https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm">TOTP</a> are two of the most popular methods for generating secure codes that we have today, but they are not interchangeable — both have their pros and cons.</p> <p>The main technical difference between them is that RSA operates asymmetrically, with a public and a private key, and TOTP operates symmetrically, with a single private key shared between both parties. But this isn't just a minor detail about how the two systems work. This single difference affects the appropriate context for each one and the trade-offs you will be making.</p> <h3>Reality: You have to choose your method based on your needs</h3> <p>The security of the public/private key pair of RSA “relies on the computational difficulty of factoring large integers”:</p> <ol> <li>Two extremely large prime numbers are generated using the <a href="http://searchsecurity.techtarget.com/definition/RSA">Rabin-Miller primality test algorithm</a>.</li> <li>The public key is generated from the modulus of those two prime numbers and a public exponent.</li> <li>The private key is generated from the modulus of those two prime numbers and an exponent calculated with the Extended Euclidean algorithm.</li> </ol> <p>This also means that computational power is required to encrypt and decrypt RSA when it's used properly. That makes RSA slower, but the benefit is that only one side of the transaction needs to actually <a href="http://crypto.stackexchange.com/questions/11293/hmac-sha256-vs-rsa-sha256-which-one-to-use">possess the private key</a>.</p> <p>TOTP, on the other hand, operates symmetrically. A secret key is known to both the signer and the signee at the same time. A hash function is used to blend the secret key with the time at the moment of authentication (requiring fairly precise clock synchronization) and a one-time password is generated that is valid only for a short amount of time.</p> <p><img src="https://cdn.auth0.com/blog/mfa-myths/totp-screenshot.png" alt="TOTP screenshots" /></p> <p>This takes significantly less time and processing power than RSA, but it does mean certain vulnerabilities become hypothetically possible. If a key was somehow compromised on the server-side, for instance, an employee of an organization could potentially impersonate a user to malicious ends. With RSA, the same employee would have to <a href="http://crypto.stackexchange.com/questions/11293/hmac-sha256-vs-rsa-sha256-which-one-to-use">change the codebase</a> to do such a thing—likely leaving a paper trail.</p> <p>If you absolutely need your users to be able to download and store their private keys on their own systems—maybe you're working with <a href="http://resources.docs.salesforce.com/204/14/en-us/sfdc/pdf/salesforce_security_impl_guide.pdf">financial data</a> like credit cards, health records, or other forms of sensitive information—you may want to go with an asymmetric method like RSA.</p> <h2>Myth #3: All MFA solutions work basically the same way</h2> <p>Mass adoption of multifactor authentication is still a significant work in progress, and it's fair to say that most sites should simply focus on implementing it in some form or another—not which method is the absolute perfect one.</p> <p>That does not, however, mean that every single form of multifactor authentication is equally secure. Each occupies a different position on the axes of security and ease of use, which means that each one will be optimal under a different set of circumstances.</p> <h3>Reality: you have to choose what you value most</h3> <p>SMS is one of the older and more common forms of multifactor authentication that you see out there. You log in to a website, and then to double-check your identity, a code is sent to a phone number that you have on file. You receive a text on your mobile phone that contains a code, and then you enter that code into the website to verify yourself. Simple.</p> <p>But the U.S National Institute of Standards and Technology has recently come out with a report saying they believe that SMS multifactor is vulnerable to hijacking, <a href="http://thehackernews.com/2016/07/two-factor-authentication.html">particularly when used</a> by subscribers to a VoIP phone service like Google Voice. SMS is also vulnerable to social engineering—in some instances, attackers have been able to simply call up a victim's phone company and, impersonating their target, ask that all text messages to that account be forwarded to a different one.</p> <p>These vulnerabilities, plus the fact that other forms of authentication have become more user-friendly, mean that many sites and apps enabled with multifactor authentication are moving on to different methods.</p> <p><img src="https://cdn.auth0.com/blog/mfa-myths/apps-of-mfa.png" alt="Different multifactor alternatives" /></p> <p>There's the time-based one-time password algorithm, or TOTP, which is most notable used by apps like Google Authenticator. A single-use password is generated from the combination of a secret key and the current time, and you enter that into the app asking for authentication rather than a code that could have been intercepted in transmission.</p> <p>TOTP, because it often involves users manually copying a six-digit code from their phone to their computer, is often considered to be a burden on users. With <a href="https://auth0.com/docs/rules">Auth0 Rules</a>, though, you can get the benefit of MFA without that annoyance by setting up special conditions under which authentication will be requested.</p> <p>Say someone tries to call your bank's customer support to reset your password — as they did to <a href="https://auth0.com/blog/how-paypal-could-have-avoided-account-hack/">Brian Krebs</a> — that event could be flagged as requiring a temporary extra authentication. You could trigger the same kind of request in the event of a new email account being added, an address being changed, and the like. This will keep your users' personal information and account more secure without disrupting their usage of your product, as they likely won't be performing these kinds of actions very often.</p> <h2>Myth #4: MFA is always annoying for users</h2> <p>At many companies where multifactor authentication is tried but fails, one of the most common complaints is that it makes logging in too much of a hassle for users.</p> <p>They have to first enter in their username and password, and <em>then</em> open up their email client or take out their phone, and <em>then</em> manually copy a code. Or they lose the hardware key that they were given during onboarding, or they misplace their mobile device and are no longer able to login to anything.</p> <p> These companies get so many annoyed emails from their employees, or start noticing users forgetting their passwords and consequently churning, that they finally turn MFA off.</p> <h3>Reality: MFA can be as easy as tapping a push notification</h3> <p>MFA does not have to be troublesome for users. It doesn't have to require keeping track of a token, manually writing a code, or copying and pasting a code from a mobile device to your computer.</p> <p>With <a href="https://auth0.com/guardian/">Auth0 Guardian</a>, you can make logging in through multifactor authentication a simple matter of swiping and tapping a push notification from your <a href="https://auth0.com/blog/announcing-Auth0-Guardian-a-new-way-to-login/">phone's lock screen</a>.</p> <p><img src="https://cdn.auth0.com/blog/mfa-myths/auth0-guardian-mfa.png" alt="Auth0's Guardian App" /></p> <p>It's available for both iOS and Android, and can be enabled with a <a href="https://auth0.com/guardian">simple toggle</a>. Check out the full docs <a href="https://auth0.com/docs/multifactor-authentication/guardian">here</a>.</p> <h2>Myths Busted</h2> <p>There's no doubt that implementing multifactor authentication is one of the best ways to improve the security of a website or an app that doesn't have it. But as with any decision regarding the privacy and security of your users and their information, nothing is as simple as it appears at first glance.</p> <p>At <a href="https://auth0.com/">Auth0</a>, we want to make sure that MFA is something you can implement knowing that it will protect your accounts without harming the user experience. With <a href="https://auth0.com/guardian/">Guardian</a>, we're pushing that project forward, and we're really excited to have you try it out. Check it out!</p> Migrating a PHP 5 App to PHP 7 (Rundown of PHP 7 Features) - Part 2 2017-02-07T08:30:00+00:00 https://auth0.com/blog/migrating-a-php5-app-to-php7-part-two/ Prosper Otemuyiwa https://twitter.com/unicodeveloper <hr /> <p><strong>TL;DR:</strong> Many PHP applications are still running on PHP 5.x, not ready to take full advantage of the awesome features that PHP 7 offers. A lot of developers have not made the switch because of certain fears of compatibility issues, migration challenges and the strange awkward feeling that migrating will take away a big chunk of their time. In the <a href="https://auth0.com/blog/migrating-a-php5-app-to-php7-part-one">first part of this tutorial</a> we learned how to set up a PHP 7 development environment. This time, we'll learn about all the new PHP 7 features and how you can leverage them when migrating your PHP 5 app to PHP 7.</p> <hr /> <h2>PHP 7 Features</h2> <h3>Scalar Type Declaration</h3> <p>With PHP 5, you could typehint a function parameter with Classes, Interfaces, callable and array types only. For example, if you want a parameter of a certain type <code>string</code> to be passed into a function, you would have to do a check within the function like so:</p> <pre><code class="php"> // php 5 function getBookNo($number) { if (! is_integer($number)) { throw new Exception("Please ensure the value is a number"); } return $number; } getBookNo('boooks'); </code></pre> <p>PHP 7 eliminates the need for the extra check. With PHP 7, you can now typehint your function parameters with <code>string</code>, <code>int</code>, <code>float</code>, and <code>bool</code>.</p> <pre><code class="php"> // PHP 7 function getBookNo(int $number) { return $number; } getBookNo('boooks'); // Error raised PHP Fatal error: Uncaught TypeError: Argument 1 passed to getBookNo() must be of the type integer, string given, called in .... </code></pre> <p>PHP 7 will throw a Fatal error as seen above once you typehint with scalar values.</p> <h3>Strong Type Check</h3> <p>By default, PHP 5 and 7 allow for coercion when dealing with operations such as numeric strings. An example is this:</p> <pre><code class="php"> function getBookNo(int $number) { return "This is it: " . $number; } echo getBookNo("8"); // Result This is it: 8 </code></pre> <p>I passed in a string and it coerced it to an integer and allowed it to run successfully. Now in PHP 7, you can be strict and ensure no form of automatic conversion occurs by declaring a strict mode at the top of your PHP file like so:</p> <pre><code class="php">declare(strict_types=1); function getBookNo(int $number) { return "This is it: " . $number; } echo getBookNo("8"); // Result PHP Fatal error: Uncaught TypeError: Argument 1 passed to getBookNo() must be of the type integer, string given, called in ...... </code></pre> <p>In PHP 5, if you pass in a float value, it automatically strips out the decimal parts and leaves you with an integer. Now in PHP 7, If you pass in a float value too, it will throw a Fatal error. When building a financial application, this feature comes in handy!</p> <p>Remember something like this in JavaScript? where you have to write <code>use "strict";</code> at the top of your JavaScript file.</p> <h3>Return Type Declaration</h3> <p>PHP 7 supports return types for functions. This feature has been available in several strongly typed languages for a long time. Now, you can easily enforce a function to return a certain type of data like so:</p> <pre><code class="php"> function divideValues(int $firstNumber, int $secondNumber): int { $value = $firstNumber / $secondNumber; return $value; } echo divideValues(8, 9); // Result 0 </code></pre> <p>In the function above, we want the return value to be an integer, regardless of whatever the division turns out to be. Now the default weak(coercive) type checking in PHP comes to play again here. The value returned should be a float and it should throw a Fatal Type Error but it is automatically coerced into an integer.</p> <p>Enable strict mode by placing <code>declare(strict_types=1);</code> at the top of the file and run it again. It should throw a PHP Fatal Type error like so:</p> <pre><code class="bash"> PHP Fatal error: Uncaught TypeError: Return value of divideValues() must be of the type integer, float returned in ..... </code></pre> <h3>Spaceship Operator</h3> <p>PHP 7 ships with a new operator, <strong>&lt;=></strong>, for simplifying the evaluation of arithmetic operations. With this operator, it is easier to evaluate less than, equal to, or greater than. The results will either be -1, 0 or 1. Ruby and PERL programmers are familiar with this operator.</p> <p>This is how it works. If we have two operands $x and $y, and we do <code>$x &lt;=&gt; $y</code>, then</p> <ul> <li>if $x is less than $y, the result will be -1</li> <li>if $x equals $y, the result will be 0</li> <li>if $x is greater than $y, the result will be 1</li> </ul> <pre><code class="php"> function evaluate($x, $y) { return $x &lt;=&gt; y; } evaluate(9, 8); // Result 1 </code></pre> <p>Good real world cases for this operator is in the simplification of comparison methods and using it for switch operations like so:</p> <pre><code class="php"> $data = [ ['name' =&gt; 'Ado', 'cars' =&gt; 2], ['name' =&gt; 'Tony', 'cars' =&gt; 4], ['name' =&gt; 'Ramirond', 'cars' =&gt; 3], ['name' =&gt; 'Woloski', 'cars' =&gt; 12] ]; function sortByCars($x, $y) { return $x['cars'] &lt;=&gt; $y['cars']; } usort($data, 'sortByCars'); print_r($data); // Result Array ( [0] =&gt; Array ( [name] =&gt; Ado [cars] =&gt; 2 ) [1] =&gt; Array ( [name] =&gt; Ramirond [cars] =&gt; 3 ) [2] =&gt; Array ( [name] =&gt; Tony [cars] =&gt; 4 ) [3] =&gt; Array ( [name] =&gt; Woloski [cars] =&gt; 12 ) ) </code></pre> <p>It sorted the array easily with less code. Without the spaceship operator, I would have to write the <code>sortByCars</code> method like so:</p> <pre><code class="php"> function sortByCars($x, $y) { if ($x['cars'] == $y['cars']) { return 0; } return ($x['cars'] &lt; $y['cars']) ? -1 : 1; } </code></pre> <h3>Array Constants</h3> <p>Before now, constants defined with the <code>define()</code> method can only accept scalar values. In PHP 7, you can have constant arrays using the <code>define()</code> method like so:</p> <pre><code class="php"> // PHP 7 define('CARS', [ 'fine' =&gt; 'Mercedes', 'strong' =&gt; 'Volkswagen', 'ugly' =&gt; 'chevrolet' ]); echo CARS['fine']; // Result Mercedes </code></pre> <h3>Group Use Declarations</h3> <p>Group use declaration helps make the code shorter and simpler. Before now, if you are trying to use multiple classes, functions and constants from the same namespace, you have to write it like so:</p> <pre><code class="php"> // PHP 5 namespace Unicodeveloper\Emoji; use Unicodeveloper\Emoji\Exceptions\UnknownMethod; use Unicodeveloper\Emoji\Exceptions\UnknownEmoji; use Unicodeveloper\Emoji\Exceptions\UnknownUnicode; use Unicodeveloper\Emoji\Exceptions\UnknownIsNull; use function Unicodeveloper\Emoji\Exceptions\checkForInvalidEmoji; use const Unicodeveloper\Emoji\Exceptions\INVALID_EMOJI; class Emoji { } </code></pre> <p>With PHP 7, you can group them like so:</p> <pre><code class="php"> // PHP 7 namespace Unicodeveloper\Emoji; use Unicodeveloper\Emoji\Exceptions\{ UnknownMethod, UnknownEmoji, UnknownUnicode, IsNull, function checkForInvalidEmoji, const INVALID_EMOJI }; class Emoji { } </code></pre> <h3>Anonymous Classes</h3> <p>An Anonymous class is essentially a local class without a name. Anonymous classes offer the ability to spin up throwaway objects. These objects have closure-like capabilities. An anonymous class is defined like so:</p> <pre><code class="php"> new class($constructor, $args) { } </code></pre> <p>A real world case is a situation where you want to have objects that implement some interfaces on the fly, rather than having several files, where you have to define the class and then instantiate it, you can leverage anonymous classes like so:</p> <pre><code class="php"> $meme = new class implements MemeInterface { public function memeForm($form) { return $form; } }; $app = new App($meme); </code></pre> <h3>Enhanced Unicode Support</h3> <p>In PHP 7, all you need is the hexadecimal code appended to "\u" and you'll have your symbol/emoji as an output. An example is this:</p> <pre><code class="php"> function getMoney() { echo "\u{1F4B0}"; } getMoney(); // Result 💰 </code></pre> <p>The enhancements were made possible from the <a href="https://wiki.php.net/rfc/unicode_escape">Unicode Codepoint Escape Syntax RFC</a>.</p> <p>Now, you can also get the name equivalent of the unicode character, say "\u{1F4B0}" via the new <code>IntlChar</code> class like so:</p> <pre><code class="php"> echo IntlChar::charName("\u{1F4B0}"); </code></pre> <p>You can get the character from the name like so:</p> <pre><code class="php"> var_dump(IntlChar::charFromName("LATIN CAPITAL LETTER A")); var_dump(IntlChar::charFromName("SNOWMAN")); var_dump(IntlChar::charFromName("TURTLE")); </code></pre> <blockquote><p><strong>Note:</strong> The IntlChar class contains about 600 constants and 59 static methods.</p></blockquote> <p>This was made possible from the <a href="https://wiki.php.net/rfc/intl.char">IntlChar RFC</a>. The PHP manual has extensive documentation on <a href="http://php.net/manual/en/class.intlchar.php">IntlChar</a> class.</p> <h3>Null Coalescing Operator</h3> <p>The purpose of this new operator, <strong>??</strong>, is to allow developers to set values from user inputs without having to check if the value has been set. Before PHP 7, this is how you evaluate input. Check this out:</p> <pre><code class="php"> $occupation = isset($_GET['occupation']) ? $_GET['occupation'] : 'bricklayer'; </code></pre> <p>If the value of <code>$_GET['occupation']</code> exists, it returns the value else it assigns <code>bricklayer</code> to the $occupation variable. In PHP 7, you can simply shorten that line of code using the <strong>??</strong> operator like so:</p> <pre><code class="php"> // PHP 7 $occupation = $_GET['occupation'] ?? 'bricklayer'; </code></pre> <p>It automatically checks whether the value is set and assigns the value to <code>$occupation</code> variable if it is, else it returns <code>bricklayer</code>.</p> <p>The Null coalescing operator also allows you to chain expressions like so:</p> <pre><code class="php"> // PHP 7 $_ENV['occupation'] = 'software engineer'; $occupation = isset($_GET['occupation']) ?? $_ENV['occupation'] ?? 'bricklayer'; // Result software engineer </code></pre> <p>This will assign the first defined value to the <code>$occupation</code> variable.</p> <h3>Closure on Call</h3> <p>There is now a better and more performant way of binding an object scope to a closure and calling it. Before PHP 7, you would bind an object to a closure like so:</p> <pre><code class="php"> class NameRegister { private $name = "Prosper"; } // Closure $getName = function() { return $this-&gt;name; }; $getTheName = $getName-&gt;bindTo(new NameRegister, 'NameRegister'); echo $getTheName(); </code></pre> <p>With PHP 7, you now have a <code>call</code> method on the Closure class. So you can bind an object to a closure easily like so:</p> <pre><code class="php"> class NameRegister { private $name = "Prosper"; } $getName = function() { echo $this-&gt;name; }; $getName-&gt;call(new NameRegister()); </code></pre> <p>Check out the <a href="https://secure.php.net/manual/en/closure.call.php">PHP Manual: Closure::call</a> for more information.</p> <h3>Expectations and Assertions</h3> <p>Assertions are a debugging and development feature. The <code>assert()</code> function in PHP 7 is now a language construct, where the first parameter can also be an expression instead of just been a string or boolean. They have been optimized to have zero cost in production. You can now enable or disable assertions from the PHP_INI file like so:</p> <pre><code class="php"> zend.assertions = 1 // Enable assertion zend.assertions = 0 // Disable assertion zend.assertions = -1 // (production mode), don't generate or execute code </code></pre> <p>Assertions can now throw an Exception when it fails. You can enable that from the INI file like so:</p> <pre><code class="php"> assert.exceptions = 1 // Throw exceptions // or assert.exceptions = 0 // Issue warnings, which has always been the case. </code></pre> <p>The <code>assert()</code> can now take in two arguments where the second argument is a custom error message. It can also be an instance of an <code>Exception</code>. An example is shown below:</p> <pre><code class="php"> class ProjectException extends AssertionError {} public function checkAuthenticityOfProject() { /* ... */ assert('$project instanceof \Unicodeveloper\Project', new ProjectException('$project was not a Project object')); } </code></pre> <blockquote><p><strong>Note:</strong> With this new feature, you might not need to depend on assertion libraries anymore while developing and testing your code.</p></blockquote> <p>Check out the <a href="https://wiki.php.net/rfc/expectations">Expectations RFC</a> for more information.</p> <h3>Error Handling</h3> <p>Many fatal and recoverable fatal errors have been converted to exceptions in PHP 7. Most errors are now reported by throwing <code>Error</code> exceptions. The <code>Exception</code> class now implements a <code>Throwable</code> Interface.</p> <p><em>Hierarchy</em></p> <pre><code class="bash"> \Throwable ├── \Exception (implements \Throwable) │ ├── \LogicException | │ │ \BadFunctionCallException │ | | └── \BadMethodCallException │ │ |── \DomainException | | ├── \InvalidArgumentException | | ├── \LengthException | | └── \OutOfRangeException │ │ │ | | └── \RuntimeException │ ├── \OutOfBoundsException │ ├── \OverflowException │ ├── \RangeException │ ├── \UnderflowException │ └── \UnexpectedValueException └── \Error (implements \Throwable) ├── \AssertionError ├── \ArithmeticError ├── \DivisionByZeroError ├── \ParseError └── \TypeError </code></pre> <p>So you can catch specific Errors like so:</p> <pre><code class="php"> try { // evaluate something } catch (\ParseError $e) { // do something } </code></pre> <p>Earlier in this article, we were evaluating scalar type hinting and PHP 7 threw TypeErrors. Remember? Yes, that's how cool PHP 7 is now!</p> <p>In PHP 7.1, you can catch multiple errors and exceptions in one catch block like so:</p> <pre><code class="php"> try { // Some code... } catch (ExceptionTypeA | ExceptionTypeB | ExceptionTypeC $e) { // Code to handle the exception } catch (\Exception $e) { // ... } </code></pre> <p>This is particular useful when one method throws different type of exceptions that you can handle the same way.</p> <blockquote><p><strong>Note:</strong> A new <code>error_clear_last()</code> method has been added to clear the most recent error. Once used, calling <code>error_get_last()</code> will be unable to retrieve the most recent errors.</p></blockquote> <p>Check out the <a href="https://wiki.php.net/rfc/multiple-catch">Catching Multiple Exception Types</a> RFC.</p> <h3>Integer Division</h3> <p>PHP 7 introduced a new function <code>intdiv()</code> which returns the result of an integer division operation as int.</p> <pre><code class="php"> // PHP 7 $result = intdiv(10, 4); // Result: 2 </code></pre> <h3>Regular Expressions</h3> <p>Handling regular expressions just got easier in PHP 7. A new <code>preg_replace_callback_array()</code> function has been added to perform a regular expression search and replace using callbacks.</p> <pre><code class="php"> $message = 'Haaaalaaaaaa, Girls and people of Instagrant'; preg_replace_callback_array( [ '~[a]+~i' =&gt; function ($match) { echo strlen($match[0]), ' matches for "a" have been found'; }, '~[b]+~i' =&gt; function ($match) { echo strlen($match[0]), ' matches for "b" found'; }, '~[p]+~i' =&gt; function ($match) { echo strlen($match[0]), ' matches for "p" found'; } ], $message ); // Result 4 matches for "a" have been found 6 matches for "a" have been found 1 matches for "a" have been found 1 matches for "a" have been found 1 matches for "a" have been found 1 matches for "p" found 1 matches for "p" found </code></pre> <h3>Filtered unserialize()</h3> <p>The <code>unserialize()</code> function has been existing since PHP 4. It allows you to take a single serialized variable and convert back into a PHP value.</p> <p>In PHP 7, the <strong>options</strong> parameter has been added. You can now whitelist classes that can be unserialized like so:</p> <pre><code class="php"> // converts all objects into __PHP_Incomplete_Class object unserialize($obj, ["allowed_classes" =&gt; false]); // converts all objects into __PHP_Incomplete_Class object except those of FirstClass and SecondClass unserialize($obj, ["allowed_classes" =&gt; ["FirstClass", "SecondClass"]]); // default behaviour (same as omitting the second argument) that accepts all classes unserialize($obj, ["allowed_classes" =&gt; true]); </code></pre> <p>It was introduced to enhance security when unserializing objects on untrusted data.</p> <blockquote><p><strong>Note:</strong> In PHP 7.1, the <code>allowed_classes</code> element of the <strong>options</strong> parameter is now strictly typed. <code>unserialize()</code> returns false if anything other than an array or boolean is given.</p></blockquote> <h3>Cryptographically Secure Pseudorandom Number Generator (CSRPNG)</h3> <p><code>random_bytes()</code> and <code>random_int()</code> have been added to the CSRPNG functions in PHP 7.</p> <ul> <li><code>random_bytes()</code> returns a random string of a given length</li> <li><code>random_int()</code> returns a random integer from a range</li> </ul> <pre><code class="php"> random_bytes(12); random_int(0, 5000); </code></pre> <h3>Generator Delegation and Return Expressions</h3> <p>Generators were introduced in PHP 5.5. Prior to PHP 7, if you tried to return anything, an error would be thrown. Now, you can use a <code>return</code> statement within a generator.</p> <p>You can get the returned value by calling the <code>Generator::getReturn()</code> method. Look at the code below:</p> <pre><code class="php"> $square = function (array $number) { foreach($number as $num) { yield $num * $num; } return "Done calculating the square. What next?"; }; $result = $square([1,2,3,4,5]); foreach($result as $value) { echo $value . PHP_EOL; } echo $result-&gt;getReturn(); // grab the return value // RESULT 1 4 9 16 25 Done calculating the square. What next? </code></pre> <p>Generators can now delegate to another generator by using <code>yield from</code> like so:</p> <pre><code class="php"> function square(array $number) { foreach($number as $num) { yield $num * $num; } yield from addition($number); }; function addition(array $number) { foreach($number as $num) { yield $num + $num; } } foreach(square([1,2,3,4,5]) as $value) { echo $value . PHP_EOL; } // Result 1 4 9 16 25 2 4 6 8 10 </code></pre> <h3>session_start config enhancements</h3> <p>The <code>session_start()</code> method now accepts an array of values that can override the session config in php.ini file.</p> <p><code>session.lazy_write</code> which is on by default can be turned off by explicitly stating it in the <code>session_start()</code> method like so:</p> <pre><code class="php"> session_start([ 'lazy_write' =&gt; false, 'cache_limiter' =&gt; 'private' ]); </code></pre> <h3>Unpack objects with list()</h3> <p>The <code>list()</code> language construct now allows you to unpack objects implementing the <em>ArrayAccess</em> interface.</p> <pre><code class="php"> $fruits = new ArrayObject(['banana', 'mango', 'apple']); list($a, $b, $c) = $fruits; echo $a. PHP_EOL; echo $b. PHP_EOL; echo $c. PHP_EOL; // Result banana mango apple </code></pre> <blockquote><p><strong>Note:</strong> In PHP 7.0.0 list() expressions can no longer be completely empty. In PHP 5, list() assigns the values starting with the right-most parameter. In PHP 7, list() starts with the left-most parameter. This is true when working with arrays with indices.</p></blockquote> <h3>Accessing Static Values</h3> <p>In PHP 5.x, if you try to access a static value like so:</p> <pre><code class="php"> class Auth0 { static $lock = 'v10'; } echo 'Auth0'::$lock; // Result Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM), expecting ',' or ';' in ..... </code></pre> <p>Now, In PHP 7.x, it throws no error, it simply works!</p> <pre><code class="php"> // PHP 7 class Auth0 { static $lock = 'v10'; } echo 'foo'::$lock; // Result v10 </code></pre> <h3>dirname() enhancement</h3> <p>The <code>dirname()</code> in PHP 5 returns a parent directory's path. In PHP 7.0.0, an optional <em>levels</em> parameter has been added to the function to allow you as developer determine how many levels up you want to go when getting a path.</p> <pre><code class="php"> $path = '/Unicodeveloper/source/php-workspace/laravel/vavoom'; dirname($path, 3); // Result /Unicodeveloper/source </code></pre> <h3>Uniform Variable Syntax</h3> <p>This brings a much needed change to the way variable-variable expressions are constructed. It allows for a number of new combinations of operators that were previously disallowed, and so introduces new ways to achieve old operations in a more polished code.</p> <pre><code class="php"> // nesting :: $foo::$bar::$baz // access the property $baz of the $foo::$bar property // nesting () foo()() // invoke the return of foo() // operators on expressions enclosed in () (function () {})() // IIFE syntax from JS </code></pre> <pre><code class="php"> // old meaning // new meaning $$foo['bar']['baz'] ${$foo['bar']['baz']} ($$foo)['bar']['baz'] $foo-&gt;$bar['baz'] $foo-&gt;{$bar['baz']} ($foo-&gt;$bar)['baz'] $foo-&gt;$bar['baz']() $foo-&gt;{$bar['baz']}() ($foo-&gt;$bar)['baz']() Foo::$bar['baz']() Foo::{$bar['baz']}() (Foo::$bar)['baz']() </code></pre> <h3>Reserved Words</h3> <p>PHP 7 now allows globally reserved words such as <code>new</code>, <code>private</code>, <code>for</code> as property, constant, and method names within classes, interfaces, and traits.</p> <pre><code class="php"> class Car { private $type, $who, $costs; public function new($carType) { $this-&gt;type = $carType; return $this; } public function for($who) { $this-&gt;who = $who; return $this; } public function costs($price) { $this-&gt;price = $price; return $this; } public function __toString() { return $this-&gt;type . ' ' . $this-&gt;who . ' ' . $this-&gt;price. PHP_EOL; } } $car = new Car(); echo $car-&gt;new('Mercedes Benz')-&gt;for('Wife')-&gt;costs(14000); // Result Mercedes Benz Wife 14000 </code></pre> <h3>Reflection API Enhancements</h3> <p>PHP 7 introduces two new reflection classes. One is the <code>ReflectionGenerator</code> class that reports information about generators and the other is the <code>ReflectionType</code> class that reports information about a function's return type.</p> <p><em>ReflectionType API</em></p> <ul> <li><code>ReflectionType::allowsNull</code> — Checks if null is allowed</li> <li><code>ReflectionType::isBuiltin</code> — Checks if it is a built-in type</li> <li><code>ReflectionType::__toString</code> - gets the parameter type name</li> </ul> <p><em>ReflectionGenerator API</em></p> <ul> <li><code>ReflectionGenerator::__construct</code> — Constructs a ReflectionGenerator object</li> <li><code>ReflectionGenerator::getExecutingFile</code> — Gets the file name of the currently executing generator</li> <li><code>ReflectionGenerator::getExecutingGenerator</code> — Gets the executing Generator object</li> <li><code>ReflectionGenerator::getExecutingLine</code> — Gets the currently executing line of the generator</li> <li><code>ReflectionGenerator::getFunction</code> — Gets the function name of the generator</li> <li><code>ReflectionGenerator::getThis</code> — Gets the $this value of the generator</li> <li><code>ReflectionGenerator::getTrace</code> — Gets the trace of the executing generator</li> </ul> <p>Two new methods have also been added to the <code>ReflectionParameter</code> and <code>ReflectionFunctionAbstract</code> classes.</p> <p><em>ReflectionParameter API</em></p> <ul> <li><code>ReflectionParameter::hasType</code> - Checks if parameter has a type</li> <li><code>ReflectionParameter::getType</code> - Gets a parameter's type</li> </ul> <p><em>ReflectionFunctionAbstract API</em></p> <ul> <li><code>ReflectionFunctionAbstract::hasReturnType</code> - Checks if the function has a specified return type.</li> <li><code>ReflectionFunctionAbstract::getReturnType</code> — Gets the specified return type of a function</li> </ul> <h3>Deprecated Features</h3> <p>Using deprecated features in PHP will trigger an <code>E_DEPRECATED</code> error.</p> <ul> <li><p>PHP 4 Style constructors are deprecated, and will be removed in the future. An example of a PHP 4 style of writing constructors(having the same name with the class) is this:</p> <pre><code class="``php"> class Economy { function economy() { /* ... */ } } </code></pre></li> <li><p>Static calls to methods that are actually not <em>static</em> are deprecated.</p> <pre><code class="``php"> class Economy { function affordPrimaryEducation() { echo 'I think I might not be able to afford it with this economy'; } } Economy::affordPrimaryEducation(); // Result Deprecated: Non-static method Economy::affordPrimaryEducation() should not be called statically in ...... </code></pre></li> <li><p>The salt option for the <code>password_hash()</code> function has been deprecated to prevent developers from generating their own salts which are mostly insecure.</p></li> <li><p>The <code>capture_session_meta</code> SSL context option has been deprecated. <code>stream_get_meta_data()</code> can now be used to get SSL metadata.</p></li> <li><p>The <code>ldap_sort()</code> function has been deprecated.</p></li> <li><p>The alternative PHP tags shown below have been removed:</p> <p> <em>PHP Script tags</em></p> <pre><code class="``js"> &lt;script language="php"&gt; &lt;/script&gt; </code></pre> <p> <em>PHP ASP tags</em></p> <pre><code class="``php"> &lt;% %&gt; </code></pre></li> </ul> <h3>Backward Incompatible Changes</h3> <p>Here are backward incompatible changes you should be aware of:</p> <ul> <li><em>set_exception_handler()</em> is no longer guaranteed to receive Exception objects</li> <li>Internal constructors always throw exceptions on failure: Prior to PHP 7, some internal classes would return <strong>NULL</strong> when the constructor failed. Now, they will throw an <em>Exception</em>.</li> <li>Error handling for <code>eval()</code> should now include a catch block that can handle the <a href="https://php.net/manual/en/class.parseerror.php">ParseError</a> object.</li> <li><p>The almighty <code>E_STRICT</code> notices now have new behaviors. It's no longer too strict.</p> <p> <img src="https://cdn.auth0.com/blog/estrict/notice.png" alt="E_Strict notice" /></p></li> <li><p><code>list()</code> can no longer unpack string variables. <code>str_split()</code> should be used when performing this form of operation.</p></li> <li><code>global</code> can no longer accept <em>variable variables</em> unless you fake it by using the curly brace like so <code>global ${$foo-&gt;bar}</code>.</li> <li>An <code>E_WARNING</code> will be emitted and <strong>NULL</strong> will be returned when internal functions try to perform float to integer automatic conversions.</li> <li>Prefixing comments with <code>#</code> in <code>php.ini</code> file is no longer allowed. Only semi-colons(;) should be used.</li> <li>Dividing by 0 will emit an <code>E_WARNING</code> and also one of either <code>+INF</code>, <code>-INF</code>, or <code>NAN</code>.</li> <li><code>$HTTP_RAW_POST_DATA</code> was deprecated in PHP 5.6.0 and finally removed in PHP 7.0.0. Use <a href="https://php.net/manual/en/wrappers.php.php#wrappers.php.input">php://input</a> as a replacement.</li> <li>Switch statements can no longer have multiple default blocks. An <strong>E_COMPILE_ERROR</strong> will be triggered if you try to define more than one default block.</li> <li>Functions can not have multiple parameters with the same name. <code>function slap($hand, $hand, $strength)</code>. An <strong>E_COMPILE_ERROR</strong> will be triggered as a result of this function.</li> <li>Static calls made to a non-static method with an incompatible context will now result in the called method having an undefined <code>$this</code> variable and a deprecation warning being issued.</li> </ul> <p>You can check out the few other <a href="https://secure.php.net/manual/en/migration70.changed-functions.php">PHP core functions</a> that have changed.</p> <h3>Removed Extensions and SAPIs</h3> <p>The <code>ext/mysql</code>, <code>ext/mssql</code>, <code>ereg</code> and <code>sybase_ct</code> extensions have been removed. All the <code>mysql_</code> functions have been removed! You should either use the <code>ext/mysqli</code> extension or use the <code>ext/pdo</code> extension which is has an object-oriented API.</p> <p>The <code>aolserver</code>, <code>apache</code>, <code>apache_hooks</code>, <code>apache2filter</code>, <code>caudium</code>, <code>continuity</code>, <code>isapi</code>, <code>milter</code>, <code>nsapi</code>, <code>phttpd</code>, <code>pi3web</code>, <code>roxen</code>, <code>thttpd</code>, <code>tux</code> and <code>webjames</code> SAPIs have been removed.</p> <h2>Conclusion</h2> <p>We have successfully covered all the new features of PHP 7. It might be overwhelming at first because it is a major version with a lot of new features, and lots of deprecations.</p> <p>Going over the rundown of all these features as highlighted in this article and using it as a handy reference will give you all the necessary information to migrate your PHP 5 apps to PHP 7.</p> <p>Thanks to the PHP Manual and RFC documents. You can always reference them for more information.</p> <p>In the next and final part of this series, we'll convert a small PHP 5 app to PHP 7, then measure and report the performance difference.</p> Customizing create-react-app: How to Make Your Own Template 2017-02-06T08:30:00+00:00 https://auth0.com/blog/how-to-configure-create-react-app/ Prosper Otemuyiwa https://twitter.com/unicodeveloper <hr /> <p><strong>TL;DR:</strong> There are several tools available for developers to aid the building of various types of websites and applications. One such tool is <a href="https://github.com/facebookincubator/create-react-app"><strong>Create React App(CRA)</strong></a>, the CLI tool that helps JavaScript developers create react apps with no build configuration. As awesome as <strong>CRA</strong> is, developers still need a way of tweaking, adding special scripts and modules that doesn't come bundled with <strong>CRA</strong>. Today, I'll teach you how to create custom <code>create-react-app</code> scripts for you and your team!</p> <hr /> <p>Many developers already use <a href="https://github.com/facebookincubator/create-react-app">create-react-app</a> to build their React applications, but like I mentioned earlier, developers are still screaming for more configuration options! Some are interested in having support for:</p> <ul> <li>PostCSS</li> <li>CSS Modules</li> <li>LESS</li> <li>SASS</li> <li>ES7</li> <li>MobX</li> <li>Server Rendering</li> </ul> <p>..and a lot more out of the box!</p> <p>A lot of developers, including JavaScript newbies create <em>React</em> apps from scratch daily, so the <em>CRA</em> team at Facebook built the <em>create-react-app</em> tool to make the process of creating such apps less tedious and error-prone.</p> <p>As a developer that needs support for some of the technologies I highighted earlier, one way of going about it is running <code>npm run eject</code>. This command copies all the config files and dependencies right into your project, then you can manually configure your app with all sorts of tools to satisfaction.</p> <p>One major challenge developers might face with <em>eject</em> is not been able to enjoy the future features of <em>CRA</em> . Another challenge with <em>eject</em> would be ineffecient synchronised setup across React developers working in team. One great way of solving this later challenge is publishing a fork of <code>react-scripts</code> for your team, then all your developers can just run <code>create-react-app my-app --scripts-version mycompany-react-scripts</code> and have the same setup across board. Let's learn how to accomplish that!</p> <h2>Create a Fork</h2> <p>Open up your GitHub repo and fork the <a href="https://github.com/facebookincubator/create-react-app">create-react-app repo</a></p> <p><img src="https://cdn.auth0.com/blog/cra/fork.png" alt="Creating a fork of create-react-app" /> <em>Creating a fork of create-react-app</em></p> <p>Inside the <code>packages</code> directory, there is a folder called <code>react-scripts</code>. The <code>react-scripts</code> folder contains scripts for building, testing and starting your app. In fact, this is where we can tweak, configure and add new scripts and templates.</p> <h2>Tweak the Configuration</h2> <p>Clone the directory and open up the <code>react-scripts/scripts/init.js</code> in your code editor. Let's add some few console messages like so:</p> <pre><code class="js"> ...... ...... console.log(chalk.red('VERY IMPORTANT:')); console.log('Create a .env file at the root of your project with REACT_APP_EMPLOYEE_ID and REACT_APP_POSITION_ID'); console.log(' You can find these values in the company dashboard under application settings.'); console.log(' https://company.bamboohr.com/settings'); console.log(); ....... </code></pre> <p><img src="https://cdn.auth0.com/blog/cra/important-messages.png" alt="Block to add important message" /> <em>Add the important message during installation here</em></p> <p><img src="https://cdn.auth0.com/blog/cra/added_message.png" alt="Important Message added to Installation process" /> <em>Added important message to show during installation</em></p> <p><strong>Now, Let's change templates</strong></p> <p>Open up <code>react-scripts/template/src/App.js</code> and replace it with this:</p> <pre><code class="js"> import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class App extends Component { getEnvValues() { if (!process.env.REACT_APP_EMPLOYEE_ID || !process.env.REACT_APP_POSITION_ID) { throw new Error('Please define `REACT_APP_EMPLOYEE_ID` and `REACT_APP_POSITION_ID` in your .env file'); } const employeeID = process.env.REACT_APP_EMPLOYEE_ID const position = process.env.REACT_APP_POSITION_ID; return { employeeID, position }; } render() { const { employeeID, position } = this.getEnvValues(); return ( &lt;div className="App"&gt; &lt;div className="App-header"&gt; &lt;img src={logo} className="App-logo" alt="logo" /&gt; &lt;h2&gt;Welcome to Unicode Labs&lt;/h2&gt; &lt;/div&gt; &lt;p className="App-intro"&gt; &lt;b&gt; Employee ID: { employeeID } &lt;/b&gt;&lt;br/&gt;&lt;br/&gt; &lt;b&gt; Position: { position } &lt;/b&gt; &lt;/p&gt; &lt;/div&gt; ); } } export default App; </code></pre> <p>Now, go to <code>react-scripts/template/public</code> directory. Open the <code>index.html</code> file and change the value of the <code>&lt;title&gt;</code> tag to <code>Unicode Labs</code>.</p> <p>You can also change the favicon to your company's favicon. You can change as many things as you want and add custom components that your team uses frequently.</p> <p>Create an <code>.env.example</code> in the <code>react-scripts/template</code> directory that contains the following:</p> <pre><code class="bash"> REACT_APP_EMPLOYEE_ID='44566' REACT_APP_POSITION_ID='ENGR' </code></pre> <p>A user will have to rename it to <code>.env</code> once the <code>create-react-app</code> tool is done installing the <code>react-scripts</code>. You should add this instruction to the <code>README</code> file.</p> <p><strong>Note:</strong> <em>CRA</em> already includes support for custom env variables if you're open to prefixing their names with <strong>REACT_APP</strong>.</p> <p>That's all we need!</p> <h2>Publish react-scripts to NPM</h2> <p>Before publishing to npm, we need to change the value of the <code>name</code> key of the <code>package.json</code> file in <code>react-scripts</code> directory to <code>unicodelabs-react-scripts</code>.</p> <p>Change the value of the <code>description</code> key to <code>Unicodelabs Configuration and scripts for Create React App.</code> Also, point the value of the <code>repository</code> key to the right location. In my case, it is <code>unicodelabs/create-react-app</code>.</p> <p>Now, <code>cd</code> to the <code>react-scripts</code> directory from your terminal like so:</p> <p><img src="https://cdn.auth0.com/blog/cra/react-scripts-directory.png" alt="react-scripts directory" /> <em>Change into this directory on your terminal</em></p> <p>You need to login to npm like so:</p> <p><img src="https://cdn.auth0.com/blog/cra/npmlogin.png" alt="Npm Login" /> <em>Log into Npm</em></p> <p>Go ahead and publish</p> <p><img src="https://cdn.auth0.com/blog/cra/publish.png" alt="Publish" /> <em>Published unicodelabs-react-scripts to npm</em></p> <h2>Test Your Custom Script</h2> <p>Head over to your terminal and run:</p> <pre><code class="bash"> create-react-app test-app --scripts-version unicodelabs-react-scripts </code></pre> <p>In your own case it would be <code>yourname-react-scripts</code>, where <code>yourname</code> is your company name or whatever name you choose to give it.</p> <p><em>CRA</em> would install it and then you will see a notice like so:</p> <p><img src="https://cdn.auth0.com/blog/cra/important-warning.png" alt="Important Warning" /> <em>Important Warning</em></p> <p>Remember, when we put this message in the code earlier? Awesome!</p> <p>Now, <code>cd</code> into the <code>test-app</code> directory, rename the <code>.env.example</code> to <code>.env</code> and run <code>npm start</code> command.</p> <p>Your app will spin up with the new template like so:</p> <p><img src="https://cdn.auth0.com/blog/cra/result.png" alt="New template showing up" /></p> <p><strong>Note</strong>: If you have yarn installed, then create-react-app would install your app using Yarn.</p> <h2>Aside: Using create-react-app with Auth0</h2> <p>Authentication is a very key part of various applications. Auth0 helps you to:</p> <ul> <li>Add authentication through more traditional username/password databases.</li> <li>Add support for linking different user accounts with the same user.</li> <li>Support for generating signed Json Web Tokens to call your APIs and flow the user identity securely.</li> <li>Analytics of how, when and where users are logging in.</li> <li>Pull data from other sources and add it to the user profile, through <a href="https://docs.auth0.com/rules">JavaScript rules</a>.</li> <li>Achieve <a href="https://auth0.com/docs/sso">SSO(Single Sign On)</a> seamlessly.</li> </ul> <p><strong>Auth0</strong> has its own fork of <code>react-scripts</code> which means you can install an Auth0-powered React app with a single command like so:</p> <pre><code class="bash">create-react-app my-app --scripts-version auth0-react-scripts </code></pre> <p>Once it is done installing, go ahead and:</p> <ul> <li>Grab your <em>Client id</em> and <em>Auth0 domain</em> from the <a href="https://manage.auth0.com">Auth0 dashboard</a>.</li> <li>Create a <em>.env</em> file in the root of the <code>my-app</code> project and add <em>client id</em> and <em>Auth0 domain</em> values to <strong>REACT_APP_AUTH0_CLIENT_ID</strong> and <strong>REACT_APP_AUTH0_DOMAIN</strong> respectively.</li> <li>Run the app.</li> </ul> <p><img src="https://cdn.auth0.com/blog/cra/welcomepage.png" alt="Welcome Screen" /> <em>Welcome Screen</em></p> <p><img src="https://cdn.auth0.com/blog/cra/loginscreen.png" alt="Login Screen" /> <em>Login Screen</em></p> <p><img src="https://cdn.auth0.com/blog/cra/loggedin.png" alt="Logged In State" /> <em>Logged In</em></p> <p>Viola! You now have a fresh React app with full authentication powered by Auth0 ready for use.</p> <p><a href="javascript:signup()">Sign up</a> for a free account today and enjoy fast, seamless, and hassle-free authentication in your apps.</p> <h2>Conclusion</h2> <p>Great programmers constantly sharpen their tools daily to increase productivity. <em>CRA</em> is a great tool for quickly building React Applications. In addition, having your own customized fork of <code>react-scripts</code> helps you and your team easily add all the configurations you need. You'll need to maintain your fork, and <a href="https://help.github.com/articles/fork-a-repo/#keep-your-fork-synced">make sure it is synced</a> with the upstream to have all updates. <a href="https://github.com/1egoman/backstroke">Backstroke</a> is a bot that can help you with this.</p> <p>Have a very productive time hacking away!</p> How Enterprise Federation Helps Shorten The Sales Cycle 2017-02-03T08:30:00+00:00 https://auth0.com/blog/how-enterprise-federation-helps-shorten-the-sales-cycle/ Martin Gontovnikas http://twitter.com/mgonto <hr /> <p>Enterprise customers are great. They're large, stable accounts that can represent a real win for your business. But they're also a unique challenge, and more complicated than small to medium-sized businesses (SMBs).</p> <p>Selling to enterprise clients has always meant managing:</p> <ul> <li>Long sales cycles</li> <li>Custom solutions</li> <li>Specific needs</li> </ul> <p>But in 2017, in the aftermath of some of the most prominent hacks of all time, it also means keeping up with enterprise companies that are getting extra serious about making sure that their security practices are airtight.</p> <p>Implementing Auth0, with support for 10+ types of enterprise IAM federation, is the best way to shorten your sales cycle with these companies and make sure you don't have to do frantic work on the back-end to make deals happen.</p> <h2>How selling to enterprise companies usually works</h2> <p>You've built a product that you've been selling to SMBs. But, finally, you're starting to get a foothold with enterprise-level customers. Your hard work is paying off, and you line up a deal with Coca-Cola. Things are really moving for your business, and it feels amazing.</p> <p>As it turns out, Coca-Cola uses Active Directory for their IAM, so if you want Coca-Cola employees using your product, you need to implement Active Directory. Of course, you get right on it to close the deal, but it takes three months, which stretches your sales cycle out much longer than it could be.</p> <p>After your deal with Coca-Cola closes, you're feeling good about your ability to serve the enterprise customer. So you go to Disney and you try to sell to Disney. Bad news comes almost immediately: Disney uses SAML!</p> <p>Now you have to go through the whole process all over again. Extending your sales cycle because of compatibility issues is just time and money being constantly thrown away. On top of that:</p> <ul> <li>It doesn't present your business in the best light</li> <li>Your internal champion at your enterprise customer could leave or be fired in those three months</li> <li>Opportunities could be lost elsewhere because you had to spend time building this integration</li> <li>You have to spend even more money on developers making those integrations happen</li> </ul> <p>This is not a cycle you want to be stuck in. <strong>And many of your customers are going to have these kinds of requirements if you want to sell to them. </strong>Based on data we've collected about enterprise identity management, we learned that <strong>hundreds of thousands of companies rely on </strong><a href="https://auth0.com/blog/analysis-of-enterprise-connections-data/"><strong>Active Directory alone</strong></a>.</p> <p><img src="https://cdn.auth0.com/blog/enterprise/enterprise-connections.png" alt="Enterprise Connections" /></p> <ul> <li>Most (<a href="https://auth0.com/blog/analysis-of-enterprise-connections-data/">53%</a>) Enterprise connections are through Active Directory Federation Services (ADFS).</li> <li>Another <a href="https://auth0.com/blog/analysis-of-enterprise-connections-data/">35%</a> are using Active Directory connections.</li> <li>SAMLP (<a href="https://auth0.com/blog/analysis-of-enterprise-connections-data/">7%</a>), Microsoft Azure Active Directory (<a href="https://auth0.com/blog/analysis-of-enterprise-connections-data/">3%</a>), and Google Apps (<a href="https://auth0.com/blog/analysis-of-enterprise-connections-data/">2%</a>) round out the top 5.</li> </ul> <p>You've got to be able to handle these requirements to get your product in the door with enterprise customers.</p> <h2>Safari Books case study</h2> <p>A great example of how Auth0 can be easily integrated into to your app to open up enterprise possibilities is through Safari Books Online.</p> <p>Safari Books Online was facing a predictable pattern of long sales cycles and new development time when they first started to go upmarket and sell their design resources, videos, and e-books services to the enterprise customer.</p> <p>At first, they tried to implement all the enterprise demands they were receiving in-house, but realized they couldn't upgrade their login quickly enough. Understanding what they stood to lose, <a href="https://auth0.com/learn/safari-case-study/">they sought out an IAM</a>.</p> <p>Safari Books Online chose Auth0's secure enterprise login options to upgrade their platform and implement logins across enterprise requirements. This dramatically shortened their sales cycle and gave them the functionality they desperately needed.</p> <p>“Compared to the costs and resources required to build, host, and secure a custom solution, the <a href="https://auth0.com/learn/safari-case-study/">investment associated with a third-party authentication service like Auth0 was a sensible choice</a>,” said Safari engineering manager Cris Concepcion.</p> <p>Today, Safari Books Online is used by a wide range of enterprise clients, from Google to Tesla.</p> <h2>How enterprise sales work with Auth0</h2> <p>When you use Auth0, you immediately cut down on the time that your team has to spend doing heavy lifting on the compatibility front. Auth0 allows you to make your app work with 10+ different enterprise identity providers, out of the box.</p> <p><img src="https://cdn.auth0.com/blog/enterprise/options.png" alt="Auth0 Enterprise Options" /></p> <p>Auth0 acts as an intermediary between your app and your users. It seamlessly integrates into your product, but <a href="https://auth0.com/docs/identityproviders">keeps your app isolated</a> from any changes to or idiosyncrasies of different implementations. This means you can keep maximum function for your app with minimal effort for login.</p> <p><img src="https://cdn.auth0.com/blog/enterprise/overview.png" alt="Enterprise Overview" /></p> <p>Using Auth0 to ramp up your security and login doesn't just shorten your sales cycle for one customer, but also gives you the tools to fit your login to a wide variety of enterprise needs. If you configure compatibility between Auth0 and your app once, you've configured compatibility for 10+ identity providers in one fell swoop.</p> <p>Auth0 also gives you the power to add other critical features that enterprise customers want, like multi-factor authentication and single sign-on.</p> <h2>The power of the enterprise customer</h2> <p>Enterprise contracts can represent a big win for your business and are one of the best ways to maximize your revenue.</p> <p>The enterprise customer wants great solutions to their problems, and it's likely that a well-crafted product that works for SMBs will<a href="https://auth0.com/blog/how-to-go-upmarket-and-grow-your-revenue-by-20x/?utm_source=twitter&amp;utm_medium=sc&amp;utm_campaign=saas_upmarket"> scale extremely well</a> to an enterprise venture. Add a few extra perks, like a designated point-person and a higher user limit, and you've paved the path to scale up.</p> <p>The key is to couple this with enterprise-ready security and identity management.</p> <p>If enterprise customers want employees to be able to sign in with their existing logins instead of creating more accounts, you can use Auth0's <a href="https://auth0.com/docs/sso">single sign-on</a> to streamline your product's integration. If they want to hone in on security, you can offer <a href="https://auth0.com/docs/multifactor-authentication">multifactor authentication</a> that requires both a login and an additional security precaution, like a fingerprint scan, or a verification code.</p> <p>Whatever their need, a good IAM integration will help you cater to it.</p> <p>This will allow you to take that premium plan and charge a premium price. Better yet, when you use an IAM, that “premium plan” can be ready as soon as you decide to go after enterprise clients. When you offer enterprise login and security compatibility, you instantly open the door to a whole new — and efficient — revenue stream.</p> Migrating a PHP 5 App to PHP 7 (Development Environment) - Part 1 2017-02-02T08:30:00+00:00 https://auth0.com/blog/migrating-a-php5-app-to-php7-part-one/ Prosper Otemuyiwa http://twitter.com/unicodeveloper?lang=en <p><strong>TL;DR:</strong> Many PHP applications are still running on PHP 5.x, not ready to take full advantage of the awesome features that PHP 7 offers. A lot of developers have not made the switch because of certain fears of compatibility issues, migration challenges and the strange awkward feeling that migrating will take away a big chunk of their time. In this tutorial, you'll learn how to upgrade your PHP 5 application to PHP 7 starting from upgrading your development environment.</p> <hr /> <h2>PHP 5 and PHP 7</h2> <p>PHP 5 has been around for a very long time, over 10 years now. In fact, many production PHP apps are currently running on either PHP 5.2, 5.3 or 5.6. PHP 5 brought a lot of awesome features to PHP such as:</p> <ul> <li>Robust Support for Object oriented programming.</li> <li>Standard PHP Library (SPL)</li> <li>Closures.</li> <li>Namespaces.</li> <li>Magical methods for metaprogramming.</li> <li>MySQLi - improved MySQL extension.</li> <li>Cleaner Error handling.</li> <li>Better support for XML extensions.</li> </ul> <p>Unfortunately, every thing that has a beginning must have an end. PHP 5.6 active support ended January 19, 2017. It will receive security support until December 31, 2018.</p> <p><img src="https://cdn.auth0.com/blog/phpv/release.png" alt="Supported Release" /> <em>PHP 5 and 7 release and support duration</em></p> <p>PHP 7.0 was officially released on December 3, 2015 with a lot of new features and better performance benefits. It is twice as fast as PHP 5. A summary of the new features are highlighted below:</p> <ul> <li>Return and Scalar type declarations</li> <li>Better Unicode support</li> <li>Null Coalescing Operator</li> <li>Fatal errors conversion to Exceptions</li> <li>Generator Enhancement</li> <li>Anonymous Classes</li> <li>Secure random number generator</li> <li>Removal of deprecated features</li> </ul> <p>and much more! If you aren't using any of the deprecated features in your PHP 5 app, then the transition to PHP 7 will be seamless. In the next post, I'll give a very detailed rundown of PHP 7 features, including the deprecated features.</p> <h2>Upgrading your development environment to PHP 7</h2> <p>The first step to upgrading your application to use PHP 7 features is to migrate your development environment from PHP 5.x to PHP 7.x. We will cover how to upgrade your development environment to run PHP 7.x on Ubuntu, CentOs, Windows and Mac OS machines.</p> <h2>Mac OS X</h2> <p>If you are a fan of <a href="http://brew.sh">Homebrew</a>, you can install PHP 7.0 via homebrew like so:</p> <pre><code class="bash"> brew tap homebrew/dupes brew tap homebrew/versions brew tap homebrew/homebrew-php brew unlink php56 brew install php70 </code></pre> <blockquote><p>If you were using PHP 5.6, then you should unlink the old PHP by running <code>brew unlink php56</code> else unlink whatever version is present before you go ahead to install PHP 7.0.</p></blockquote> <p>Another option is to install it via <code>curl</code> on your terminal like so:</p> <pre><code class="bash"> curl -s https://php-osx.liip.ch/install.sh | bash -s 7.0 </code></pre> <h2>Windows</h2> <p>If you are fan of <a href="http://www.wampserver.com/en">WAMP</a> or <a href="https://www.apachefriends.org/download.html">XAMPP</a>, then you can just download the latest versions of the software. It comes packaged with PHP 7.0.</p> <p><img src="https://cdn.auth0.com/blog/phpv/donwload.png" alt="XAMPP download" /> <em>Download and install the last/latest version</em></p> <p>Another option is to download the PHP 7.0 distribution for windows from <a href="http://windows.php.net/download#php-7.0">http://windows.php.net/download#php-7.0</a>.</p> <h2>Ubuntu</h2> <p>If you are running Ubuntu on your machine, especially around v14 and 15, you can install PHP 7.0 by running these commands:</p> <pre><code class="bash"> sudo apt-get update sudo add-apt-repository ppa:ondrej/php sudo apt-get install -y php7.0-fpm php7.0-cli php7.0-curl php7.0-gd php7.0-intl php7.0-mysql </code></pre> <p><strong>Note:</strong> You can check out how to install PHP 7 and Nginx here, and manually build memcached module for PHP 7.</p> <h2>Debian</h2> <p>If you are running Debian on your machine, especially around v6, v7 and v8, you can install PHP 7.0 by doing the following:</p> <ul> <li>Open up your <code>/etc/apt/sources.list</code> file, and make sure you have these commands below:</li> </ul> <p><em>If you are using a Jessie distribution</em></p> <pre><code class="bash"> deb http://packages.dotdeb.org jessie all deb-src http://packages.dotdeb.org jessie all </code></pre> <p><em>If you are using a Wheezy distribution</em></p> <pre><code class="bash"> deb http://packages.dotdeb.org wheezy all deb-src http://packages.dotdeb.org wheezy all </code></pre> <ul> <li>Fetch and Install the GnuPG key</li> </ul> <pre><code class="bash"> wget https://www.dotdeb.org/dotdeb.gpg sudo apt-key add dotdeb.gpg </code></pre> <ul> <li>Install PHP 7.0</li> </ul> <pre><code class="bash"> sudo apt-get update sudo apt-get install php7.0 </code></pre> <h2>CentOS / Red Hat Enterprise Linux</h2> <p>If you are running CentOS or Red Hat Enterprise Linux operating system on your machine, you can install PHP 7.0 by running the following commands on your terminal like so:</p> <pre><code class="bash"> sudo yum update rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm sudo yum install php70w sudo yum install php70w-mysql </code></pre> <p>When you are done, run this command <code>php -v</code>, you should see something like this:</p> <pre><code class="bash"> PHP 7.0.0 (cli) (built: Dec 2 2015 20:42:32) ( NTS ) Copyright (c) 1997-2015 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2015 Zend Technologies </code></pre> <h2>phpbrew</h2> <p><a href="https://github.com/phpbrew/phpbrew">PHPBrew</a> is a tool that you can use to build and install multiple versions of PHP on your machine. It can:</p> <ul> <li>Build PHP with different variants like PDO, MySQL, SQLite, debug etc</li> <li>Compile Apache PHP module and separate them by different versions.</li> <li>Switch versions very easily and is integrated with bash/zsh shell.</li> <li>Install &amp; enable PHP extensions into current environment with ease.</li> <li>Install multiple PHP into system-wide environment.</li> <li>Detect path for Homebrew and MacPorts.</li> </ul> <p><img src="https://raw.github.com/phpbrew/phpbrew/master/screenshots/01.png" alt="phpbrew" /> <em>phpbrew</em></p> <p>You can install it on your machine like so:</p> <pre><code class="bash"> curl -L -O https://github.com/phpbrew/phpbrew/raw/master/phpbrew chmod +x phpbrew </code></pre> <p>Then you can install it into your bin folder like so:</p> <pre><code class="bash"> sudo mv phpbrew /usr/local/bin/phpbrew </code></pre> <p><strong>Note:</strong> Make sure you have <code>/usr/local/bin</code> in your <code>$PATH</code> environment variable.</p> <p>You can install PHP 7 by running the following commands:</p> <pre><code class="bash"> phpbrew self-update phpbrew install next as php-7.1.0 phpbrew use php-7.1.0 </code></pre> <p>You can use phpbrew to install PHP 7.0 from GitHub like so:</p> <pre><code class="bash"> phpbrew install github:php/php-src@PHP-7.0 as php-7.0.0 </code></pre> <p>Most times, we use PHP with other extensions such as MySQL, PDO, OpenSSL etc. You can use <strong>phpbrew</strong> to build your PHP environment with various variants like so:</p> <pre><code class="bash"> phpbrew install 7.0.0 +mysql+mcrypt+openssl+debug+sqlite </code></pre> <p>This command above will build PHP with MySQL, mycrypt, OpenSSL, debug and SQLite.</p> <h2>Vagrant</h2> <p>Vagrant provides a simple, elegant way to manage and provision Virtual Machines. The development environments that run on Vagrant are packaged via <strong>Vagrant boxes</strong>. Vagrant boxes are completely disposable. If something goes wrong, you can destroy and re-create the box in minutes! One of such boxes I recommend is <strong>Laravel Homestead</strong>.</p> <blockquote><p><strong>Note:</strong> You can check out these awesome free courses on <a href="https://serversforhackers.com/series/vagrant">learning how to use Vagrant</a> on <a href="https://serversforhackers.com/">https://serversforhackers.com</a></p></blockquote> <h3>Laravel Homestead</h3> <p>Laravel Homestead is an official, pre-packaged Vagrant box that provides you a wonderful development environment without requiring you to install PHP, a web server, and any other server software on your local machine. Homestead runs on any Windows, Mac, or Linux system. It includes the following:</p> <ul> <li>Ubuntu 16.04</li> <li>Git</li> <li>PHP 7.1 (Latest version of PHP)</li> <li>Nginx</li> <li>MySQL</li> <li>MariaDB</li> <li>Sqlite3</li> <li>Postgres</li> <li>Composer</li> <li>Node (With Yarn, PM2, Bower, Grunt, and Gulp)</li> <li>Redis</li> <li>Memcached</li> <li><p>Beanstalkd</p></li> <li><p>Install <a href="https://www.virtualbox.org/wiki/Downloads">VirtualBox 5.1</a>, or <a href="https://www.vmware.com">VMWare</a>, and <a href="https://www.vagrantup.com/downloads.html">Vagrant</a>.</p></li> <li><p>Now that you have Vagrant and VirtualBox or VMware installed, go ahead and download the Laravel Homestead box like so:</p></li> </ul> <pre><code class="bash"> vagrant box add laravel/homestead </code></pre> <p>Follow the instructions on the <a href="https://laravel.com/docs/5.3/homestead">Laravel Homestead documentation</a> to find out more about the installation process.</p> <blockquote><p>I recommend Windows users to take a stab at using <a href="https://laragon.org">Laragon</a>. It provides an alternative but suitable and powerful environment like Laravel Homestead.</p></blockquote> <h3>php7dev</h3> <p>Another Vagrant image is <strong><a href="https://github.com/rlerdorf/php7dev">php7dev</a></strong> by Rasmus Ledorf (Creator of PHP). It is a Debian 8 Vagrant image which is preconfigured for testing PHP apps and developing extensions across many versions of PHP. You can gloriously switch between PHP versions by using the <code>newphp</code> command.</p> <p>Follow the instructions on the <a href="https://github.com/rlerdorf/php7dev">README</a> to find out how to install, configure and use.</p> <h2>Valet</h2> <p><a href="https://github.com/laravel/valet">Valet</a> is a PHP development environment for Mac minimalists. It was built by <a href="https://twitter.com/taylorotwell">Taylor</a> and <a href="https://twitter.com/adamwathan">Adam Wathan</a> of the Laravel community. It is a fast blazing development environment that uses roughly 7MB of RAM. It requires Homebrew.</p> <p>Laravel Valet configures Mac to use PHP's built-in web server in the background when your machine starts. With Valet, if you create a project folder called <code>auth0-php</code>, then you can just open <code>auth0-php.dev</code> in your browser and it will serve the contents of the folder automatically.</p> <p>You can share whatever you are working on locally with someone in another part of the world by just running this command:</p> <pre><code class="bash"> valet share </code></pre> <p><img src="https://cdn.auth0.com/blog/valet/share.png" alt="Valet share" /> <em>Valet uses Ngrok under the hood to share</em></p> <p>You can even serve a local site over encrypted TLS using HTTP/2 by invoking a command like so:</p> <pre><code class="bash"> valet secure blog </code></pre> <p>where <code>blog</code> is the name of the site or project folder. Valet generates a Fresh local TLS certificate.</p> <p><img src="https://cdn.auth0.com/blog/valet/share.png" alt="Secure the Blog" /> <em>Invoke the secure command</em></p> <p><img src="https://cdn.auth0.com/blog/valet/secure.png" alt="Secure Blog" /> <em>Site is served over https locally</em></p> <p>Very awesome!</p> <p>Out of the box, Valet supports <a href="https://laravel.com">Laravel</a>, <a href="https://lumen.laravel.com">Lumen</a>, <a href="https://symfony.com">Symfony</a>, <a href="https://framework.zend.com">Zend</a>, <a href="https://cakephp.org">CakePHP 3</a>, <a href="https://wordpress.org">Wordpress</a>, <a href="https://roots.io/bedrock">Bedrock</a>, <a href="https://craftcms.com">Craft</a>, <a href="https://statamic.com">Statamic</a> and <a href="http://jigsaw.tighten.co">Jigsaw</a>. However, you can extend Valet with your own <a href="https://laravel.com/docs/5.3/valet#custom-valet-drivers">custom drivers</a>.</p> <p>Follow the instructions on the <a href="https://laravel.com/docs/5.3/valet">laravel valet documentation</a> to find out how to install and get started using it.</p> <h2>Docker</h2> <h3>php7-dockerized</h3> <p><a href="https://github.com/hamptonpaulk/php7-dockerized">php7-dockerized</a> is a simple PHP 7 Docker and Compose environment that is bundled with Nginx and MySQL. Follow the instructions on <a href="https://medium.com/code-school/setting-up-a-local-php7-development-environment-with-docker-compose-e9531baed291#.bezir0x7n">setting up a local PHP 7 development environment with docker and compose!</a>.</p> <h3>Laradock</h3> <p><a href="https://github.com/laradock/laradock">Laradock</a> is a docker PHP development environment that gives you a wonderful development environment without requiring you to install PHP 7, Nginx, MySQL, Redis, and any other software on your machines.</p> <ul> <li>Clone Laradock inside your project like so:</li> </ul> <pre><code class="bash"> git clone https://github.com/Laradock/laradock.git </code></pre> <ul> <li>Enter the laradock folder and run this command:</li> </ul> <pre><code class="bash"> docker-compose up -d nginx mysql redis beanstalkd </code></pre> <ul> <li>Open your <code>.env</code> file and set the following:</li> </ul> <pre><code class="bash"> DB_HOST=mysql REDIS_HOST=redis QUEUE_HOST=beanstalkd </code></pre> <p>Follow the instructions on the <a href="https://github.com/laradock/laradock/blob/master/README.md">laradock documentation</a> to find out how to install and configure it.</p> <h3>phpdocker</h3> <p><a href="https://github.com/phpdocker-io/phpdocker.io">phpdocker.io</a> is a PHP and Docker generated environment. It supports PHP 7 up until 7.1 beta. Follow the instructions to set it up like so:</p> <ul> <li>Clone <a href="https://github.com/phpdocker-io/phpdocker.io">https://github.com/phpdocker-io/phpdocker.io</a></li> <li>Copy <code>app/config/parameters.yml.dist</code> into <code>app/config/parameters.yml</code></li> <li>Run <code>composer install</code></li> <li>Run <code>bower install</code></li> <li>Run <code>php bin/console assets:install --symlink --relative</code></li> <li>Run <code>docker-compose up -d</code></li> </ul> <p>Don't hesitate to submit an issue on the <code>phpdocker-io</code> repo if you hit a roadblock.</p> <p><strong>Note:</strong> <a href="https://twitter.com/fideloper">Chris Fidao</a> has a fantastic course on Docker. With his course on <a href="https://shippingdocker.com">shippingdocker.com</a>, you'll learn how to use Docker in development, testing and production.</p> <p>There are different ways of setting up a PHP 7 development environment. The few I have mentioned here should give you a lot of options in getting your machine ready to effectively test PHP 7 features.</p> <h2>Conclusion</h2> <p>We have successfully covered various ways of setting up a PHP 7 development environment. The first step to migrating an app from a specific language version to another is ensuring that the development environment supports the new version.</p> <p>Do you have other ways of setting up PHP 7 development environments? Are you currently using an awesome tool to run your PHP 7 apps? Please let me know in the comments section.</p> <p>In the next article, we'll go through all the features of PHP 7 that you can leverage when migrating your PHP 5 application!</p> Better User Management with the Delegated Administration Dashboard 2017-02-01T08:30:00+00:00 https://auth0.com/blog/delegated-admin-v2/ Ado Kukic https://twitter.com/kukicado <hr /> <p><strong>TL;DR</strong> The Delegated Administration Dashboard extension exposes the <a href="https://manage.auth0.com/#/users">Users</a> tab of the Auth0 <a href="https://manage.auth0.com">dashboard</a> allowing you to easily and securely grant limited access for privileged user accounts. The extension exposes a number of hooks allowing you to provide a customized and fine-grained experience. Today, we will look at how the Delegated Admin extension can help a growing organization simplify their user management workflow by giving subordinate accounts access to create, edit, and further manage various user accounts throughout the organization.</p> <hr /> <p>Building modern applications is only half the battle. As your app grows, the need for excellent management and maintenance tools becomes key. User management is one area where you don't want to get this wrong. If you are using <a href="https://auth0.com">Auth0</a> for managing modern identity in your applications and are at a point where you need more control over user management, then I would like to introduce you to our <strong><a href="https://auth0.com/docs/extensions/delegated-admin">Delegated Administration Dashboard</a></strong> extension.</p> <p>The Delegated Administration Dashboard or Delegated Admin extension allows you to give fine-grained access to user data stored and accessed through Auth0. With this extension, you can give individual users access to view, manage, and edit users in your apps, without giving them the proverbial <em>keys to the kingdom</em> a.k.a. full access to the Auth0 <a href="https://manage.auth0.com">dashboard</a>.</p> <blockquote class="tweet-quote"> <a href="https://twitter.com/intent/tweet?text=&quot;The Delegated Admin Dashboard allows companies to build and enforce powerful user management workflows.&quot; via @auth0 http://auth0.com/blog/delegated-admin-v2/"> <p>"The Delegated Admin Dashboard allows companies to build and enforce powerful user management workflows."</p> <p class="tweet-link">TWEET THIS <img src="https://cdn.auth0.com/blog/resources/twitter.svg"></p> </a> </blockquote> <script> $(function() { $('.tweet-quote').on('click', function() { metricsLib.track('blog:share:twitter_quote'); }); }); </script> <p>Today, we will look at how you can utilize the Delegated Admin extension to expose only the User dashboard to a set of privileged users. We will be doing this in the context of a fictional company that has grown tremendously and needs a better way to delegate user management access. Our example is a common one but there are many use cases where this extension can be applied. For example, a SaaS platform may want to give their clients an easy to use dashboard to manage their tenants. Another example could be an organization wishing to grant specific access to various departments, IT Support would be able to view, edit, and delete all organizational accounts, while Customer Support would only have access to customers. We'll try to address various use cases throughout the post to show the versatility of the extension. Let's get started.</p> <h2>CloudCakes Goes Global</h2> <p>CloudCakes is a fictional company that delivers on-demand cakes. Users simply place an order through the company's web or mobile app and within 30 minutes a cake is delivered. The company has gone global, amassing millions of users and opening many franchises along the way. Each franchise operates independently and serves a designated local market. The company has scaled operations in many ways, but has never really had a solid user management strategy. They recently switched to Auth0 for managing their users, but now need a way to allow individual franchises to have more control over their users.</p> <h2>Delegated Administration Extension</h2> <p>The Delegated Administration extension will allow CloudCakes to better delegate access to their vast pool of users. As it stands only the executives from CloudCakes corporate can access the <a href="https://dashboard.auth0.com">Auth0 dashboard</a>. Giving access to the dashboard for all franchise owners is not an option. They could use the Auth0 <a href="https://auth0.com/docs/api/management/v2">Management API</a> to build an experience for the franchise owners, or they could use the <a href="https://auth0.com/docs/extensions/delegated-admin">Delegated Administration</a> extension to expose only the Users section of the Dashboard. The latter seems like a much better option. Let's see how CloudCakes and your organization can accomplish this quickly and easily.</p> <p>To use the Delegated Administration Dashboard you will need to have an active Auth0 account. If you don't already have one, you can <a href="javascript:signup()">sign up for free</a>.</p> <h3>Create a New Client</h3> <p>The first thing we are going to do is create a new Auth0 client to house the user accounts that will have access to the users dashboard. This client will essentially act as the command center for the users dashboard.</p> <p>To create the client, navigate to the Auth0 dashboard and click on the <strong>New Client</strong> button. You can name the client whatever you want, we'll just name ours CloudCakes Inc. Set the type of app as <strong>Single Page App* and click </strong>Create**.</p> <p><img src="https://cdn.auth0.com/blog/delegated-admin-cloud-cakes/create-client.png" alt="Auth0 Create New Client" /></p> <p>With the new client created, go ahead and copy its <strong>Client ID</strong>. Navigate to the bottom of the <strong>Settings</strong> tab in this newly created client and click on the <strong>Show Advanced Settings</strong> link. From here, navigate to the <strong>OAuth</strong> tab and in the <strong>Allowed APPs/APIs</strong> section paste in the <strong>Client ID</strong>. Additionally in this section, change the <strong>JsonWebToken Signature Algorithm</strong> to <strong>RS256</strong>.</p> <p><img src="https://cdn.auth0.com/blog/delegated-admin-cloud-cakes/advanced-client-settings.png" alt="Auth0 Advanced Client Settings" /></p> <p>Finally, scroll up to the <strong>Allowed Callback URLs</strong> section and here we will add the url that will be used to access the Users Dashboard. The url will follow this structure <code>https://YOUR-AUTH0-USERNAME.LOCALE.webtask.io/auth0-delegated-admin/login</code>, so since I am in the US and my username is <code>adobot</code> the URL I will add is <code>https://adobot.us.webtask.io/auth0-delegated-admin/login</code>. Save your changes and navigate to the <a href="https://manage.auth0.com/#/extensions">Extensions</a> tab in the main menu.</p> <h3>Setup New Database Connection</h3> <p>In addition to setting up a new client for our Users Dashboard, we'll also want to setup a new database connection to store our privileged users. We could use an existing data store if we really wanted to, but it's more secure to isolate these users in their own database. As always you can either store the users with Auth0 or connect to <a href="https://auth0.com/docs/connections/database#using-a-custom-user-store">any custom datastore</a>.</p> <p>To create the database connection, head over to the <a href="https://manage.auth0.com/#/connections/database">Database Connections</a> in the Auth0 dashboard and select <strong>Create DB Connection</strong>. Name your connection, select how users will login, and it is recommended you disable sign-ups so that users don't have the option to directly sign up for an account.</p> <p><img src="https://cdn.auth0.com/blog/delegated-admin-cloud-cakes/create-db-connection.png" alt="Auth0 Create DB Connection" /></p> <p>Once the connection is created go back to the client you are going to use for the Users Dashboard and enable just this newly created connection for it. This will ensure that only users that are stored in this database can login and access the Users Dashboard.</p> <h3>Enabling the Delegated Admin Extension</h3> <p>To enable the Delegation Admin Dashboard extension, you will just need the Client ID you copied earlier. From the Extensions section, navigate to the very bottom where you will find the the Delegation Admin Dashboard extension, click on it, and a modal dialog will pop up asking you to input some data before enabling the extension.</p> <p><img src="https://cdn.auth0.com/blog/delegated-admin-cloud-cakes/enable-delegated-admin-extension.png" alt="Enabling Delegated Administration Dashboard Extension" /></p> <p>The two fields you will need to provide data for are the <strong>EXTENSION_CLIENT_ID</strong> and <strong>Title</strong>. Extension Client ID will be the Client ID you copied earlier and the title can be anything. You can also optionally add a link to a CSS file to customize the look and feel of the Users Dashboard, but we'll omit that here. Click <strong>Install</strong> to enable the extension.</p> <h3>Populating the Database</h3> <p>We've enabled the Delegation Admin Dashboard extension but it's of little use to us now since we don't have any users capable of accessing it. Let's change that. Navigate to the <a href="https://manage.auth0.com/#/users">Users</a> tab in the Auth0 dashboard and create a new user. Be sure place this user in the correct database.</p> <p><img src="https://cdn.auth0.com/blog/delegated-admin-cloud-cakes/login-screen.png" alt="Delegated Admin Dashboard Login" /></p> <p>With the user created, let's go ahead and login to see the Users Dashboard. Navigate to your dashboard url, which again follows the <code>https://YOUR-AUTH0-USERNAME.LOCALE.webtask.io/auth0-delegated-admin/login</code> pattern. Attempting to login with the newly created user will give you access to the Users Dashboard but you will not be able to view or do anything as the system does not know what permissions this user has. We'll need to go edit the users <code>metadata</code> and let the system know what type of user is logging in and what they should be able to do. Let's do that now.</p> <p><img src="https://cdn.auth0.com/blog/delegated-admin-cloud-cakes/users-dashboard-no-permissions.png" alt="Users Dashboard No Permissions" /></p> <h2>Understanding User Roles</h2> <p>The Delegation Administration Dashboard supports two unique user roles: <strong>Administrator</strong> and <strong>User</strong>. The <strong>User</strong> role allows the logged in account to search, create, edit, and execute other management roles on user accounts they have access to, while the <strong>Administrator</strong> role additionally has access to logs as well as ability to configure hooks and other settings for users of the Users Dashboard.</p> <p>To grant one of these roles to our user, we'll need to edit the <code>app_metadata</code> for the user and add a <code>role</code> attribute. Let's give our newly created user the <strong>Administrator</strong> role. Go to their account in the Auth0 dashboard, click <strong>Edit</strong> in the Metadata section, and for <strong>App Metadata</strong> add the following code:</p> <pre><code class="js ">{ "roles": "Delegated Admin - Administrator" } </code></pre> <p>Save this change and go back to the Users Dashboard. Refresh the page and now the user will have full access to the Users Dashboard and will see all of the existing users across all connections, logs, and will have the ablility to configure the Users Dashboard. So far so good. If you go back and change the role to <code>"Delegated Admin - User"</code> and refresh the page, you will just be able to see the list of users, but not logs and you will not have the ability to make configuration changes to the Users Dashboard with the account.</p> <p><img src="https://cdn.auth0.com/blog/delegated-admin-cloud-cakes/adding-user-permissions.png" alt="Adding Delegated Admin Roles" /></p> <p>You may have noticed that regardless of the role you gave to your user, they were able to see all of the users across all of your Auth0 connections. In many cases you would not want this to happen, instead you'd want to have fine-grained control over which connections an account has access to. We'll address that in the next section.</p> <p><img src="https://cdn.auth0.com/blog/delegated-admin-cloud-cakes/login-with-permissions.png" alt="Delegated Admin Dashboard with Permissions" /></p> <h3>Fine-grained Control with Hooks</h3> <p>The user roles in the previous section give us some control, but in many instances we would want further control. We can accomplish this with additional properties stored in the users <code>app_metadata</code>. CloudCakes has separated its operations into various departments. We'll add a <code>department</code> attribute in our <code>app_metadata</code> to store which department a user belongs to. Let's edit our current and only user and make them part of the <strong>Executive</strong> department. Simply edit their <code>app_metadata</code> data to read:</p> <pre><code class="js">{ "roles": "Delegated Admin - Administrator", "department": "Executive" } </code></pre> <p>The department field can be set to any string value and you can have as many departments as you see fit. Hooks will give us additional functionality and combined with our metadata will allow us to grant fine-grained control over each user account. If you are familiar with how <a href="https://auth0.com/docs/rules">Rules</a> work with the Auth0 platform, you'll feel right at home. Essentially, hooks, like rules, run whenever an action triggers them such as creating a new user account or viewing a page. Hooks are written in the pattern of:</p> <pre><code class="js ">function(ctx, callback) { /* Perform any type of logic */ return callback(null, {}); // The second paramter adds any data that should be passed with the callback. } </code></pre> <p>Let's see how we can extend the capabilities of the Users Dashboard with Hooks. To access Hooks, you will need to be logged in with a user with the role of <code>Delegated Admin - Administrator</code>. Head over to the Delegated Admin dashboard and login. Once in, click on your users email in the top right corner and a dropdown menu will open, from here click on the <strong>Configuration</strong> tab and you will see the configuration page where we will add our hooks.</p> <p><img src="https://cdn.auth0.com/blog/delegated-admin-cloud-cakes/accessing-hooks.png" alt="Accessing Delegated Admin Configuration" /></p> <h4>Filter Hooks</h4> <p>Filter Hooks allow us to control the list of users that can be accessed by the logged in account. This hook is called whenever the user lands on the Users Dashboard. For our CloudCakes example, let's assume that a manager of each CloudCakes franchise can only see the users that have done business with their specific franchise.</p> <p>In the Auth0 dashboard, each franchise has it's own custom database connection. For example, <code>CloudCakes-Franchise-2479</code> is a database connection containing the users that signed up with CloudCakes Store 2479. We'll also assume that the <code>department</code> of each manager is <code>Franchise Owner</code>. Finally, we'll assume that each franchise owner has an additional <code>app_metadata</code> value for the franchise that they own, let's say <code>franchise_owned</code> is the field. A sample <code>app_metadata</code> therefore may be:</p> <pre><code class="js ">{ "roles": "Delegated Admin - User", "department": "Franchise Owner", "franchise_owned" : "2479" } </code></pre> <p>What we want to do is only display users that belong to CloudCakes Store 2479. Let's see how we can accomplish this with a Filter Hook.</p> <pre><code class="js ">function(ctx, callback) { // Get the department from the current user's metadata. var department = ctx.request.user.app_metadata &amp;&amp; ctx.request.user.app_metadata.department; var franchise = ctx.request.user.app_metadata &amp;&amp; ctx.request.user.app_metadata.franchise_owned; // If the user does not belong to a department we'll throw an error. if (!department || !department.length) { return callback(new Error('The current user is not part of any department.')); } // The Executive department can see all users. if (department === 'Executive') { return callback(); } else if(department === 'Franchise Owner') { // More details on syntax of query available here: https://auth0.com/docs/api/management/v2/user-search return callback(null, 'identities.connection:"CloudCakes-Franchise-' + franchise + '"'); } return callback(); } </code></pre> <p>This Filter Hook will display all users for all connections if the department is an Executive, but will only display users belonging to a specific franchise if the logged in account belongs to the Franchise Owner department. For the filter, you can input any filter query in <a href="https://auth0.com/docs/api/management/v2/user-search">Lucene syntax</a>, so let's say you wanted to enhance the filter results to also return the list of other franchise owners as well. Writing this query:</p> <pre><code class="js">... return callback(null, 'identities.connection:"CloudCakes-Franchise-' + franchise + '" OR app_metadata.department:"Franchise Owner"'); ... </code></pre> <p>will return the list of users belonging to a franchise but also all of the other franchise owners in the system. This could be useful if you wanted to, for example, give managers to ability to view contact details of all the other franchise owners.</p> <h4>Access Hook</h4> <p>Access hooks determine what actions a logged in account is allowed to do with the user accounts they can view. For example, certain accounts may only be able to read data, while others may be able to edit or delete user accounts. In the CloudCakes example, we'd want the logged in user to be able to only read the data of other franchise owners, but they should be allowed to do everything with users belonging to their connection. Let's see how we would implement this functionality.</p> <pre><code class="js ">function(ctx, callback) { // Get the department from the current user's metadata. var department = ctx.request.user.app_metadata &amp;&amp; ctx.request.user.app_metadata.department; var franchise = ctx.request.user.app_metadata &amp;&amp; ctx.request.user.app_metadata.franchise_owned; if (!department || !department.length) { return callback(new Error('The current user is not part of any department.')); } if (department === 'Franchise Owner') { // Check to see if the user and the account accessed share a franchise store if(!ctx.payload.user.app_metadata.franchise_owned || ctx.payload.user.app_metadata.franchise_owned !== franchise){ // If they do not, only allow the user to read data if(ctx.payload.action === 'read:user'){ return callback(); } else { // Otherwise return an error return callback(new Error('You can only read user data')); } } else { // If the franchise store is the same, then we can assume that the account is a customer account of the franchise return callback(); } } return callback(); } </code></pre> <p>As you can see with just these two hooks in place, we can create fine-grained access control for our organization. We can query off of any data we have on our users and decide what actions the logged in account can take. The following are supported actions that a logged in Users Dashboard account can take:</p> <ul> <li><code>read:user</code></li> <li><code>delete:user</code></li> <li><code>reset:password</code></li> <li><code>change:password</code></li> <li><code>change:username</code></li> <li><code>change:email</code></li> <li><code>read:devices</code></li> <li><code>read:logs</code></li> <li><code>remove:multifactor-provider</code></li> <li><code>block:user</code></li> <li><code>unblock:user</code></li> <li><code>send:verification-email</code></li> </ul> <h4>Create Hook</h4> <p>The next hook I want to talk about is the Create Hook. The code here is executed when a new user is created from the Users Dashboard. Using the account <code>app_metadata</code> again, we can further fine-tune the experience. For CloudCakes, we want to enforce that only members of the <strong>Executive</strong> department can create franchise owners. Let's see how we would accomplish this.</p> <pre><code class="js"> // Get the department from the current user's metadata. var currentDepartment = ctx.request.user.app_metadata &amp;&amp; ctx.request.user.app_metadata.department; if (!currentDepartment || !currentDepartment.length) { return callback(new Error('The current user is not part of any department.')); } // Check to see if an account being created will belong to the `Franchise Owner` department if(!currentDepartment == 'Executive' &amp;&amp; ctx.payload.memberships[0] == 'Franchise Owner'){ // If it will, but the account attempting to create it is not an Executive, then the call will fail return callback(new Error('You can only create users within your own department.')); } else { // Otherwise create the account return callback(null, { email: ctx.payload.email, password: ctx.payload.password, connection: ctx.payload.connection, app_metadata: { department: ctx.payload.memberships[0] } }); } return callback(); } </code></pre> <p>You may be asking yourself how do you assign membership roles. If you are planning on using the Users Dashboard to create users that will belong to departments, then you can use the Membership Hook.</p> <h4>Membership Hook</h4> <p>The Membership Hook will allow you to add a field in the Create User UI that will allow an account to assign a membership to the account being created. In CloudCakes case we will assign the membership to the <code>department</code> in our <code>app_metadata</code>. The simplest way to do this is as follows:</p> <pre><code class="js ">function(ctx, callback) { return callback(null, { memberships: [ "Executive", "IT", "Franchise Owner" ] }); } </code></pre> <p>Now when the logged in account goes to create a new user from the Users Dashboard, they will be able to assign a department immediatley to the new user.</p> <p><img src="https://cdn.auth0.com/blog/delegated-admin-cloud-cakes/create-with-membership.png" alt="Create User with Membership" /></p> <h3>Settings Query</h3> <p>There is one final hook that we can implement in the Users Dashboard, the settings query. This will allow us to customize the look and feel of Users Dashboard experience. We can edit such settings as which connections to display when creating a new user, which CSS stylesheet to load, or even change the wording of the different sections. For CloudCakes, we want to make sure that when a franchise owner goes to create a new user, the user is automatically created in their database connection. We won't even give them the option of seeing all the other connections. Let's see how we would implement this.</p> <pre><code class="js ">function(ctx, callback) { var department = ctx.request.user.app_metadata &amp;&amp; ctx.request.user.app_metadata.department; if(department === "Franchise Owner"){ return callback(null, { // Only these connections should be visible in the connections picker. // If only one connection is available, the connections picker will not be shown in the UI. connections: [ ctx.request.user.identities.connection ], }); } return callback(); } </code></pre> <p>For more information on fields that you can set via the settings query check out the <a href="https://auth0.com/docs/extensions/delegated-admin#settings-query">docs</a>.</p> <h3>Putting It All Together</h3> <p>Combining Auth0 with the Delegated Administration Dashboard allowed CloudCakes to give each one of their franchise owners centralized access to their users in a safe and secure way. Franchise owners could login and manage their userbase while CloudCakes corporate still owned all of the data under a single umbrella. Extensibility through Hooks made Users Dashboard useful for both the owners of CloudCakes and its franchise partners.</p> <h2>Conclusion</h2> <p>The Delegated Administration Dashboard extension is a great tool for giving limited access to only the Users dashboard of Auth0. It allows organizations to enforce fine-grained permissions for users accessing the dashboard and removes the need for giving full-access to the Auth0 dashboard. Hooks allow the Users Dashboard to meet the needs of any user management workflow whether it's limiting access or enforcing specific criteria. If your organization needs a better way to manage your Auth0 users, give the Delegated Admin extension a try today. If you don't already have an Auth0 account, <a href="javascript:signup()">sign up for free</a> to get started.</p> <blockquote class="tweet-quote"> <a href="https://twitter.com/intent/tweet?text=&quot;The Delegated Admin extension makes is a great tool for giving limited access to the Auth0 dashboard.&quot; via @auth0 http://auth0.com/blog/delegated-admin-v2/"> <p>"The Delegated Admin extension makes is a great tool for giving limited access to the Auth0 dashboard."</p> <p class="tweet-link">TWEET THIS <img src="https://cdn.auth0.com/blog/resources/twitter.svg"></p> </a> </blockquote> <script> $(function() { $('.tweet-quote').on('click', function() { metricsLib.track('blog:share:twitter_quote'); }); }); </script> Beating JSON performance with Protobuf 2017-01-31T08:30:00+00:00 https://auth0.com/blog/beating-json-performance-with-protobuf/ Bruno Krebs https://twitter.com/brunoskrebs <p><strong>TL;DR</strong></p> <p>Protocol buffers, or Protobuf, is a binary format created by Google to serialize data between different services. Google made this protocol open source and now it provides support, out of the box, to the most common languages, like JavaScript, Java, C#, Ruby and others. In our tests, it was demonstrated that this protocol performed up to <strong>6 times faster</strong> than JSON.</p> <h2>What is Protobuf</h2> <p><a href="https://developers.google.com/protocol-buffers/docs/overview">Protocol buffers</a>, usually referred as Protobuf, is a protocol developed by Google to allow serialization and deserialization of structured data. Google developed it with the goal to provide a better way, compared to XML, to make systems communicate. So they focused on making it simpler, smaller, faster and more maintainable then XML. But, as you will see in this article, this protocol even surpassed JSON with better performance, better maintainability and smaller size.</p> <h3>How Does it Differs from JSON?</h3> <p>It is important to note that, although <a href="http://www.json.org/">JSON</a> and <a href="https://developers.google.com/protocol-buffers/docs/overview">Protobuf</a> messages can be used interchangeably, these technologies were designed with different goals. JSON, which stands for JavaScript Object Notation, is simply a message format that arose from a subset of the JavaScript programming language. JSON messages are exchanged in text format and, nowadays, they are completely independent and supported by, virtually, all programming languages.</p> <p>Protobuf, on the other hand, is more than a message format, it is also a set of rules and tools to define and exchange these messages. Google, the creator of this protocol, has made it open source and provides tools to generate code for the most used programming languages around, like <a href="https://developers.google.com/protocol-buffers/docs/reference/javascript-generated">JavaScript</a>, <a href="https://developers.google.com/protocol-buffers/docs/javatutorial">Java</a>, <a href="https://developers.google.com/protocol-buffers/docs/reference/php-generated">PHP</a>, <a href="https://developers.google.com/protocol-buffers/docs/csharptutorial">C#</a>, <a href="https://developers.google.com/protocol-buffers/docs/reference/ruby-generated">Ruby</a>, <a href="https://developers.google.com/protocol-buffers/docs/reference/objective-c-generated">Objective C</a>, <a href="https://developers.google.com/protocol-buffers/docs/pythontutorial">Python</a>, <a href="https://developers.google.com/protocol-buffers/docs/cpptutorial">C++</a> and <a href="https://developers.google.com/protocol-buffers/docs/gotutorial">Go</a>. Besides that, Protobuf has more data types than JSON, like enumerates and methods, and is also heavily used on <a href="https://github.com/grpc">RPCs (Remote Procedure Calls)</a>.</p> <h2>Is Protobuf Really Faster than JSON?</h2> <p>There are several resources online that show that Protobuf performs better than JSON, XML and etc - like <a href="https://github.com/eishay/jvm-serializers/wiki">this one</a> and <a href="https://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/">this one</a> -, but it is always important to check if this is the case for your own needs and use case. Here, at Auth0, I have developed a simple <a href="https://github.com/brunokrebs/auth0-speed-test">Spring Boot application</a> to test a few scenarios and measure how JSON and Protobuf performed. Mostly I have tested serialization of both protocols to make two Java applications communicate and to make a JavaScript web application communicate to this backend.</p> <blockquote><p>The main reason to create these two scenarios - Java to Java and JavaScript to Java - was to measure how this protocol would behave in an enterprise environment like Java and also on an environment where JSON is the native message format. That is, what I show here is data from an environment where JSON is built in and should perform extremely fast (JavaScript engines) and from an environment where JSON is not a first class citizen.</p></blockquote> <p>The short answer to the question is yes, Protobuf is faster than JSON. But this answer is not useful nor interesting without the data that I gathered on my experiments. Let's take a look at the details now.</p> <h3>Test Sample</h3> <p>To support the measurements, I have created three Protobuf messages: <code>Address</code>, to hold just the street and number; <code>Person</code>, to hold the name, a collection of addresses, a collection of mobile numbers, and a collection of email addresses; <code>People</code>, to hold a collection of <code>Person</code> messages. These messages were assembled together in an application with four RESTful endpoints:</p> <ol> <li>One that accepted <code>GET</code> requests and returned a list of 50 thousand people in Protobuf format.</li> <li>Another one that accepted <code>GET</code> requests and returned the same list of 50 thousand people, but in JSON format.</li> <li>A third one that accepted <code>POST</code> requests with any number of people in Protobuf format.</li> <li>A fourth one that accepted <code>POST</code> requests with any number of people in JSON format.</li> </ol> <h3>JavaScript to Java Communication</h3> <p>Since there are a lot of JavaScript engines available, it is valuable to see how the most popular of them behave with this set of data. So I decided to use the following browsers: <a href="https://www.google.com/chrome">Chrome</a>, as this is the most popular browser around and its JavaScript engine is also used by <a href="https://nodejs.org">Node.js</a>; <a href="https://www.mozilla.org/en-US/firefox/new/">Firefox</a>, as this is another very popular browser; and <a href="www.apple.com/safari/">Safari</a>, as this is the default browser on MacBooks and iPhones.</p> <p>The following charts exposes the average performance, of these browsers, on 50 subsequent <code>GET</code> requests to both endpoints - the Protobuf and JSON endpoints. These 50 requests per endpoint were issued twice: first when running the Spring Boot application with compression turned on; and then when running the application with compression turned off. So, in the end, each browser requested 200 times all these 50 thousand people data.</p> <p><img src="https://cdn.auth0.com/blog/protobuf-json/compressed-env-times.png" alt="Comparison of Protobuf/JSON performance on compressed GET requests" /></p> <p><img src="https://cdn.auth0.com/blog/protobuf-json/compressed-env-sizes.png" alt="Comparison of Protobuf/JSON payload sizes on compressed GET requests" /></p> <p>As you can see in the charts above, the results for the <strong>compressed environment</strong> were quite similar for both Protobuf and JSON. Protobuf messages were <strong>9% smaller</strong> than JSON messages and they took only <strong>4% less time</strong> to be available to the JavaScript code. This can sound like nothing, but considering that Protobuf has to be converted from binary to JSON - JavaScript code uses JSON as its object literal format - it is amazing that Protobuf managed to be faster than its counterpart.</p> <p>Now, when we have to deal with <strong>non-compressed messages</strong>, the results change quite a bit. Let's analyze the charts below:</p> <p><img src="https://cdn.auth0.com/blog/protobuf-json/non-compressed-env-times.png" alt="Comparison of Protobuf/JSON performance on non-compressed GET requests" /></p> <p><img src="https://cdn.auth0.com/blog/protobuf-json/non-compressed-env-sizes.png" alt="Comparison of Protobuf/JSON payload sizes on non-compressed GET requests" /></p> <p>On these situations, Protobuf performs even better when compared to JSON. Messages, on this format, were <strong>34% smaller</strong>, and they took <strong>21% less time</strong> to be available to the JavaScript code.</p> <p>When issuing <code>POST</code> requests, the difference gets almost imperceptible as usually this kind of request doesn't deal with heavy messages. More frequent than not, these requests just handle the update of a few fields on a form or something similar. So, to make the test trustworthy, I issued 50 requests with just one <code>Person</code> message and a few properties, like emails addresses and mobiles, on it. The results can be checked below:</p> <p><img src="https://cdn.auth0.com/blog/protobuf-json/post-requests-times.png" alt="Comparison of Protobuf/JSON performance on POST requests" /></p> <p><img src="https://cdn.auth0.com/blog/protobuf-json/post-requests-sizes.png" alt="Comparison of Protobuf/JSON payload sizes on POST requests" /></p> <p>In this case the messages sizes were not even different, mainly because they were so small that the meta-data about them were heavier than the data itself. And the time to issue the request and get a response back was almost equal as well, with only a <strong>4% better</strong> performance from Protobuf requests when compared to JSON requests.</p> <h3>Java to Java Communication</h3> <p>If we were to use only JavaScript environments, like Node.js applications and web browsers as interfaces, I would think twice before investing time on learning and migrating endpoints to Protobuf. But, when we start adding other platforms, like Java, Android, Python, etc, then we start to see real gains on using Protobuf.</p> <p>The chart below was generated with the average performance of 500 <code>GET</code> requests issued by one Spring Boot application to another Spring Boot application. Both applications were deployed on different virtual machines hosted by <a href="https://www.digitalocean.com/">Digital Ocean</a>. I chose this strategy to simulate a common scenario where two microservices are communicating through the wire. Let's see how this simulation ran:</p> <p><img src="https://cdn.auth0.com/blog/protobuf-json/java-times.png" alt="Comparison of Protobuf/JSON performance on GET requests issued by a Java app to another Java app" /></p> <p>Now this is a great performance improvement. When using Protobuf on a <strong>non-compressed</strong> environment, the requests took <strong>78% less time</strong> than the JSON requests. This shows that the binary format performed almost <strong>5 times faster</strong> than the text format. And, when issuing these requests on a <strong>compressed</strong> environment, the difference was even bigger. Protobuf performed <strong>6 times faster</strong>, taking only 25ms to handle requests that took 150ms on a JSON format.</p> <p>As you can see, when we have environments that JSON is not a native part of, the performance improvement is huge. So, whenever you face some latency issues with JSON, consider migrating to Protobuf.</p> <h2>Are There Any Other Advantages and Disadvantages?</h2> <p>As every decision that you take, there will be advantages and disadvantages. And, when choosing one message format or protocol over another, this is not different. Protocol buffers suffers from a few issues, as I list below:</p> <ul> <li><strong>Lack of resources</strong>. You won't find that many resources (do not expect a very detailed documentation, nor too many blog posts) about using and developing with Protobuf.</li> <li><strong>Smaller community</strong>. Probably the root cause of the first disadvantage. On Stack Overflow, for example, you will find roughly 1.500 questions marked with Protobuf tags. While JSON have more than 180 thousand questions on this same platform.</li> <li><strong>Lack of support</strong>. Google does not provide support for other programming languages like Swift, R, Scala and etc. But, sometimes, you can overcome this issue with third party libraries, like <a href="https://github.com/apple/swift-protobuf">Swift Protobuf provided by Apple</a>.</li> <li><strong>Non-human readability</strong>. JSON, as exchanged on text format and with simple structure, is easy to be read and analyzed by humans. This is not the case with a binary format.</li> </ul> <p>Although choosing Protobuf will bring these disadvantages along, this protocol is a lot faster, on some situations, as I demonstrated above. Besides that, there are a few other advantages:</p> <ul> <li><strong>Formal format</strong>. Formats are self-describing.</li> <li><strong>RPC support</strong>. Server RPC interfaces can be declared as part of protocol files.</li> <li><strong>Structure validation</strong>. Having a predefined and larger, when compared to JSON, set of data types, messages serialized on Protobuf can be automatically validated by the code that is responsible to exchange them.</li> </ul> <h2>How Do We Use Protobuf?</h2> <p>Now that you already know that Protobuf is faster than JSON and you also know its advantages and disadvantages, let's take a look on how to use this technology. Protobuf has three main components that we have to deal with:</p> <ol> <li><strong>Message descriptors</strong>. When using Protobuf we have to define our messages structures in <code>.proto</code> files.</li> <li><strong>Message implementations</strong>. Messages definitions are not enough to represent and exchange data in any programming language. We have to generate classes/objects to deal with data in the chosen programming language. Luckily, Google provides code generators for the most common programming languages.</li> <li><strong>Parsing and Serialization</strong>. After defining and creating Protobuf messages, we need to be able to exchange these messages. Google helps us here again, as long as we use one of the supported programming language.</li> </ol> <p>Let's catch a glimpse of each of components.</p> <h3>Protobuf Message Definition</h3> <p>As already mentioned, messages on Protobuf are describe in <code>.proto</code> files. Below you can find an example of the three message descriptors that I used in my performance tests. I have defined all of them in the same file, which I called <code>people.proto</code>.</p> <pre><code>syntax = "proto3"; package demo; option java_package = "com.auth0.protobuf"; message People { repeated Person person = 1; } message Person { string name = 1; repeated Address address = 2; repeated string mobile = 3; repeated string email = 4; } message Address { string street = 1; int32 number = 2; } </code></pre> <p>The three messages above are very simple and easy to understand. The first message, <code>People</code>, contains just a collection of <code>Person</code> messages. The second message, <code>Person</code>, contains a <code>name</code> of type <code>string</code>, a collection of <code>Address</code> messages, a collection of <code>mobile</code> numbers that are hold as <code>string</code> and, lastly, a collection of <code>email</code> addresses, also hold as <code>string</code>. The third message, <code>Address</code>, contains two properties: the first one is <code>street</code> of type <code>string</code>; and the second one is <code>number</code> of type <code>int32</code>.</p> <p>Besides these definitions, there are three lines, at the top of the file, that helps the code generator:</p> <ol> <li>First there is a <code>syntax</code> defined with the value <code>proto3</code>. This is the version of Protobuf that I'm using, which, as the time of writing, it is the latest version. It is important to note that previous versions of Protobuf used to allow the developers to be more restrictive, about the messages that they exchanged, through the usage of the <code>required</code> keyword. This is now deprecated and not available anymore.</li> <li>Second there is a <code>package demo;</code> definition. This configuration is used to nest the generated classes/objects created.</li> <li>Third, there is a <code>option java_package</code> definition. This configuration is also used by the generator to nest the generated sources. The difference here is that this is applied to Java only. I have used both configurations to make the generator behave differently when creating code to Java and when creating code to JavaScript. That is, Java classes were created on <code>com.auth0.protobuf</code> package, and JavaScript objects were created under <code>demo</code>.</li> </ol> <p>There are a lot more options and data types available on Protobuf. Google has a very good documentation on this regard <a href="https://developers.google.com/protocol-buffers/docs/proto3">over here</a>.</p> <h3>Message Implementations</h3> <p>To generate the source code for the <code>proto</code> messages, I have used two libraries:</p> <ol> <li>For Java, I have used the <code>Protocol Compiler</code> provided by Google. <a href="https://developers.google.com/protocol-buffers/docs/downloads">This page on Protocol Buffers' documentation</a> explains how to install it. As I use <a href="http://brew.sh/">Brew</a> on my MacBook, it was just a matter of issuing <code>brew install protobuf</code>.</li> <li>For JavaScript, I have used <code>protobuf.js</code>. You can find its source and instructions <a href="https://github.com/dcodeIO/protobuf.js">over here</a>.</li> </ol> <p>For most of the supported programming languages, like Python, C#, etc, Google's <code>Protocol Compiler</code> will be good enough. But for JavaScript, <code>protobuf.js</code> is better, since it has better documentation, <a href="https://github.com/dcodeIO/protobuf.js/blob/2db4305ca67d003d57aa14eb23f25eb6c3672034/README.md#compatibility">better support</a> and better performance - I have also ran the performance tests with the default library provided by Google, but with it I got worse results than I got with JSON.</p> <h3>Parsing and Serialization with Java</h3> <p>After having the <code>Protocol Compiler</code> installed, I generated the Java source code with the following command:</p> <pre><code class="bash">protoc --java_out=./src/main/java/ ./src/main/resources/people.proto </code></pre> <p>I issued this command from the root path of the project and I added two parameters: <code>java_out</code>, which defined <code>./src/main/java/</code> as the output directory of Java code; and <code>./src/main/resources/people.proto</code> which was the path for the <code>.proto</code> file.</p> <p>The code generated is quite complex, but fortunately its usage is not. For each message compiled, a builder is generated. Check it out how easy it is:</p> <pre><code class="java">final Address address1 = Address.newBuilder() .setStreet("Street Number " + i) .setNumber(i) .build(); final Address address2 = Address.newBuilder() .setStreet("Street Number " + i) .setNumber(i) .build(); final Person person = Person.newBuilder() .setName("Person Number " + i) .addMobile("111111" + i) .addMobile("222222" + i) .addEmail("emailperson" + i + "@somewhere.com") .addEmail("otheremailperson" + i + "@somewhere.com") .addAddress(address1) .addAddress(address2) .build(); </code></pre> <p>These instances alone just represent the messages, so I also needed a way to exchange them. Spring provides support for Protobuf and there are a few resources out there - like <a href="https://spring.io/blog/2015/03/22/using-google-protocol-buffers-with-spring-mvc-based-rest-services">this one on Spring's blog</a>, and <a href="http://www.baeldung.com/spring-rest-api-with-protocol-buffers">this one from Baeldung</a> - that helped me on that matter. Just be aware that, as in any Java project, a few dependencies are needed. These are the ones that I had to add to my Maven project:</p> <pre><code class="xml">&lt;dependencies&gt; &lt;!-- Spring Boot deps and etc above.. --&gt; &lt;dependency&gt; &lt;groupId&gt;com.google.protobuf&lt;/groupId&gt; &lt;artifactId&gt;protobuf-java&lt;/artifactId&gt; &lt;version&gt;3.1.0&lt;/version&gt; &lt;/dependency&gt; &lt;dependency&gt; &lt;groupId&gt;com.google.protobuf&lt;/groupId&gt; &lt;artifactId&gt;protobuf-java-util&lt;/artifactId&gt; &lt;version&gt;3.1.0&lt;/version&gt; &lt;/dependency&gt; &lt;dependency&gt; &lt;groupId&gt;com.googlecode.protobuf-java-format&lt;/groupId&gt; &lt;artifactId&gt;protobuf-java-format&lt;/artifactId&gt; &lt;version&gt;1.4&lt;/version&gt; &lt;/dependency&gt; &lt;/dependencies&gt; </code></pre> <h3>Parsing and Serialization with JavaScript</h3> <p>The library used, <code>protobuf.js</code>, helped me to compile the <code>.proto</code> messages to JavaScript and also to exchange these messages. The first thing that I had to do was to install it as a dependency. For this, I have used <a href="https://nodejs.org">Node.js</a> and <a href="https://www.npmjs.com">NPM</a>:</p> <pre><code class="bash">npm install -g protobufjs </code></pre> <p>The command above enabled me to use <code>pbjs</code> command line utility (CLI) to generate the code. The following command is how I used this CLI:</p> <pre><code class="bash">pbjs -t static-module -w commonjs -o \ ./src/main/resources/static/people.js \ ./src/main/resources/people.proto </code></pre> <p>After generating the JavaScript code, I used another tool, <a href="http://browserify.org/"><code>browserify</code></a>, to bundle the generated code along with <code>protobuf.js</code> in a single file:</p> <pre><code class="bash"># Installing browserify globally to use wherever I want. npm install -g browserify # Running browserify to bundle protobuf.js and message objects together. browserify ./src/main/resources/static/people.js -o ./src/main/resources/static/bundle.js </code></pre> <p>By doing that I was able to add a single dependency to my <code>index.html</code> file:</p> <pre><code class="html">&lt;html&gt; &lt;body&gt; &lt;!-- This has all my protobuf dependecies: three messages and protobuf.js code. --&gt; &lt;script src="bundle.js"&gt;&lt;/script&gt; &lt;/body&gt; &lt;/html&gt; </code></pre> <p>Finally, after referencing the bundle, I was then able to issue <code>GET</code> and <code>POST</code> requests to my Protobuf endpoints. The following code is an AngularJS HTTP <code>GET</code> request and, as such, must be very easy to understand:</p> <pre><code class="js">// Just a shortcut. const People = protobuf.roots.default.demo.People; let req = { method: 'GET', responseType: 'arraybuffer', // make it clear that it can handle binary url: '/some-protobuf-get-endpoint' }; return $http(req).then(function(response) { // We need to encapsulate the response on Uint8Array to avoid // getting it converted to string. ctrl.people = People.decode(new Uint8Array(response.data)).person; }); </code></pre> <p>The <code>POST</code> request is trivial as well:</p> <pre><code class="js">// Just populating some usual object literals. let address = new Address({ street: 'Street', number: 100 }); let person = { name: 'Some person', address: [], mobile: [], email: [] }; person.address.push(address); person.mobile.push('(1) 732-757-2923'); person.email.push('someone@somewhere.com'); // Encapsulating the object literal inside the protobuf object. let people = new People({ person: [new Person(person)] }); // Building the POST request. let post = { method: 'POST', url: '/some-protobuf-post-endpoint', // Transforming to binary. data: People.encode(people).finish(), // Avoiding AngularJS to parse the data to JSON. transformRequest: [], headers: { // Tells the server that a protobuf message is being transmitted. 'Content-Type': 'application/x-protobuf' } }; // Issuing the POST request built above. return $http(post).then(function() { console.log('Everything went just fine'); }); </code></pre> <p>Not difficult to use <code>protobuf.js</code> library to exchange binary data, right? If you want, you can also check the JavaScript code, that I used to compare Protobuf and JSON performance, directly on <a href="https://github.com/brunokrebs/auth0-speed-test/blob/master/src/main/resources/static/index.html#L46">my GitHub repo</a>.</p> <h2>Conclusion</h2> <p>I have to be honest, I was hoping to come across a more favorable scenario for Protobuf. Of course, being able to handle, on a Java to Java communication, 50 thousand instances of <code>Person</code> objects in 25ms with Protobuf, while JSON took 150ms, is amazing. But on a JavaScript environment these gains are much lower.</p> <p>Nevertheless, considering that JSON is native to JavaScript engines, Protobuf still managed to be faster.</p> <p>Also, one important thing that I noticed is that, even though there are not many resources around about Protobuf, I was still able to use it in different environments without having a hard time. So I guess I will start using this technology with more frequency now.</p> <p>How about you? What do you think about the speed of Protobuf? Are you considering using it in your projects? Leave a comment!</p> Mozilla Replaces Persona with Auth0 for Identity and Access Management (IAM) 2017-01-30T08:30:00+00:00 https://auth0.com/blog/auth0-mozilla-partnership/ Martin Gontovnikas http://twitter.com/mgonto <p><strong>BELLEVUE, WA</strong> - As of November 30, 2016, Mozilla, one of the largest open-source organizations on the web, has replaced their longstanding Persona authentication system and has instead chosen Auth0 for all of their identity and access management (IAM) needs moving forward. The removal of Persona also means that Mozilla will no longer offer a public-facing authentication service.</p> <p>Auth0 has already been integrated in many Mozilla web properties including <a href="https://mozillians.org/">Mozillians</a>, <a href="https://moderator.mozilla.org/">Mozilla Moderator</a>, and <a href="https://reps.mozilla.org/">Mozilla Reps</a>. Mozilla is making use of Auth0’s <a href="https://auth0.com/passwordless">passwordless authentication</a>, <a href="https://auth0.com/docs/identityproviders#enterprise">LDAP</a>, and <a href="https://auth0.com/docs/identityproviders#social">social connections</a> features to make it easier for contributors and employees to gain access to the various services Mozilla provides.</p> <p><img src="https://cdn.auth0.com/blog/auth0-mozilla-pr/mozilla.png" alt="Mozilla Website" /></p> <p>We are honored to have Mozilla as both a customer and ally. Auth0 has always embraced and contributed to the open-source community and we built our platform around open standards like OAuth and <a href="https://auth0.com/security">OpenID Connect</a> so that our platform can easily integrate and interoperate in any organization while still following industry standards and best practices.</p> <h3>About Auth0</h3> <p>Auth0 provides frictionless authentication and authorization for developers. The company makes it easy for developers to implement even the most complex identity solutions for their web, mobile, and internal applications. Ultimately, Auth0 allows developers to control how a person’s identity is used with the goal of making the internet safer. As of August, 2016, Auth0 has raised over $24m from Trinity Ventures, Bessemer Venture Partners, K9 Ventures, Silicon Valley Bank, Founders Co-Op, Portland Seed Fund and NXTP Labs, and the company is further financially backed with a credit line from Silicon Valley Bank.</p> <p>For more information visit <a href="https://auth0.com">https://auth0.com</a> or follow <a href="https://twitter.com/auth0">@auth0</a> on Twitter.</p> Machine Learning for Everyone - Part 2: Spotting anomalous data 2017-01-27T12:00:00+00:00 https://auth0.com/blog/machine-learning-for-everyone-part-2-abnormal-behavior/ Pablo Casas https://twitter.com/datasciheroes <h3>Overview</h3> <p>We're going to analyze data that contain cases flagged as abnormal. So we'll build a predictive model in order to spot cases that are not currently flagged as abnormal, but behaving like ones that are.</p> <p>Topics are:</p> <ul> <li>Creating a predictive model (random forest)</li> <li>Introduction to ROC value (model performance)</li> <li>Understanding of label and score prediction</li> <li>Inspection of suspicious cases (audit)</li> <li>Prediction and dimension reduction (t-SNE)</li> </ul> <h3>Let's start!</h3> <p>This post contains R code and some machine learning explanations, which can be extrapolated to other languages such as Python. The idea is to create a case study giving the reader the opportunity to recreate results. You will need the following:</p> <ul> <li>Download <a href="https://cloud.r-project.org/" target="blank">R engine</a></li> <li>Download <a href="https://www.rstudio.com/products/rstudio/download/">RStudio IDE</a></li> </ul> <blockquote><p>Note: There are some points oversimplified in the analysis, but hopefully you'll become curious to learn more about this topic, in case you've never done a project like this.</p></blockquote> <p>First, install and load the packages (libraries) containing the functions we'll use in this project, and load the data.</p> <pre><code class="r"># delete these installation lines after 1st run install.packages("caret") install.packages("funModeling") install.packages("Rtsne") </code></pre> <pre><code class="r">library(caret) library(funModeling) library(Rtsne) ## download data from github, if you have any problem go directly to github: https://github.com/auth0/machine-learning-post-2-abnormal-behavior url_git_data = "https://raw.github.com/auth0/machine-learning-post-2-abnormal-behavior/master/data_abnormal.txt" download.file(url_git_data,"data_abnormal.txt") ## reading source data data=read.delim("data_abnormal.txt", header = T, stringsAsFactors = F, sep = "\t") </code></pre> <p>The data contains the following columns:</p> <pre><code class="r">colnames(data) </code></pre> <pre><code>## [1] "id" "abnormal" "var_1" "var_2" "var_3" "var_4" ## [7] "var_5" "var_6" "var_7" "var_8" </code></pre> <p>We are going to predict column <code>abnormal</code> based on <code>var_1</code>, <code>var_2</code> ... <code>var_8</code> variables.</p> <p>Inspecting target variable:</p> <pre><code class="r">freq(data, "abnormal") </code></pre> <p><img src="https://cdn.auth0.com/blog/machine-learning-2/target_distribution.png" alt="abnormal variable distribution"></p> <p>Almost 3 percent of cases are flagged as abnormal.</p> <p>Next, we create the predictive model using <strong>Random Forest</strong>, doing the model parameter tuning with <code>caret</code> library using 4-fold cross-validation optimized for the ROC metric. We'll come back to this later.</p> <p><em>You can find the basics of random forest in the <a href="https://auth0.com/blog/machine-learning-for-everyone/" target="blank">first post</a> of this series.</em></p> <pre><code class="r">################################################ ## MODEL CREATION: ################################################ set.seed(999) ## Setting the validation metric: Cross-Validation 4-fold. fitControl = trainControl(method = "cv", number = 4, classProbs = TRUE, summaryFunction = twoClassSummary) ## Creating the model, given the cross-validation method. fit_model = train(abnormal ~ var_1 + var_2 + var_3 + var_4 + var_5 + var_6 + var_7 + var_8, data = data, method = "rf", trControl = fitControl, verbose = FALSE, metric = "ROC") </code></pre> <p>There are some important things to note about the last layout:</p> <p>The <code>mtry</code> column indicates a parameter that is optimized by the library <code>caret</code>.</p> <p>The selection is based on the ROC metric. This metric goes from 0.5 to 1 and indicates how well the model distiguishes between <code>True Positve</code> and <code>False Positive</code> rates. The higher the better.</p> <h3>Choosing the "best" model</h3> <p>Predictive models have some parameters that can be tuned in order to improve predictions based on the input data. In the last example, <code>caret</code> chooses the <strong>best model configuration</strong> based on a desired accuracy metric---ROC, in this case.</p> <p>Random forest does not have many parameters to tune compared with other similar gradient boosting machines. The parameter to tune was <code>mtry</code>.</p> <p><code>caret</code> tested 3 different values of <code>mtry</code>, and the value which maximizes the ROC value is <code>6</code>.</p> <p><em>Cross-validating results is really important; you can get more information in ref. [1]</em></p> <h3>What is the ROC value?</h3> <p>This is a long -long- topic, but here we try to introduce you to some aspects to start becoming familiar with it.</p> <h4>Some history</h4> <p>During World War II, radar detected if an airplane was coming or not, so they sent out the following alerts:</p> <ul> <li><code>Hey, a plane was spotted!</code> (positive prediction)</li> <li><code>Be easy, no plane is coming....</code> (negative prediction)</li> </ul> <p>These outcomes can be <code>True</code> or <code>False</code>, so we have four possibilites:</p> <p>1- If the detection of <code>Hey, a plane was spotted!</code> is <code>True</code>, it is called a <code>True Positive</code>.</p> <p>2- On the other hand, if <code>Hey, a plane was spotted!</code> is <code>False</code>, the result is a <code>False Positive</code>, which implies that the radar (predictive model) <em>said</em> a plane was coming but there isn't actually a plane out there.</p> <p>3- The radar <em>says</em> <code>Be easy, no plane is coming....</code> and the real result is <strong>Positive</strong>: It's a <code>True Negative</code>.</p> <p>4- The radar <em>says</em> <code>Be easy, no plane is coming....</code> and the real result is <strong>Negative</strong>: It's a <code>False Negative</code>.</p> <h4>Abnormal example data</h4> <p>In the data we used to build the model, we have:</p> <ul> <li><code>Positive</code> is when abnormal=<code>yes</code>.</li> <li><code>Negative</code> is when abnormal=<code>no</code>.</li> </ul> <p>Normally we associate the positive value with the less representative value, which is the one we are trying to explain and the least common.</p> <h4>Analysis of possibilites</h4> <p>Points 1 and 3 imply the radar (or the predictive model) asserts the prediction.</p> <p>With points 2 and 4, the model failed---it predicted one thing and it was actually the opposite.</p> <p>The ROC value measures the trade-off between the <code>True Positive</code> and <code>True Negative</code> rates. This is because we need to be sure about what the model is saying when it detects a <code>Positive</code> outcome:</p> <p><strong>Is this <code>Positive</code> prediction reliable or not?</strong></p> <h4>Usage in medicine</h4> <p>This accuracy metric is so powerful that it is used in other fields, such as <strong>medicine</strong>, to measure the accuracy of certain diagnoses:</p> <p><em>"The flu test for this patient was positive"</em>: if this result is confirmed after a while or a second test, we've got a true positve.</p> <p>It is used in many tests in which the result is either <code>true</code> or <code>false</code>; it's very important to know if we can trust this result.</p> <h4>Usage in Auth0</h4> <p>We did some proof of concept to automatically spot the most suspicious login cases in order to boost current <strong>anomaly detection</strong> feature, and ROC curve was a good option to test the predictive model sensitivity.</p> <p><em>More info about current anomaly detection feature at ref. [2]</em></p> <h4>Understanding the extremes</h4> <p>Knowing extreme ROC values is a good approach to better understanding it:</p> <ul> <li>An ROC value of <code>1</code> indicates all the <code>Positive</code> values returned by the model are correct. Perfect model.</li> <li>An ROC value of <code>0.5</code> indicates all the <code>Positive</code> values returned by the model have results similar to random guessing. This is the worst model.</li> </ul> <p><em>See more about ROC in ref. [3]</em></p> <h3>Going back to the predictive model</h3> <p>We talked about the predictive model output, which is something like: <code>positive / negative</code> or <code>yes / no</code>. But it's better to work with probabilities (also known as <strong>score</strong>) so the output of any predictive model (in binary or multi-label class prediction) should be the score.</p> <p><em>For a longer explanation, see ref. [4]</em>.</p> <p>Once we get the score value, we can select all cases above a threshold and label them as <code>abnormal</code>.</p> <p>We assign the probability of being <code>abnormal=yes</code> to each case:</p> <pre><code class="r">data$score=predict(fit_model$finalModel, type="prob")[,2] </code></pre> <p>We can kept with those cases with are actually <code>abnormal=no</code>:</p> <pre><code class="r"># filtering cases... data_no_abnormal=subset(data, abnormal=="no") </code></pre> <p>We obtain the top 2% of cases with the highest score for being abnormal:</p> <pre><code class="r"># obtaining the score to filter top 2% cutoff=quantile(data_no_abnormal$score, probs = c(0.98)) # filtering most suspicious cases data_to_inspect=subset(data_no_abnormal, score&gt;cutoff) </code></pre> <p>And here we've got in <code>data_to_inspect</code> ~ 60 cases which are actually no abnormal, but <strong>they are showing a behavior of being suspicious</strong>.</p> <p>Displaying only the first 6 suspicious IDs to further inspect...</p> <pre><code class="r">head(data_to_inspect$id) </code></pre> <pre><code>## [1] 59 94 105 107 224 259 </code></pre> <p><strong>Is there a way to visualize how the predictive model "sees" data and assigns the probabilities?</strong></p> <h3>Let's talk about projections</h3> <p>We've built a machine learning model in order to know the abnormal cases, using random forest.</p> <p>Predictive models handle several variables <strong>at the same time</strong>, which is different from the classical reporting approach, in which you see two or three variables in one plot.</p> <p>In the following example, you'll see how <strong>eight variables are mapped in only two dimensions</strong>. In this case there are eight, but it could be thousands. This is quite fancy since it is like a compression of the information.</p> <p>You've probably already seen this "complex" technique: in geographical maps. They map three dimensions into two:</p> <p><img src='https://cdn.auth0.com/blog/machine-learning-2/map_projections.png' width="350px" alt="Variable reduction"></p> <p>There are several ways to do this with data; the most popular is probably Principal Component Analysis -aka PCA- (however, this doesn't lead to good visualizations). The one we used in this post is <strong>t-Distributed Stochastic Neighbor Embedding</strong>, which is also implemented in languages other than <strong>R</strong>. <em>More info at ref. [5].</em></p> <p><em>Google did a live demo based on text data, see ref. [6].</em></p> <h4>Hands on R!</h4> <p>First some data preparation--excluding id and score variables to create the t-SNE model. Also, converting all string variables into numeric ones since t-SNE doesn't support this type of variable (one-hot encoding or dummy variables).</p> <p>Actually, we're going to map 17 variables (not eight) because of this transformation.</p> <pre><code class="r"># excluding id column and score variable data_2=data[,!(names(data) %in% c("id", "score"))] d_dummy = dummyVars(" ~ .", data = data_2) data_tsne = data.frame(predict(d_dummy, newdata = data)) </code></pre> <p>Now we create the t-SNE model, adding it to the <code>score</code> variable we created before.</p> <pre><code class="r">set.seed(999) tsne_model = Rtsne(as.matrix(data_tsne), check_duplicates=FALSE, pca=TRUE, perplexity=30, theta=0.5, dims=2) d_tsne = as.data.frame(tsne_model$Y) d_tsne$abnormal = as.factor(data$abnormal) d_tsne$score=data$score d_tsne = d_tsne[order(d_tsne$abnormal),] </code></pre> <p><strong>Now the magic!</strong> Plotting the resulting t-SNE model which maps 17 variables in two dimensions :)</p> <pre><code class="r">ggplot(d_tsne, aes(x=V1, y=V2, color=abnormal)) + geom_point(size=0.25) + guides(colour=guide_legend(override.aes=list(size=6))) + xlab("") + ylab("") + ggtitle("t-SNE on Abnormal Data") + theme_light(base_size=20) + theme(axis.text.x=element_blank(), axis.text.y=element_blank()) + geom_point(data=d_tsne[d_tsne$abnormal=="yes",], color="black", alpha=1,shape=21) + geom_point(data=d_tsne[d_tsne$abnormal=="no" &amp; d_tsne$score&gt;=cutoff,], color="blue", alpha=0.8,shape=5, aes(color=Class)) + scale_colour_brewer(palette = "Set2") </code></pre> <p><img src="https://cdn.auth0.com/blog/machine-learning-2/tsne_abnormal_data.png" alt="tsne on abnormal data" width="500px"></p> <h3>But what are we seeing there? Analysis</h3> <ul> <li><p><strong>Blue rhomboids</strong> represent the cases which are actually not flagged as abnormal, but are flagged as "highly abnormal" by the predictive model (this is what was analyzed before).</p></li> <li><p><strong>Pink points</strong> represent the cases which are actually flagged as abnormal.</p></li> <li><p><strong>Green points</strong> are the cases which are not actually abnormal, having a low likelihood of being one of them.</p></li> </ul> <p><strong>Similar cases tend to be closer in the plot.</strong></p> <p>Pink cases are close to the blue ones. These are the cases predicted as <strong>highly suspicious</strong> and that share similar behavior with the ones actually flagged as abnormal.</p> <p>That's why we left the <code>score</code> variable out of the t-SNE model creation. This model put closely together some cases that were actually <code>abnormal</code> and <code>not abrnormal</code>, and this makes sense since these cases were flagged by the random forest as suspicious ones.</p> <p>Look at the biggest islands made of green points---there are no abnormal points, flagged or predicted, near them.</p> <h4>Conclusions</h4> <p>The cases flagged as abnormal, plus the top 2 percent of suspicious ones detected by the random forest, are mapped closer together away from the normal cases, because they behave differently. This is one way of uncovering the information in the data.</p> <p>Time to play with your own data :)</p> <h3>References</h3> <ul> <li>[1] Why validate predictive models? <a href="http://livebook.datascienceheroes.com/model_performance/knowing_the_error.html" target="blank">Knowing the error</a></li> <li>[2] <a href="https://auth0.com/docs/anomaly-detection" target="blank">Anomaly detection</a> feature at Auth0.</li> <li>[3] <a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic" target="blank">Wikipedia ROC Curve</a></li> <li>[4] <a href="http://livebook.datascienceheroes.com/scoring/scoring.html" target="blank">Data Science Live Book - Data Scoring</a></li> <li>[5] Original implementation <a href='https://lvdmaaten.github.io/tsne/'>t-Distributed Stochastic Neighbor Embedding</a></li> <li>[6] <a href="https://research.googleblog.com/2016/12/open-sourcing-embedding-projector-tool.html"> Open sourcing the Embedding Projector: a tool for visualizing high dimensional data</a></li> </ul> <p><a href="https://github.com/auth0/machine-learning-post-2-abnormal-behavior" target="blank">Link</a> to clone from Github (only R code).</p> Testing React Applications with Jest 2017-01-26T17:00:00+00:00 https://auth0.com/blog/testing-react-applications-with-jest/ Joyce Echessa https://twitter.com/joyceechessa <h2>Introduction</h2> <p>Writing tests is an integral part of application development. Testing results in software that has fewer bugs, more stability, and is easier to maintain. In this article, we'll look at how to test a React application using the Jest testing framework.</p> <p><a href="https://github.com/facebook/jest">Jest</a> is a JavaScript test runner maintained by Facebook. A test runner is software that looks for tests in your codebase, runs them and displays the results (usually through a CLI interface).</p> <p>The following are some of the features that Jest offers.</p> <ul> <li><strong>Performance</strong> - Jest run tests in parallel processes thus minimizing test runtime.</li> <li><strong>Mocking</strong> - Jest allows you to <a href="http://stackoverflow.com/a/2666006/1380071">mock</a> objects in your test files. It supports <a href="https://facebook.github.io/jest/docs/mock-functions.html#content">function mocking</a>, <a href="https://facebook.github.io/jest/docs/manual-mocks.html#content">manual mocking</a> and <a href="https://facebook.github.io/jest/docs/timer-mocks.html#content">timer mocking</a>. You can mock specific objects or turn on automatic mocking with <a href="https://facebook.github.io/jest/docs/configuration.html#automock-boolean">automock</a> which will mock every component/object that the component/object test depends on.</li> <li><strong>Snapshot testing</strong> - When using Jest to test a <a href="https://facebook.github.io/react/">React</a> or <a href="https://facebook.github.io/react-native/">React Native</a> application, you can write a snapshot test that will save the output of a rendered component to file and compare the component's output to the snapshot on subsequent runs. This is useful in knowing when your component changes its behaviour.</li> <li><strong>Code coverage support</strong> - This is provided with Jest with no additional packages or configuration.</li> <li><strong>Test isolation and sandboxing</strong> - With Jest, no two tests will ever conflict with each other, nor will there ever be a global or module local state that is going to cause trouble. Sandboxed test files and automatic global state resets for every test.</li> <li><strong>Integrates with other testing libraries</strong> - Jest works well with other testing libraries (e.g. <a href="https://github.com/airbnb/enzyme">Enzyme</a>, <a href="http://chaijs.com/">Chai</a>).</li> </ul> <p>Jest is a Node-based runner which means that it runs tests in a Node environment as opposed to a real browser. Tests are run within a fake DOM implementation (via <a href="https://github.com/tmpvar/jsdom">jsdom</a>) on the command line.</p> <p>You should note though that while Jest provides browser globals such as <code>window</code> by using jsdom, their behavior is only an approximation of their counterparts on a real browser. Jest is intended for unit testing an application's logic and components rather than for testing it for any DOM quirks it might encounter. For this, it is recommended that you use a separate tool for browser end-to-end tests. This is out of scope of this article.</p> <h2>Setting up the Sample Project</h2> <p>Before looking at how tests are written, let's first look at the application we'll be testing. It can be downloaded <a href="https://github.com/echessa/react-testing-with-jest">here</a>. In the downloaded folder, you will find three projects - one named <code>starter</code> with no test files, another named <code>completed</code> with the test files included and another named <code>completed_with_auth0</code> which contains test files and also adds authentication to the application. In this article, we'll start with the <code>starter</code> project and proceed to add tests to it.</p> <p>The sample application is a simple countdown timer created in React. To run it, first navigate to the root of the starter project:</p> <pre><code class="sh">$ cd path/to/starter/CountdownTimer </code></pre> <p>Install the necessary libraries:</p> <pre><code class="sh">$ npm install </code></pre> <p>Run Webpack:</p> <pre><code class="sh">$ webpack </code></pre> <p>Then run the application with:</p> <pre><code class="sh">$ npm start </code></pre> <p>Navigate to <a href="http://localhost:3000/">http://localhost:3000/</a> in you browser. You should see the following.</p> <p><img src="https://raw.githubusercontent.com/echessa/various_learning/d71b81b76687e35f9757840bde3c84e9be64b6ba/misc/jest_images/image_01.png" alt="React Countdown Timer" /></p> <p>You can set a time in seconds and start the countdown by clicking on the <strong>Start Countdown</strong> button.</p> <p>The functionality of the countdown timer has been separated into three components stored in the <code>app/components</code> folder namely <code>Clock.jsx</code>, <code>Countdown.jsx</code> and <code>CountdownForm.jsx</code>.</p> <p>The Clock component is responsible for rendering the clock face and formatting the user's input to an <code>MM:SS</code> format. The CountdownForm component contains a form that takes the user input and passes it to the Countdown component which starts decrementing the value every second, passing the current value to the Clock component for display.</p> <p>Having looked at the sample application, we'll now proceed with writing tests for it.</p> <h2>Writing Tests</h2> <p>Let's start by installing and configuring Jest.</p> <p>Run the following command to install Jest and the <code>babel-jest</code> library which is a Jest plugin for Babel. The application uses Babel for transpiling JSX and ES6 so the plugin is needed for the tests to work.</p> <pre><code class="sh">$ npm install --save-dev jest babel-jest </code></pre> <p>With <code>babel-jest</code> added, Jest will be able to work with the Babel config file <code>.babelrc</code> to know which presets to run the code through. The sample application already has this file. You can see its contents below.</p> <pre><code class="json">{ "presets": ["es2015", "react"] } </code></pre> <p>The <code>react</code> preset is used to transform JSX into JavaScript and <code>es2015</code> is used to transform ES6 JavaScript to ES5.</p> <p>With that done, we are now ready to write our first test.</p> <p>Jest looks for tests to run using the following conventions:</p> <ul> <li>Files with .test.js suffix.</li> <li>Files with .spec.js suffix.</li> <li>Files with .js suffix inside a folder named <strong>tests</strong>.</li> </ul> <p>Other than <code>.js</code> files, it also automatically considers files and tests with the <code>jsx</code> extension.</p> <p>For our project, we'll store the test files inside a <strong>tests</strong> folder. In the <code>app</code> folder, create a folder named <code>__tests__</code>.</p> <p>For the first test, we'll write a simple test that en