Auth0 Email Verification in Go

Nicholas Martinez
5 min readAug 21, 2020

Hand rolling authentication these days is best left to, well, no one. This blog post is going to explore how to accomplish email verification using Auth0 without using a custom database connection.

If you are not familiar with Auth0, the service provides its users with the ability to use custom database connections that communicate directly with a database you control to authenticate, create, verify and change the password of the users of your application. The UI provides the administrator with scripts that can be created and modified for execution on a specific action. For example, an admin can write a script that inserts a new user and the new user’s credentials into their database when they sign up.

It could look something like this:

Similarly there is a custom database script that can be added when a user confirms his or her email address using Auth0’s email verification process:

All of this works marvelously when an admin has access to their database, can poke holes into a firewall from Auth0 or has control over the security groups at AWS. (One more downside to using custom scripts with Auth0 are the dozen or so IP addresses that need to be whitelisted in your security group or firewall to connect to the service properly.)

With that said, the email verification feature falls apart quickly if Auth0 is unable to write directly to your database. Auth0 offers a force email verification rule that is enabled through the dashboard but without the requisite connection to the database, managing the state of a user in your application requires API calls be made to confirm that the user has verified their account. Even the Auth0 documentation state:

Note: It might be a better UX to make this verification from your application.

Rather than writing a redundant feature within my application to verify the email addresses of my users I simply leverage Auth0’s email verification feature in conjunction with their machine-to-machine API to check if a user had verified their account. Note: The Auth0 machine-to-machine API differs from the application API. The application API provides permissions scoped for general application authentication, the machine-to-machine API is required to programmatically communicate with your Auth0 domain using “non-interactive services”.

I am going to be explicit on this point only because it confused me. I was attempting to make Management API calls using the credentials provided to me from the “Regular Web Application” API. The Auth0 application that is created and used to log users into your web app is not the same Auth0 application that is used to make Management API calls for doing things like permissions scoping or user searches.

After you have created the machine-to-machine application, click into the application’s dashboard — this is where we find our API Client ID and Client Secret. You will need these to authentication with the API and get the JWT.

The Code:

I have a route /dashboard in my Go Lang application that I would like to prevent user access to if they are both not authenticated and have not verified their email address:

The IsAuthenticated function comes from the Go Gorilla/Mux library and using negroni we can add any number of middleware components we would like between the user and fulfilling the request.

Lets take a look at theIsVerified function:

The first line of the function gets the email address of the currently logged in user from the MySqlStore. The second line of the function kicks off a series of function calls that will authenticate with the Auth0 machine-to-machine api, search for users in our Auth0 application by email address and return a boolean of their verification status. Note: The email verification setup process for Auth0 is beyond the scope of the article. It does, however, allow administrators to set up email templates that will be sent to users when they sign up, click on a link and confirm their email.

Fetching the user information required to confirm email verification is a three step process, first, we need to authenticate with our Auth0 domain to obtain our Java Web Token, then we will return a list of users with their email addresses (we might have the same user’s email address across multiple Auth0 application connection types within the same Auth0 domain) and finally we will check the email verification status of the user we select.

The tutorial is going to work logically through each function as presented above, however they will call each other in the reverse order as to not make one dependent on the other.

Fetching the JWT:

Here we make an API call to the /oauth/token route of our Auth0 API domain and unmarshal the response into our Jwt struct.

API call to fetch users:

The fetchAuthZeroUsers function calls getJWT() to collect the token that is needed to authenticate with the API and returns a list of users. Our URL carries the email we are searching for.

Example User list (API Response — single user):

Retrieve the current user from the list:

The getCurrentAuth0User function iterates over the list of users returned by fetchAuthZeroUsers and loops over the slice until it matches on a the value of the Connection key in the Identities slice. This match is done to ensure that the user we are returning is from the same Auth0 database our application is using.

Putting it all together we have the IsVerified function calling the getCurrentAuth0User function which then moves up the stack, getting our Java Web Token to authenticate the API call that queries for a collection of users filtered using an email address we know our current user is logged in with.

Back to the IsVerified function:

In this function we check the boolean value of the interface returned in the User struct for the property isVerified — if the email has not been verified, the code redirects the user to the home page with a flash message attached to the user session which informs the user that he or she must verify their email address before proceeding, otherwise, the user is inserted into our local database with insertUser() and then next() is called to move down through the stack to the dashBoardHandler and they are taken to the dashboard page.

I ended up building this after I began to have issues with the custom database connections I had created for my web app Webhookrelay.io. The truth is I wish I had done this first rather than building ultimately unnecessary connections to my database.

If you have any questions or comments please leave them below and don’t forget to follow my here on Medium for more tutorials. Additionally, please check out some of the other tutorials I have written for AWS:

Build an AWS MySQL RDS Database and connect to it from your network

Connecting an AWS VPC to your VPN — From the Cloud to the Colo

Medium, Lambda, and Me (or how I export Medium stories to my website)

--

--