Home About Projects Blog

Adding Google Oauth to Golang Applications (and some other nice authentication features)

Tue, Aug 30, 2022

So I’ve been working on a personal project lately and wanted to add some basic authentication to my app. The only problem was that I had no clue how to set up OAuth in a Golang project. So after some research, I finally came up with the solution (which I think is fairly elegant, but you can be the judge of that).

Step 1: Google Setup

For this walkthrough, we’ll be using Google as our OAuth provider. To begin, you need to set up a google project within the Google Cloud Console. Once you’ve done that, you can go to the APIs & Services OAuth Consent Screen page to set up an OAuth login screen for your application. It will ask you for things like your domain, support email, and even allow you to upload an app logo. For most people’s needs you’re going to want to select the “External User Type” which will allow you to register external users for your application. The “Internal User Type” allows you to make your application domain specific for only users within your organization (Google Workspace). Most of these settings can be changed later, so there’s no need to worry about giving it much thought up front.

After you’ve prepared your OAuth Consent Screen, you’ll want to create credentials for your application to access it. To do so, go to the API & Services Credentials page. Click on the “Create Credentials” at the top and select “OAuth client ID”.

Credentials Creation

From here, select the “Web Application” application type. Fill out the rest of the page with your desired settings and make sure to include a redirect URI for “http://localhost:8080/auth/google/callback” (if you’d like to follow along with the rest of this walkthrough). Now you should be ready! You’ll want to securely store your client id and client secret in either a secret manager or secure file system of some sort.

Step 2: Set up basic HTTP server

In Golang, I usually start by setting up a bare-bones HTTP server and then adding onto it. For the purposes of this walkthrough, I’m going to be using sirupsen/logrus for logging, jmoiron/sqlx for storing authenticated user’s data, gorilla/mux for http routing, and gorilla/sessions for session management. Here is the simple server that I usually start with:

Code block 1

For the purposes of this walkthrough, the PORT environment variable will be set to “8080”. It is also very important to note that whatever value you use for a SESSION_KEY should be on at least the level of a strong password. It is recommended to use the crypto/rand package to create a cryptographically secure and random value for your key. It is also strongly advised that you do not store this value in your code! Please use some kind of secret manager or secure file system to store this value.

Step 3: Setting up OAuth Routes

Now that you’ve got all of your setup done we’ll start by creating the “/login” route. This will redirect you to the Google OAuth consent screen that you created in step 1.

Code block 2

It’s important to note that as above with the session key for your session store, you should never hardcode your client id or client secret in code. As for the other variables in the OauthConfig object, this will set the redirect route back to your callback route and request the scope to get a user’s email address information.

The GoogleLogin function itself is fairly simple. It generates a random identifier for the request and sets a cookie up to store that for future usage. It then redirects the user to the google authentication page for your OAuth consent screen. One thing you may notice is that the function is wrapped and returns a closure for an http.HandlerFunc rather than just being an http.HandlerFunc itself. This is a method I frequently use to pass state into my http routes to avoid using global state or server objects to pass state. This makes it much easier to pass in database connections when they’re required, as you’ll see later. This isn’t required for this particular function, but I find it useful to have in the event that I want to extend the functionality at a later time.

Now that we have the login redirect set up, it’s time to create the callback route to capture the incoming requests that are validated by Google and sent back to us.

Code block 3

In short, this route will capture any incoming redirects from the Google OAuth consent screen that you set up for your project, validate the code received from it, and fetch the user’s information from the Google API. Once it has the user’s information, it saves that to the given database (in this example we’re using a SQL database) for future use. This is not required and can be swapped out for no storage or any other type of database supported in Golang. Once the user is authenticated and their data is stored in the database, we redirect them to the root route with a valid session cookie.

Step 4: Authentication Middleware

So now you have authentication in your application, congratulations! But what to do with it? The next step is to start gating your other routes with a middleware that checks for valid sessions. It should send a “401 Unauthorized” response when the session is invalid, but pass it on to the requested route if it is valid.

Code block 4

Step 5: Getting the current user’s information

Now that you can gate your routes, we can start adding some utility functionality. For starters, we can allow for users to request their own info. This will allow for client-side rendering of different pages depending on roles or permissions associated with a given account. This is only a simple example and does not include those things, but it is easy to imagine adding them. For this walkthrough, we’re simply going to return a representation of the existing session object for a given user.

Code block 5

Step 6: Logging out

Once you have everything above, you may want to allow for users to log out so that other people that share a machine with them don’t have access to their account. This is a very simple process with the current setup. You only need to delete the session cookies from their browser and they will be deauthenticated.

Code block 6

Step 7: Updating the server

Great! So now you have a login workflow, utility middleware, and a few routes for user needs. Now we just have to update the server to connect all of these workflows!

Code block 7

To start, we’ve added the creation of an authentication database that we can use within the callback route for storing user information. Next we added the “/current-user” route and gated it behind the authentication middleware. This will allow for authenticated users to fetch information about their current session. Then we added simple routes for “/login” and “/logout” so that the user can enter into and exit this workflow. Finally, we add in the google callback route and pass it the database connection so that it can store authenticated user’s information.

Final Thoughts

All-in-all, setting up Google OAuth isn’t very difficult if you know where to look for answers. Hopefully this walkthrough will help anyone that needs help on this topic. You can find the rest of the code here. It’s important to note that this is only a demonstration of authentication, not authorization which is a different concept. Maybe I’ll create a walkthrough for authorization in the future. Hope this helps!