Skip to main content

OIDC GoLang Example

This guide demonstrates how to integrate NetActuate OIDC authentication into a Go application using the standard golang.org/x/oauth2 and github.com/coreos/go-oidc packages.

Prerequisites

  • Go 1.21 or later
  • A NetActuate OIDC client ID and client secret (configured at Account → Settings → OIDC)

Project Setup

Initialize a new Go module and install dependencies:

mkdir netactuate-oidc-example && cd netactuate-oidc-example
go mod init netactuate-oidc-example
go get github.com/coreos/go-oidc/v3/oidc
go get golang.org/x/oauth2

Configuration

Create a config.go file with your OIDC settings:

package main

const (
issuerURL = "https://portal.netactuate.com"
clientID = "your-client-id"
clientSecret = "your-client-secret"
redirectURL = "http://localhost:8080/callback"
)

Note: Never commit client secrets to version control. Use environment variables or a secrets manager in production.


Full Implementation

Create a main.go file:

package main

import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"

"github.com/coreos/go-oidc/v3/oidc"
"golang.org/x/oauth2"
)

var (
oauth2Config *oauth2.Config
verifier *oidc.IDTokenVerifier
state = "random-state-string" // Use a secure random value in production
)

func main() {
ctx := context.Background()

// Initialize OIDC provider
provider, err := oidc.NewProvider(ctx, issuerURL)
if err != nil {
log.Fatalf("Failed to initialize OIDC provider: %v", err)
}

// Configure OAuth2
oauth2Config = &oauth2.Config{
ClientID: clientID,
ClientSecret: clientSecret,
RedirectURL: redirectURL,
Endpoint: provider.Endpoint(),
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
}

// Configure ID token verifier
verifier = provider.Verifier(&oidc.Config{ClientID: clientID})

// Set up HTTP handlers
http.HandleFunc("/", handleHome)
http.HandleFunc("/login", handleLogin)
http.HandleFunc("/callback", handleCallback)

fmt.Println("Server running at http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}

func handleHome(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `<html><body><a href="/login">Log in with NetActuate</a></body></html>`)
}

func handleLogin(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, oauth2Config.AuthCodeURL(state), http.StatusFound)
}

func handleCallback(w http.ResponseWriter, r *http.Request) {
// Verify state parameter
if r.URL.Query().Get("state") != state {
http.Error(w, "Invalid state parameter", http.StatusBadRequest)
return
}

// Exchange authorization code for tokens
ctx := r.Context()
token, err := oauth2Config.Exchange(ctx, r.URL.Query().Get("code"))
if err != nil {
http.Error(w, fmt.Sprintf("Token exchange failed: %v", err), http.StatusInternalServerError)
return
}

// Extract and verify ID token
rawIDToken, ok := token.Extra("id_token").(string)
if !ok {
http.Error(w, "No id_token in response", http.StatusInternalServerError)
return
}

idToken, err := verifier.Verify(ctx, rawIDToken)
if err != nil {
http.Error(w, fmt.Sprintf("ID token verification failed: %v", err), http.StatusInternalServerError)
return
}

// Extract claims
var claims struct {
Email string `json:"email"`
Name string `json:"name"`
Sub string `json:"sub"`
}
if err := idToken.Claims(&claims); err != nil {
http.Error(w, fmt.Sprintf("Failed to parse claims: %v", err), http.StatusInternalServerError)
return
}

// Display user info
response, _ := json.MarshalIndent(claims, "", " ")
w.Header().Set("Content-Type", "application/json")
w.Write(response)
}

Running the Application

go run .

Open your browser and navigate to http://localhost:8080. Click the login link to initiate the OIDC flow.


Token Refresh

To refresh an expired access token, use the TokenSource from the OAuth2 config:

tokenSource := oauth2Config.TokenSource(ctx, token)
newToken, err := tokenSource.Token()
if err != nil {
log.Fatalf("Failed to refresh token: %v", err)
}

The TokenSource automatically handles refresh when the access token expires.


Production Considerations

  • Store client secrets in environment variables or a secrets manager
  • Use a cryptographically random value for the state parameter
  • Implement proper session management
  • Enable HTTPS for the redirect URL
  • Add error handling and logging appropriate for your environment

Need Help?

If you run into issues, contact NetActuate Support.