Clerk Auth Redirect/Reload Loop

I am currently looking into alternative forms of user authorization and authentication. Among the solutions I am looking into is Clerk. It’s pretty sweet and has a lot of cool features baked in. (Although the MFA support is a premium add-on and they aren’t super upfront about that).

One of the issues I ran into while implementing Clerk was a redirect loop. I set my home page within the Clerk Dashboard and when I reloaded my app, boom REDIRECTION FOR DAYS. Clerk was continuing to reload the home page for all eternity.

So, I added an onbeforeunload event into the page with a debugger call inside of it. This paused the page in the inspector before it reloaded and allowed me to actually see what was going on.

It turns out that Clerk was outputting an error message into the console. This error message is pictured below:

Clerk Error Message in JS Console

The <SignUp/> and <SignIn/> components cannot render when a user is already signed in, unless the application allows multiple sessions. Since a user is signed in and this application only allows a single session, Clerk is redirecting to the Home URL instead. (This notice only appears in development)

? Clerk

Well – ok then. Clerk is redirecting to the Home URL (which is the one it’s already on) and causing a permanent redirect loop. It seems like this would be handled better by simply _not_ loading the SignIn or SignUp components should the conditions for their existence fail.

Hopefully this helps you out! You might consider making your home page and your sign in pages different pages, or conditionally load those components, so that Clerk can be happy and not mess things up.

PHP: What is the difference between .env files and .ini files?

That’s a good question. You might ask this when you are implementing a new project and trying to figure out where to store your secret configuration values.

Before getting into the difference, let’s state the similarities:

  1. Both allow storage of environment specific configuration values and secrets from outside of your codebase.
  2. Both allow retrieval of environment specific configuration values and secrets from outside your codebase.
  3. Both files use a key value pair type format.
  4. Both allow comments within the files.

So what about the differences?

  1. The names are different .ini vs .env
  2. The method of storing the data is different.
  3. The method of retrieving the data is different.
  4. The syntax is different.

That probably doesn’t answer your question though. You likely aren’t interested as much in what the differences are as you are in why you would use one over the other.

Why use .env instead of .ini or .ini instead of .env?

This is likely what you are wanting to know, why would you use one over the other. So let’s list some pro’s and cons of each format to help make the decision.

.env Pros

  • language-agnostic
  • allows referencing other .env values as variables
  • libraries like phpdotenv provide robust functionality

Let’s expand a little on the language-agnostic pro above.

First Scenario. You are coming to PHP from another environment, like Ruby, you are probably wondering where to put your secrets and configuration values for your code. A .env file just makes sense, these are supported in Ruby so there must be a way to add them in PHP. Voila! There is a package that supports .env files that you can easily include in your PHP code and you don’t have to think anymore about it. It probably doesn’t even occur to you to use the build in .ini support.

Second Scenario. You are using both server side JS, like Node, and PHP. You want to share configuration values between the two systems. Both support .env files allowing you to easily share your secrets between both languages.

.ini Pros

  • built-in PHP Support
  • allows grouping of values via sections
  • supports typed values via INI_SCANNER_TYPED
  • allows interpolating other config values and environment variables

.env Cons

  • requires third party library and composer to work
  • features provided change based on library used for loading
  • *some libraries load configuration secrets into globally accessible variables like $_SERVER or $_ENV which will could expose your secrets to code you don’t intend to

.ini Cons

  • requires familiarity with PHP

Which one should I use?

I’m going to give you the answer you don’t want to hear. That’s up to you. It really depends on the needs of your environment and your program.

As far as my personal preferences go. I don’t like including unnecessary dependencies in my codebase. Therefore, if I’m using PHP to develop my app, and I have no need to share my config secrets with other languages, then I would use an .ini file and the built in support for those that PHP provides.

Converting a JavaScript Map to JSON

Ok, let’s cut to the chase. Everyone knows that converting a JavaScript Map to JSON does not work out of the box. By default, the JSON.stringify method will return a {} when converting a Map. It’s super helpful, because it returns an empty object, which is usually precisely what we don’t want. That’s a wee bit frustrating!

How Not to Serialize a Map to JSON

The internet has provided us with the silver bullet, though, right? Object.entries is great and can do all things, right? WRONG. That is wrong and you are wrong if you think that it’s right. You see what I’m getting at?

The existing advice is to use Object.fromEntries and Object.entries in tandem to make it easy to convert a map to and from JSON. The code below shows you this method in all it’s glory.

// ### inspired code below
const mapToSerialize = new Map([[1, 'first key']])
const serializedMap = JSON.stringify(Object.fromEntries(mapToSerialize ))

// now deserialize
const deserializedMap = new Map(Object.entries(JSON.parse(serializedMap)))

Isn’t the code above beautiful? Doesn’t it just wonderfully handle our serialization in the best of ways? No! It doesn’t. Let’s compare the original map to the deserialized map and see how amazing the code works.

The original map looks like this when logged to the console Map(1) {1 => 'first key'}. The deserialized map looks like this when logged to the console: Map(1) {'1' => 'first key'}. Did you spot the difference?

Just to make things clear, let’s try to delete the keyed value out of our Map.

Hey look, deleting that value totally didn’t work

So really, in the end, our serialization using the currently advised method totally works. We serialize our map, deserialize it, and then can’t use it properly. Just as we expected.

NO. It doesn’t work correctly. The difference is that the original map uses an integer key, and the deserialized map uses a string key. When we attempt to delete the value out of the deserialized map, using the key, it fails because the type doesn’t match.

How to Serialize a Map to JSON

I am proposing a different way to serialize a map to JSON.

  1. Create a new array from the existing map
  2. Serialize the array to JSON
  3. Create a new map from the deserialized JSON

The code I propose looks like this. You might not want to keep the logging at the end in your own implementations.

/// ### ugly code below
const mapToSerialize = new Map([[1, 'first key']])

// convert the map to JSON
const arrayToSerialize = []
mapToSerialize.forEach((value, key) => arrayToSerialize.push([key, value]))
const serializedMap = JSON.stringify(arrayToSerialize)

// convert the JSON back to a map
const deserializedMap = new Map(JSON.parse(serializedMap))

// log to console for inspection
console.log(mapToSerialize)
console.log(deserializedMap)

This code correctly works to serialize and deserialize a map to/from JSON.

Look at that, both maps match

In Conclusion

Serializing a Map to and from JSON isn’t as simple as it looks on the outside. Especially if from the outside it looks like it would be super simple. The Object.entries silver bullet only works for Maps with string keys, and attempting to use it for Maps with integer keys will end up with you hating your life. You probably will start listening to Barry Manilow constantly. You might even start eating Quinoa. I’m sure it happens all of the time due to Map serialization woes.

Anyways, if you prefer to not eat Quinoa, then go ahead and convert your Maps to and from JSON the way I suggested above.

That’s all I have to say about that.

POST Body not Included with JavaScript Fetch

I just ran into a problem and I wanted to document it for myself and for anyone else who might have issues. First I describe the problem, then I give the solution. Scroll down if you’re looking for the solution.

The Problem

After posting with JavaScript fetch I did not see the “body” arguments come through on the server. The method of the fetch was set to POST and the body included was an instance of FormData. According to the documentation on MDN, everything should’ve worked. So why wasn’t it working?

The Basic Client Side Code

const body = new FormData(myForm)
// assume myForm.action = "https://example.com/ajax/post"
const response = await fetch(myForm.action, {
	method: "post",
	body,
})

The Basic Server Side Code

<?php
// file: index.php within the ajax/post directory

// don't bother processing the post if there is none
if(empty($_POST)){
	exit;
}

// ... processing code below

I spent some time debugging and without a doubt, every POST request to the index.php file did not have the $_POST array filled out. The POST array was empty as well as the REQUEST array, even the oft-touted file_get_contents('php://input') came up empty.

The Solution

You aren’t going to like it. I don’t like it. The solution to this problem is so annoying that you’ll just facepalm like Picard.

Add a slash to the end of the url you are posting to.

The problem url is: https://example.com/ajax/post
The working url is: https://example.com/ajax/post/

Currently, when this url is posted to, the server responds with a 301 Redirect before the index.php file is hit. But why? The problem is that you do not have a trailing slash in your url. That’s it. You are posting to an index.php file within a directory, but your url does not have a trailing slash. So your server helpfully redirects you to a url with a trailing slash, and you lose your posted information along the way.

Yep, that’s it. Add a trailing slash and you’ll see your body come through when debugging.

Fixing UI-SREF-ACTIVE – Specifying a Default Abstract State

I’ve recently begun working with Angular and by extension Angular UI-Router. The fact that you are reading this means that you likely have as well. That said, let’s all pause for a moment and cry together. I know it’s hard. You will get through it. It will be ok. We can do this.

Basic ui-sref-active Usage

One of the things that UI-Router gives you is the ability to add a class to an element if that elements state is currently active. This is done via the ui-sref-active directive.


<ul class="nav navbar-nav" ng-controller="navController">
   
   <li class="nav-node nav" ui-sref-active="active"><a ui-sref="home">Home</a></li>

   <li class="nav-node nav" ui-sref-active="active"><a ui-sref="notHome">Not Home</a></li>

</ul>

So above we have some basic navigation with two states. The home state and the notHome state. The ui-sref-active directive takes care of adding the active class to whichever li contains the state that is currently active.

The Problem with Abstract States

The problem is that the ui-sref-active directive does not work correctly (or as we expect) when the parent state is an abstract state.

Let’s say you want to expand your “home” state a bit. Maybe you want to add a “dashboard” state and from there link to a “messages” state. You might set up your $stateProvider a bit like this.

$stateProvider
	.state("home",
	{
		abstract: true,
		url: "/home"
	})
	.state("home.dashboard", {
		url: "/dashboard",
		views: {
			"content@": {
				templateUrl: "app/home/dashboard.html",
				controller: "DashboardController"
			}
		}
	})
   .state("home.messages", {
		url: "/messages",
		views: {
			"content@": {
				templateUrl: "app/home/messages.html",
				controller: "MessagesController"
			}
		}
	});

You’ll see we’ve setup home as an abstract view. By default we want to land on our home.dashboard state. We also want ui-sref-active to set the active class on our “Home” link regardless of which child state we are on.


<ul class="nav navbar-nav" ng-controller="navController">
   
   <li class="nav-node nav" ui-sref-active="active"><a ui-sref="home.dashboard">Home</a></li>


   <li class="nav-node nav" ui-sref-active="active"><a ui-sref="notHome">Not Home</a></li>

</ul>

You will notice that in the code above we are now using ui-sref to link to  home.dashboard. This is where the problem with ui-sref-active crops up, it will only show the active class if the state is home.dashboard. We want the active class to appear on any child of the “home” state. As it is, the ui-sref-active directive will not detect home.messages as active. So the question becomes, “how can we fix ui-sref-active so that it detects a parent abstract state”?

Fixing ui-sref-active

The answer comes from Tom Grant in the form of a comment on a GitHub issue.

Tom informs us that there is an undocumented built in solution to this ui-sref-active problem. The solution, he says, is to “use an object (like with ng-class) and it will work”.

Code examples that Tom provides:

<!-- This will not work -->
<li ui-sref-active="active">
   <a ui-sref="admin.users">Administration Panel</a>
</li>

<!-- This will work -->
<li ui-sref-active="{ 'active': 'admin' }">
   <a ui-sref="admin.users">Administration Panel</a>
</li>

That’s it. Now we can link to children of abstract ui-router states and ui-sref-active will behave the way we expect it should.

JavaScript Scoping. Callbacks and Loops

I just ran into this issue last night. The problem: I had a loop that was adding a callback to a method. Something like this:

for(var i=0;i<10;i++){
    $myElement.on('some-event', function(){
        DoSomethingWith(i);
    });
}

What I expected was that the value of the i variable at the time it was called would be used in my callback method. However, this was not the case… the i variable was the same in every single callback.

See this JSFiddle for an example.

The reason for this? JavaScript variable hoisting.  Before your code is executed it is scanned and the variables are processed. This has the effect of moving your variables to the top of the current function regardless of where in the function they are defined. (Except for in cases where you are implicitly declaring global variables).

So, in our situation we’ve defined var i. This is processed before the loop is processed and it is as if we wrote this:

var i;
for(i=0;i<10;i++){
    $myElement.on('some-event', function(){
        DoSomethingWith(i);
    });
}

Now it becomes a bit more clear why we are running into the issue with i being the same. The reason is because by the time the callback is executed the for loop has already run and the value of the i variable is already 10.

The solution, as far as I can tell, is to use an IIFE to scope the variable correctly in order store the current value for later. It looks ugly and it feels hacky… but it seems to be what is necessary. Update: It appears that you can also use .bind to set the value correctly as well.

var i;
for(i=0;i<10;i++){
    $myElement.on('some-event', 
        (function(i){
            return function(){
                DoSomethingWith(i);
            };
        })(i);
    );
}

And the JSFiddle to demonstrate.

Example With .bind

var i;
for(i=0;i<10;i++){
    $myElement.on('some-event', DoSomethingWith.bind(undefined, i));
}

Deserializing JSON to a .NET Object

Generally in .NET MVC you would use the default model binders to deserialize JSON to a .NET object. However, there are some cases, involving “complex” collections, where this becomes a bit tedious to do. Microsoft provides a few ways around this, but none are satisfactory. Unlike the default model binders, the JavaScriptSerializer provides support for deserializing JSON to a .NET object with complex collections.

Take the following simple class and method signature for example:

// simple class
public class SaveInformation
{
    public string Name { get; set; }
    public Dictionary<string, List<SaveItem>> Components { get; set; }
}

// method signature
public ActionResult Save(SaveInformation saveInformation)

Below I’ve included some simple JSON that we will pass to .NET via AJAX:

{"SaveToSession":false,"Name":"My Stupendous Thing","Components":{"Component1":[{"ProductId":"1234"}]}}

We are passing the JSON to .NET using AJAX with the “application/json” contentType. Because we are using the “application/json” contentType, .NET will automatically call the JsonValueProviderFactory and map the information over to our SaveInformation model. It seems pretty straight forward, the Save method will receive a SaveInformation object when it is called.

Not so straightforward unfortunately, the Save method does receive a SaveInformation object. If we inspect our SaveInformation object we see the Name is populated perfectly fine, but the Components dictionary ends up being null.

The reason for this? It seems that the JsonValueProviderFactory doesn’t fully support pure JSON syntax. In order for .NET to properly parse a complex collection, you actually have to give it a numerical index.

From http://msdn.microsoft.com/en-us/magazine/hh781022.aspx:

Though it’s somewhat counterintuitive, JSON requests have the same requirements—they, too, must adhere to the form post naming syntax. Take, for example, the JSON payload for the previous UnitPrice collection. The pure JSON array syntax for this data would be represented as:

[
    { "Code": "USD", "Amount": 100.00 },
    { "Code": "EUR", "Amount": 73.64 }
]

However, the default value providers and model binders require the data to be represented as a JSON form post:

{
    "UnitPrice[0].Code": "USD",
    "UnitPrice[0].Amount": 100.00,

    "UnitPrice[1].Code": "EUR",
    "UnitPrice[1].Amount": 73.64
}

I know right? It was hard for me to read this as well due to the anime-sized tears in my normal-sized eyes. The problem is, no browser I know of has a JSON.serializeForDotNet function. So this leaves us with two options, make our own JSON serializer, or make our own ValueProvider/ModelBinder. Neither of these options sounded very appealing to me, so I went with the hidden third option. Pass in a string 🙂

You can use the JavaScriptSerializer class, located in System.Web.Script.Serialization, to deserialize JSON information and, as an added bonus, it actually handles properly formatted pure JSON!

So, the new method looks like this. We pass in a string value and deserialize it using the JavaScriptSerializer. Now we receive a SaveInformation object with a fully populated Components dictionary.

public ActionResult Save(string saveInformation)
{
    // instantiate a JavaScriptSerializer
    JavaScriptSerializer serializer = new JavaScriptSerializer();

    // use the JavaScriptSerializer to deserialize our json into the expected object
    SaveInformation saveInformationObject = serializer.Deserialize<SaveInformation>(saveInformation);

Use a JSON Parser to Visualize a JSON String

Just noting this here for future reference.

Whenever I am working with JSON I find it useful to be able to parse it. Now I can certainly parse it with Chrome’s inspector and see it in the console… but it’s nice to have an easy online tool to use as well.

The tool I use, and the tool that has helped me find several issues in the past, is JSON Parser Online. It’s really nice to be able to see the JSON string on the left and the parsed object on the right.