Reference

Go Reference - Http "net/http"

Go Reference - OAuth2 for Go "golang.org/x/oauth2"

Go Reference - OAuth2 (Google APIs) "golang.org/x/oauth2/google"

Authorization Server Flow

Diagram of OAuth authorization flow

  1. A Go client will serve a redirect to a browser. This redirect will include a random state variable and a following redirect URL back to the Go client from the authorizing server.
  2. The user enters credentials into the browser (user agent).
  3. The user agent send credentials to the authorization server (u := config.AuthCodeURL(oauthState) prepares the URL, a call to http.Redirect() accepts u and the server redirects the browser).
  4. Authorization server returns an authorization code (r.FormValue("code")) via the redirection URL provided in step 1.
  5. The Go client will exchange the authorization code for an access token (the client will store the access token in a cookie).
  6. The Go client uses the access token to access scoped resource servers.

A Simple OAuth Implementation

Download the oauth2 library for import.

go get golang.org/x/oauth2

The app structure I followed is pretty simple:

1. In main.go use net/http to start a server

main.go

package main

import (
"fmt"
"log"
"net/http"

"foundry-automations/handlers"
)

func main() {
server := &http.Server{
    Addr:    fmt.Sprintf(":8000"),
    Handler: handlers.New(),
}

log.Printf("Starting HTTP Server. Listening at %q", server.Addr)
if err := server.ListenAndServe(); err != http.ErrServerClosed {
    log.Printf("%v", err)
  } else {
    log.Println("Server closed!")
  }
}

2. Create a module /handlers and add two .go files

  • base.go
  • <service>.go where <service> is a meaningful representation of the authorization server you are relying on (e.g., google apis)

3. Create a Handler

In base.go create func New() http.Handler {} and set up a mux with two handlers, "/auth/<service>/login" and "/auth/<service>/callback", then return mux. The helper functions passed as the second argument of mux.HandleFunc will live in your <service>.go implementation

base.go

package handlers

import (
{
    "net/http"
)

func New() http.Handler {
mux := http.NewServeMux()
// Root
mux.Handle("/", http.FileServer(http.Dir("templates/")))

// // OauthGoogle
// mux.HandleFunc("/auth/google/login", oauthGoogleLogin)
// mux.HandleFunc("/auth/google/callback", oauthGoogleCallback)
mux.HandleFunc("/auth/pco/login", pcoLogin)
mux.HandleFunc("/auth/pco/callback", pcoCallback)

return mux
  }
}

About michaellamb.dev

Michael Lamb is a software engineer working at C Spire. If you have a blog-specific inquiry please create a new issue on GitHub. Feel free to fork this blog and build your own!

Get to know who I am in my first post Hello, World!

© Copyright 2021-2024
Using OAuth2 in Go | Michael Lamb