Namecheap, Webflow, Auth0, Apollo, and the Whole 9 Yards
A very different post from the others. We’ve spent the past two weeks building our new MVP and I wanted to share the experience. I’ll be discussing various issues with Namecheap, Auth0, and GraphQL that you might run into when trying to incorporate everything together.
I’m not going to dive deep into the technical details of everything, so this post will be easiest to understand for those of you with a software background.
It’s a fairly long, see you at the end and happy hacking!
Early February we pivoted ideas to a B2B2C product. Doing so, we thought of a new name and purchased the domain through Namecheap. Of the various domain marketplaces, I find that Namecheap is the most user-friendly and has everything built in (certificates/ssl, domain configuration, hosting, etc). More importantly, they have an extensive library of documentation, how-to guides, and responsive customer support.
Connecting Heroku & Webflow to Namecheap
Within the first week, the first draft of the React application was complete and I was investigating the best deployment strategy. Initially, I was planning on using AWS, but both @kamath_harish and @lekhasurasani recommended using Heroku. Deploying through Heroku was so simple, I think I clicked 3 buttons. I linked our Github and could manually trigger deployments off the main
branch (one-day I’ll set up automatic deployments with CI/CD).
Once deployed, Heroku lets you can create a domain for the project. We needed to map the Heroku domain to the domain purchased from Namecheap. Under the Advanced DNS settings tab I created a CNAME record pointing to the Heroku domain (Namecheap’s guide).
For traditional use-cases you would use www instead of the wildcard character *. We use a wildcard approach due to the nature of our application. We wanted to create subdomains for each company we are working with and point the root domain (the www domain) to the Webflow landing page. Webflow provides very clear instructions when you are ready to host, so connecting the landing page to the root domain was super quick.
Enabling HTTPS
When have you been on the internet recently and seen a normal HTTP site? HTTPS is pretty much the norm nowadays, even incorporated into Google’s page rank algorithm.
In order to enable HTTPS, you need to upgrade to the Hobby plan for Heroku. Then purchase a SSL certificate from Namecheap (I recommend email verification because its the fastest). Next, upload it to Heroku. You can upload the certificate through the Heroku CLI, but I prefer the Web UI.
Given the nature of our use-case with wildcard domains, we needed to purchase a Wildcard SSL certificate from Namecheap. Uploading it to Heroku was painful because we kept running into an odd error (both through the CLI and UI): ... is currently in use by another app
. After a few hours, I resolved the error by contacting customer support, and from there was able to add the wildcard certificate and enable HTTPS.
Authentication with Auth0
Given we are working on a B2B product, SSO integration is vital for end user’s to login with their company email. I’ve used AWS authentication in the past, but @SohanChoudhury8 vehemently recommended against it. Looking at the different options, I decided to use Auth0 because there’s already documentation for integrating with our Hasura GraphQL database.
There are a couple of features of Auth0 that are vital for our use-case. First is Organizations. Essentially it’s a way to group users together, perfect way to organize users based on company. The second is Rules. It can be used to determines if authentication is allowed, add data to the authentication token, or complete any other type of function. At the end of the day, a rule is simply NodeJS code. You can define multiple rules, and all rules must pass for authentication to be granted. For our use-case we have 3 main rules: verifying the user is part of the company they are logging into, adding special information to the auth token required for database queries, and synchronizing user information.
For some reason, the generated token was invalid and I spent too many hours figuring out why. I’ll save you the trouble, there is a mistake in the documentation. When you create the Auth0 rule for adding Hasura JWT claims, change accessToken
to idToken
on line 3.
The other important aspect of Auth0 is setting up all of the Application URIs:
- Allowed Callback URLs: URLs that Auth0 will navigate to after authentication (eg. http://localhost:3000 )
- Allowed Logout URLs: URLs that Auth0 will navigate to after a user has logged out
- Allowed Web Origins: URLs that are allowed to direct to Auth0 for authentication
- Allowed Origins: URLs that can call the Auth0 API
Auth0 & React Integration
Now it’s time to actually integrate Auth0 into the React application.
The @auth0/auth0-react
library provides a higher-order-component (HOC), withAuthenticationRequired
, that can be used to protect any component (and therefore route). I wanted to wrap the <App />
component with the HOC, essentially protecting the entire application. However, once integrated, I realized a big problem. If an authentication error occurred (ie unauthorized access), then an infinite loop would trigger, where Auth0 would redirect to the error state. I found a Github issue where other people experienced the same problem. There’s a lot to breakdown with this issue.
As part of creating the Auth0 client object (in React) you have to pass in a onRedirectCallback
function. This defines where Auth0 should redirect after authentication. For us, this is the same URL the original authentication request is made from. For example, if the authentication request is made from www.xxxx.yyyy.com/, then after authentication, the user should be redirected to the same www.xxxx.yyyy.com/. However, on failure the URL changes to an Auth0 error URL, and onRedirectCallback
redirects to the Auth0 error URL, which attempts to re-authenticate and triggers an infinite loop.
I don’t entirely agree with the discussion points in the Github issue, because there is validity in protecting the entire <App />
component. In my opinion, there should be a better way to handle the error state. For this, I wrote my own HOC component based on existing withAuthenticationRequired
component.
Apollo Client with Auth0
If you look closely, you’ll see I return an AuthorizedApolloProvider
component. I’m not going to go over the details of setting up the normal ApolloProvider
in react, since there are enough resources on it. However, if you use Auth0 there’s one step that’s unclear: getting the idToken.
Both getIdTokenClaims
and isAuthenticated
come from the useAuth0
hook. setAccessToken
is simply a useState
variable. The actual token is the __raw
value.
Logout Issues
Cool, so everything should be working now right? Unfortunately, that’s not the case. If a user is able to login, they should be able to logout. And for some reason when I called the logout handler provided by Auth0, nothing would happen. Turns out you need to update the Allowed Logout URLs under Tenant Settings to actually work. I’m not sure why this particular setting is not under the Application settings like all of the other URIs that need to be configured.
Force HTTPS
After purchasing the SSL certificates and connecting them to Heroku, you’d think HTTPs would be enabled by default…well, not exactly. If you navigated to https://aaa.yyy.com, then yes HTTPS would be used. However, if you simply typed aaa.yyy.com, then normal HTTP is used.
It’s straightforward if you have a normal website, but with our wildcard approach, it’s not. Namecheap has documentation on forcing HTTPS for wildcard domains. So I purchased Namecheap Web Hosting and after spending a weekend with support I learnt its not scalable through Namecheap. Namecheap requires each wildcard subdomain (so aaa.yyy.com, bbb.yyy.com, ccc.yyy.com, etc) to be hardcoded in order to force HTTPS. We support many companies, so this isn’t a scalable solution for us. The alternative is forcing HTTPS on the Heroku side…which doesn’t mean anything. So the only resolution is doing it through the React application. Now, if you navigate to the HTTP domain, the application redirects you to the HTTPS domain. I built a HOC HTTPS redirect component based on mbasso’s repository.
Closing Thoughts
Looking back all of these solutions seem like simple fixes and for the most part I agree. However, the journey to come to the solutions was not smooth. I hope this post helps anyone who tries to setup something similar. And if you ever want to compare notes reach out!