<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Auth0 on Stuart Forrest</title><link>https://www.uglydirtylittlestrawberry.co.uk/tags/auth0/</link><description>Recent content in Auth0 on Stuart Forrest</description><generator>Hugo -- gohugo.io</generator><language>en-uk</language><lastBuildDate>Sun, 19 Sep 2021 15:10:12 +0000</lastBuildDate><atom:link href="https://www.uglydirtylittlestrawberry.co.uk/tags/auth0/" rel="self" type="application/rss+xml"/><item><title>Unit testing Auth0 custom database Action Scripts</title><link>https://www.uglydirtylittlestrawberry.co.uk/posts/unit-testing-auth0-database-action-scripts/</link><pubDate>Sun, 19 Sep 2021 15:10:12 +0000</pubDate><guid>https://www.uglydirtylittlestrawberry.co.uk/posts/unit-testing-auth0-database-action-scripts/</guid><description>&lt;p>I recently wrote about &lt;a href="https://www.uglydirtylittlestrawberry.co.uk/posts/pretty-urls-cloudfront-functions/">unit testing Cloudfront Functions&lt;/a> which presented some challenges. This post is about unit testing &lt;a href="https://auth0.com/">Auth0&lt;/a> Action Scripts when using a custom database, which also presented some similar challenges but had a different solution.&lt;/p>
&lt;h2 id="what--is-auth0">What is Auth0?&lt;/h2>
&lt;p>&lt;a href="https://auth0.com/">Auth0&lt;/a> is an Identity-as-a-service (IaaS) provider.&lt;/p>
&lt;h3 id="what-is-a-custom-database-and-when-would-i-use-one">What is a custom database and when would I use one?&lt;/h3>
&lt;p>When using Auth0 there is the facility to create one or more user databases that store users authenticating with a username/password combination (&lt;a href="https://auth0.com/docs/connections/database">link&lt;/a>). Should you need to, these stores can be connected to an external database that (presumably) you already control. A custom database is a database not controlled by Auth0, likely a SQL database but it doesn&amp;rsquo;t actually matter - it doesn&amp;rsquo;t really have to be a database at all, just return users.&lt;/p>
&lt;p>The most likely use for a custom database is probably going to be lazily migrating users from an old identity provider to Auth0. Lazy migration will allow users to be moved over to Auth0 at the point of login without needing to change their password (&lt;a href="https://auth0.com/docs/users/import-and-export-users/configure-automatic-migration-from-your-database">link&lt;/a>). Another use for a custom database is to not use Auth0 for storing users at all (&lt;a href="https://auth0.com/docs/connections/database/custom-db/overview-custom-db-connections">link&lt;/a>) but just to handle the authentication flows, I would expect this to be a less common usage but Auth0 facilitate it.&lt;/p>
&lt;h3 id="what-is-an-action-script-and-why-are-they-are-hard-to-unit-test">What is an Action Script and why are they are hard to unit test?&lt;/h3>
&lt;p>An Action Script is some custom code that is deployed into Auth0, it will be invoked under certain scenarios (eg. when a user logs in, &lt;a href="https://auth0.com/docs/connections/database/custom-db/templates">link&lt;/a>). There are various points at which Auth0 functionality can be extended/augmented in this way (&lt;a href="https://auth0.com/docs/rules">rules&lt;/a>, &lt;a href="https://auth0.com/docs/hooks">hooks&lt;/a>, &lt;a href="https://auth0.com/docs/actions">actions&lt;/a>) and they all behave in slightly different ways (it&amp;rsquo;s a little frustrating). This post focuses on Action Scripts in the context of using a custom database.&lt;/p>
&lt;p>The runtime in which these Action Scripts execute has some restrictions that your code must operate within (&lt;a href="https://auth0.com/docs/connections/database/custom-db/templates#limits">link&lt;/a>). The relevant (and undocumented) one for this post is that top-level &lt;code>exports&lt;/code> are not allowed. This makes structuring your code to facilitate unit testing a little tricky.&lt;/p>
&lt;p>Effectively, neither of the following approaches will work:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-js" data-lang="js">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">function&lt;/span> &lt;span style="color:#a6e22e">handler&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// do something here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">module&lt;/span>.&lt;span style="color:#a6e22e">exports&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">handler&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;p>The first approach using &lt;code>export&lt;/code> will cause a syntax error and trying to access &lt;code>module&lt;/code> will fail.&lt;/p>
&lt;h2 id="an-approach-to-unit-testing-them-auth0-custom-database-action-scripts">An approach to unit testing them Auth0 custom database Action Scripts&lt;/h2>
&lt;p>My approach to &lt;a href="https://www.uglydirtylittlestrawberry.co.uk/posts/pretty-urls-cloudfront-functions/">testing Cloudfront Functions&lt;/a> using the &lt;a href="https://github.com/jhnns/rewire">rewire module&lt;/a> is a possible solution to unit testing Auth0 custom database Action Scripts. It is not the one I used though, this is because if I can get away with not bringing in additional dependencies then that is desirable. Rewire is also a pretty invasive module that (I assume) fiddles with the inner workings of node&amp;rsquo;s module resolution process, which is a bit much if we don&amp;rsquo;t have to do it.&lt;/p>
&lt;p>Whilst top-level &lt;code>exports&lt;/code> are not permitted and &lt;code>module&lt;/code> is undefined when accessed at the top-level, &lt;code>module&lt;/code> is, surprisingly, available outside of the global scope. This is a perfect use case for an &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/IIFE">Immediately Invoked Function Expressions&lt;/a> (IIFE). An IIFE is essentially a function that is run immediately after it has been defined but bounded in &lt;code>()&lt;/code> that isolates its scope from the outer scope. This means it will be immediately invoked when the module is imported into the runtime which Auth0 has to do at some point to execute the code.&lt;/p>
&lt;p>Taking advantage of these Javascript capabilities my first pass at writing a unit-testable Action Script looked something like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-js" data-lang="js">&lt;span style="display:flex;">&lt;span>(() =&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">doStuff&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">function&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;handler ran&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">module&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">module&lt;/span>.&lt;span style="color:#a6e22e">exports&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">doStuff&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">doStuff&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>})()&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;p>The thinking was that because &lt;code>module&lt;/code> is not available in the global scope, it isn&amp;rsquo;t available in the runtime at all. To account for this the &lt;code>exports&lt;/code> are only set if &lt;code>module&lt;/code> is defined, this means that when my unit tests attempt to import this module &lt;code>doStuff&lt;/code> is importable. But when the module is executed in the Auth0 runtime trying to manipulate exports shouldn&amp;rsquo;t cause a runtime error and &lt;code>doStuff&lt;/code> is available as an (almost) top level function.&lt;/p>
&lt;p>This worked, &lt;code>handler ran&lt;/code> is logged to the terminal in Auth0 when I tested it. Job done? Yes, and no. I pushed it a bit further and removed the conditional testing of &lt;code>module&lt;/code> like so:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-js" data-lang="js">&lt;span style="display:flex;">&lt;span>(() =&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">doStuff&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">function&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;handler ran&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">module&lt;/span>.&lt;span style="color:#a6e22e">exports&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">doStuff&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">doStuff&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>})()&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;p>I was very surprised when this worked, there were no runtime errors when I tested it in Auth0 and &lt;code>handler ran&lt;/code> was logged to the terminal. I&amp;rsquo;m not really sure what is going on here, &lt;code>module&lt;/code> not being available in the runtime is inconvenient but consistent. Whereas, &lt;code>module&lt;/code> just not being available in the global scope is a little weird.&lt;/p>
&lt;p>Auth0 do have a keen interest in securing the runtime for these custom database Action Scripts which is awesome, for example they vet third party modules to include in the runtime (&lt;a href="https://auth0.com/docs/best-practices/custom-database-connections-scripts/environment#npm-modules">link&lt;/a>). Perhaps the behaviour witnessed is security related and they didn&amp;rsquo;t want exporting to be allowed (&lt;a href="https://www.uglydirtylittlestrawberry.co.uk/posts/pretty-urls-cloudfront-functions/">a la Cloudfront Functions&lt;/a>), perhaps &lt;code>module&lt;/code> being available in a nested scope is not intentional. It is though, and in this instance I took advantage of it.&lt;/p>
&lt;h2 id="summary">Summary&lt;/h2>
&lt;p>Auth0 custom database Action Scripts exhibit some slightly odd runtime behaviour but with a little experimentation and taking advantage of some not always very useful Javascript features like IIFEs unit testing them was doable. Structuring your code a certain way to facilitate unit testing, as was the case here, I don&amp;rsquo;t consider a bad thing. Code that is hard to test is usually too complex or unobservable, if unit testing code helps to reduce the complexity, break it up or make it more observable then I consider that a good thing.&lt;/p>
&lt;h3 id="get-in-contact">Get in contact&lt;/h3>
&lt;p>If you have comments, questions or better ways to do anything that I have discussed in this post then please get in contact via &lt;a href="https://linkedin.com/in/stuart-f-41a43b180">LinkedIn&lt;/a> or &lt;a href="mailto:stuart@uglydirtylittlestrawberry.co.uk">email&lt;/a>.&lt;/p></description></item></channel></rss>