Blog

How to build Log in with Google using Go and WorkOS

Step-by-step tutorial that walks you through the necessary steps to add Log in with Google to your app using Go and WorkOS.


Nowadays, it's quite rare to see a login form for a general consumer app that doesn’t offer at least one form of social login, whether from Google, Microsoft, or Facebook, among others. Customers expect it.

In this tutorial, we will go through all the steps required to add the Log in with Google functionality to your app using Go as the language and WorkOS as the authentication middleware.

While following this tutorial, please remember that some things might get outdated as products evolve. Dashboards change, and new SDK versions are released every week. If while you follow this tutorial, something is not working for you, please refer to these docs for the most up-to-date guidance:

Prerequisites

To follow this tutorial, you will need the following:

Step 1: Install the SDK

Add the WorkOS Go SDK to your app:

	
go get -u github.com/workos/workos-go/...
	

Step 2: Set secrets

To make calls to WorkOS, you must authenticate using the WorkOS API key and client ID. Copy these values from the WorkOS dashboard.

Store the values as managed secrets and pass them to the SDK as environment variables.

Environment variables example:

  
WORKOS_API_KEY='sk_example_123456789'
WORKOS_CLIENT_ID='client_123456789'
  

For more info on how to handle secrets safely see Best practices for secrets management.

Step 3: Configure the Google connection

Get the Redirect URI

WorkOS provides the Redirect URI, a whitelisted callback URL. It indicates the location to return an authorized user after they have logged in with Google. You need to get this URL from the WorkOS dashboard and provide it to Google.

  1. Go to the WorkOS dashboard and select Authentication on the left hand navigation bar.
  2. Scroll down to the Google OAuth section and click Configure Google OAuth.
  3. Click Your app’s credentials and copy the Redirect URI. We will use it in the next step while configuring the Google app.

Note that WorkOS also offers demo credentials if you want to test Google OAuth without setting up a Google OAuth app. However, this is only for testing purposes  and should be replaced by your own before going live.

Please note that when you are using WorkOS default credentials, Google's authentication flow will display WorkOS’ name, logo, and other information to users. Once you register your own application and use its Google Client ID and Google Client Secret for the OAuth flow, you will have the opportunity to customize the app, including its name, logo, etc.

Configure the Google OAuth app

To configure the connection on Google's side, follow these steps:

  1. Log in: Log in to the Google Cloud Platform Console Dashboard. Select your application’s project from the project selection dropdown menu in the navigation bar.
  2. Select your application: Select “APIs & Services”, then “OAuth Consent Screen” in the left-hand navigation menu. Select “Edit App”. Add workos.com to your list of “Authorized domains”, and select “Save”.
  3. Enter Setup Instructions: Select “Credentials” in the left-hand menu. Then select “OAuth client ID” from the “Create Credentials” dropdown menu. Then, give your OAuth client ID a name, and add the Redirect URI provided by WorkOS to the list of “Authorized redirect URIs”. As a best practice, your OAuth client ID’s name should be different from your application’s name. It will not be shown to end users. Click “Create” and you’ll be presented with your application’s Client ID and Client Secret. Copy these values as you will use them in the next step.
  4. Publish your Google OAuth application: Back in the “OAuth consent screen”, be sure that your app is “In production”. If it is still in testing mode you’ll likely get an “Access Blocked” error when attempting to log into your app.

For more detailed steps and screenshots follow the Google OAuth integration guide.

Add client credentials to WorkOS

  1. Go back to the Authentication section in the WorkOS dashboard, and click on Configure Google OAuth under Google OAuth.
  2. Click Your app’s credentials and paste the client credentials from Google that you generated in the previous step.
  3. Finally, click Save.

Step 4: Configure a redirect URI

In this step we will configure your application’s redirect URI (which is different from the one we used before).

A redirect URI is the endpoint of your application where the users are redirected after they sign in. You need to add this URI in the Redirects section of the WorkOS dashboard.

While wildcards in your URIs can be used in the staging environment, they and query parameters cannot be used in production. When users sign out of their application, they will be redirected to your app’s homepage, which is configured in the same dashboard area.

Step 5: Set up the frontend

We are ready to start adding code. In this tutorial we will use React to create a simple page with login and logout links.

Create a new React app if you don’t have one already, and add the following code to your App.js:

	
export default function App() {
  return (
    <div className="App">
      <h1>Login with Google example</h1>
      <p>
        <a href="/login">Login with Google</a>
      </p>
      <p>
        <a href="/logout">Log out</a>
      </p>
    </div>
  );
}
	

Step 6: Set up the backend

Before setting up the backend, you have to choose whether you will use AuthKit, a customizable login box powered by WorkOS and Radix, or build you own login box. Depending on the choice you should use a different API:

This tutorial will cover both cases.

Backend with AuthKit

Initiate login

When the user clicks “Sign in”, we need to start the authentication process. To do that we need to first redirect the user to Google so they can authenticate. We will use the usermanagement.GetAuthorizationURL method to generate the authorization URL and then redirect the user there.

Add the following code to main.go:

  
package main

import (
    "context"
    "net/http"

    "github.com/workos/workos-go/v2/pkg/usermanagement"
)

func main() {
    // Load environment variables from `.env`
    apiKey := os.Getenv("WORKOS_API_KEY")
    clientID := os.Getenv("WORKOS_CLIENT_ID")

    usermanagement.SetAPIKey(conf.APIKey)

    // The provider to authenticate with
    provider := "GoogleOAuth"

    // The callback URI WorkOS should redirect to after the authentication
    redirectURI := "https://your-app.com/callback"
    
    // Get the authorization URL and redirect the user there
    http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
        authorizationUrl, err := usermanagement.GetAuthorizationURL(
            context.Background(),
            usermanagement.GetAuthorizationURLOpts{
                ClientID:     clientID,
                Provider:     provider,
                RedirectURI:  redirectURI,
                State:        "dj1kUXc0dzlXZ1hjUQ==",
            },
        )

        http.Redirect(w, r, authorizationUrl.String(), http.StatusSeeOther)
    })
}
  

After the user authenticates, WorkOS redirects them to the RedirectUri including in the query string the authorization code. The URL would look like this:

	
https://your-app.com/callback?code=g0FGFmNjVmOWIkTGf2PLk4FTYyFGU5
	

Your app needs to extract this code and exchange it for a token.

Handle the callback

After the user successfully authenticates, WorkOS will generate a string (the authorization code) and send it back to the app as part of the Redirect URI. The app needs to extract that code and make another call to WorkOS in order to complete the authentication process by exchanging the authorization code for a token and user profile information.

Add the following code to main.go:

  
package main

import (
    "net/http"
    "os"

    "github.com/workos/workos-go/v3/pkg/sso"
)

func main() {
    apiKey := os.Getenv("WORKOS_API_KEY")
    clientID := os.Getenv("WORKOS_CLIENT_ID")

    usermanagement.SetAPIKey(conf.APIKey)

    http.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
        opts := usermanagement.AuthenticateWithCodeOpts{
            ClientID: conf.ClientID,
            // The authorization code returned by AuthKit
            Code:     r.URL.Query().Get("code"),
        }

        profileAndToken, err := usermanagement.AuthenticateWithCode(r.Context(), opts)
        if err != nil {
            // Handle the error...
        }

        // Use the information in `profileAndToken.User` and `profileAndToken.AccessToken 
        // for further business logic.
        userProfile := profileAndToken.User
        accessToken := profileAndToken.AccessToken

        // Redirect the user to the homepage
        http.Redirect(w, r, "/", http.StatusSeeOther)
    })
}
  

The user has now successfully logged in with Google. This is what the response looks like:

	
{
  "user": {
    "object": "user",
    "id": "user_01E4ZCR3C56J083X43JQXF3JK5",
    "email": "maria.paktiti@google.com",
    "first_name": "Maria",
    "last_name": "Paktiti",
    "email_verified": true,
    "profile_picture_url": "https://workoscdn.com/images/v1/123abc",
    "created_at": "2021-06-25T19:07:33.155Z",
    "updated_at": "2021-06-25T19:07:33.155Z"
  },
  "organization_id": "org_01H945H0YD4F97JN9MATX7BYAG",
  "access_token": "eyJhb.nNzb19vaWRjX2tleV9.lc5Uk4yWVk5In0",
  "refresh_token": "yAjhKk123NLIjdrBdGZPf8pLIDvK"
}
	

The user object can be used for further business login like personalizing the UI for the user.

The response also includes an access token and a refresh token. These two tokens can be used to manage the user’s session without asking them to authenticate all the time. The access token is short-lived and allows an application to access resources on a user’s behalf, while the refresh token, which lives a bit longer, can be used to get a new access token when that expires.

Both tokens should be handled and stored securely since if an attacker manages to obtain a user's token, they can impersonate the user and gain unauthorized access to protected resources. WorkOS SDKs use sealed sessions (i.e., sessions encrypted with a strong password) to keep tokens safe. For more information, see Handle the user session.

Backend without AuthKit

Initiate login

When the user clicks “Sign in”, we need to start the authentication process. We will use the sso.GetAuthorizationUrl method to generate the authorization URL where the user will be redirected to authenticate.

Add the following code to main.go:

  
package main

import (
    "net/http"
    "os"

    "github.com/workos/workos-go/v3/pkg/sso"
)

func main() {
    apiKey := os.Getenv("WORKOS_API_KEY")
    clientID := os.Getenv("WORKOS_CLIENT_ID")

    sso.Configure(apiKey, clientID)

    // The provider to authenticate with
    provider := "GoogleOAuth"

    // The callback URI WorkOS should redirect to after the authentication
    redirectURI := "https://your-app.com/callback"
    
    // Get the authorization URL and redirect the user there
    http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
        opts := sso.GetAuthorizationURLOpts{
            Provider:     provider,
            RedirectURI:  redirectURI,
        }

        authorizationUrl, err := sso.GetAuthorizationURL(opts)
        if err != nil {
            // Handle the error...
        }

        http.Redirect(w, r, authorizationUrl.String(), http.StatusSeeOther)
    })
}
  

After the user authenticates, WorkOS redirects them to the RedirectUri including in the query string the authorization code. The URL would look like this:

	
https://your-app.com/callback?code=g0FGFmNjVmOWIkTGf2PLk4FTYyFGU5
	

Your app needs to extract this code and exchange it for a token (in the next step).

Handle the callback

After the user successfully authenticates, WorkOS will generate a string (the authorization code) and send it back to the app as part of the Redirect URI. The app needs to extract that code and make another call to WorkOS in order to complete the authentication process by exchanging the authorization code for a token and user profile information.

Add the following code to main.go:

  
package main

import (
    "net/http"
    "os"

    "github.com/workos/workos-go/v3/pkg/sso"
)

func main() {
    apiKey := os.Getenv("WORKOS_API_KEY")
    clientID := os.Getenv("WORKOS_CLIENT_ID")

    sso.Configure(apiKey, clientID)

    http.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
        opts := sso.GetProfileAndTokenOpts{
            Code: r.URL.Query().Get("code"),
        }

        profileAndToken, err := sso.GetProfileAndToken(r.Context(), opts)
        if err != nil {
            // Handle the error...
        }

        // Use the information in `profile` for further business logic.
        profile := profileAndToken.Profile

        // Redirect the user to the homepage
        http.Redirect(w, r, "/", http.StatusSeeOther)
    })
}
  

The user has now successfully logged in with Google. This is what the response looks like:

	
{
  "access_token": "eyJhb.nNzb19vaWRjX2tleV9.lc5Uk4yWVk5In0",
  "profile": {
    "object": "profile",
    "id": "prof_01DMC79VCBZ0NY2099737PSVF1",
    "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY",
    "email": "maria.paktiti@google.com",
    "first_name": "Maria",
    "last_name": "Paktiti",
    "profile_picture_url": "https://workoscdn.com/images/v1/123abc",
    "created_at": "2021-06-25T19:07:33.155Z",
    "updated_at": "2021-06-25T19:07:33.155Z"
  }
}
	

The profile object can be used for further business login like personalizing the UI for the user.

Step 7 (optional): Add a custom Google OAuth domain

After implementing the steps above, you’ll notice that the Google OAuth sign in form displays “Choose an account to continue to workos.com”. This is based on the Authorized Redirect URI in Google. To set this to a domain other than workos.com, Google will ask for proof of ownership of your domain. To do this you need access to your Google Cloud Console and your domain’s DNS settings.

To help guide you through this process WorkOS offers a self-service flow. For step-by-step instructions on how to do this, see Customize Google OAuth domain.

Next steps

You have now successfully added Log in with Google functionality in your app. This is but the first step in your identity management journey. The next steps are handling the user’s session, implementing logout, adding SAML SSO, implementing access control, provisioning users automatically, handling failed authentication events, and more. Stay tuned for follow up tutorials on all of these areas.

In the meanwhile here are some resources you might find useful:

In this article

This site uses cookies to improve your experience. Please accept the use of cookies on this site. You can review our cookie policy here and our privacy policy here. If you choose to refuse, functionality of this site will be limited.