Go

Authenticate requests and manage Passage users with Go.

Prerequisites

A Passage App in the Passage Console.

Initialize

Run Passkey Complete Go from the command line.

go get github.com/passageidentity/passage-go

Authenticating a request

Passage makes it easy to associate an HTTP request with an authenticated user. The following code can be used to validate that a request was made by an authenticated user.

import (
	"net/http"
 
	"github.com/passageidentity/passage-go"
)
 
func exampleHandler(w http.ResponseWriter, r *http.Request) {
 
	// Authenticate this request using the Passage SDK:
	psg, _ := passage.New("<PASSAGE_APP_ID>", nil)
	_, err := psg.AuthenticateRequest(r)
	if err != nil {
		// 🚨 Authentication failed!
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
 
	// ✅ Authentication successful. Proceed...
 
}

By default, Passage looks for the user JWT from a cookie that is set by the Passage Element ( psg_auth_token ). If your application uses Authorization headers instead, you can pass the following option to the Passage Go SDK.

psg = Passage.new(PASSAGE_APP_ID,  &passage.Config{
    APIKey: PASSAGE_API_KEY,
    HeaderAuth: true,
})

Authorizing a user

It is important to remember that psg.AuthenticateRequest() validates that a request is properly authenticated and returns the authenticated user's Passage identifier, but an additional authorization check is typically required.

import (
	"net/http"
 
	"github.com/passageidentity/passage-go"
)
 
func exampleHandler(w http.ResponseWriter, r *http.Request) {
 
	// Authenticate this request using the Passage SDK:
	psg, _ := passage.New("<PASSAGE_APP_ID>", nil)
	passageID, err := psg.AuthenticateRequest(r)
	if err != nil {
		// 🚨 Authentication failed!
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
 
	// ✋ Authentication successful, but let's check authorization:
	allowed := myAuthorizationCheck(passageID, "role.manager")
	if !allowed {
		// 🚨 Authorization failed!
		w.WriteHeader(http.StatusForbidden)
		return
	}
 
	// ✅ Authentication & authorization successful. Proceed...
 
}

App information

The Passage SDK provides a way to retrieve information about an app.

import (
	"net/http"
 
	"github.com/passageidentity/passage-go"
)
 
func exampleHandler(w http.ResponseWriter, r *http.Request) {
 
  psg, _ := passage.New("<PASSAGE_APP_ID>", nil)
 
  passageAppInfo, err := psg.GetApp()
  if err != nil {
    // 💀 Couldn't get the Passage App
    w.WriteHeader(http.StatusInternalServerError)
    return
  }
}
 

User management

In addition to authenticating requests, the Passage SDK also provides a way to securely manage your users. These functions require authentication using a Passage API key. API keys can be managed in the Passage Console.

The functionality currently available on a user is:

  • Get a user's information (including any defined user metadata fields)
  • Activate or deactivate a user (a deactivated user will not be able to log in)
  • Update a user's information (email address or phone number)
  • Delete a user
  • Create a user

Passage API Keys are sensitive! You should store them securely along with your other application secrets.

User device management

The functionality currently available is:

  • List all devices for a user
  • Revoke a particular device from a user
import (
	"net/http"
 
	"github.com/passageidentity/passage-go"
)
 
func exampleHandler(w http.ResponseWriter, r *http.Request) {
 
  psg, _ := passage.New("<PASSAGE_APP_ID>", &passage.Config{
    APIKey: "<PASSAGE_API_KEY>",
  })
 
  // Get the Passage User ID from database
 
  // The passageUserID returned above can be used deactivate a user
  passageDevices, err := psg.ListUserDevices(passageUserID)
  if err != nil {
    // Couldn't list the user devices
    w.WriteHeader(http.StatusInternalServerError)
    return
  }
}
import (
	"net/http"
 
	"github.com/passageidentity/passage-go"
)
 
func exampleHandler(w http.ResponseWriter, r *http.Request) {
 
  psg, _ := passage.New("<PASSAGE_APP_ID>", &passage.Config{
    APIKey: "<PASSAGE_API_KEY>",
  })
 
  // Get the Passage User ID from database
 
  // The passageUserID returned above can be used deactivate a user
  success, err := psg.RevokeUserDevice(passageUserID, passageDeviceID)
  if err != nil {
    // Couldn't delete the device
    w.WriteHeader(http.StatusInternalServerError)
    return
  }
}

Creating Magic Links

The Go SDK can be used to generate custom Magic Links for users, that can be embedded into any content medium. To learn more, see our full guide on Embedded Magic Links.

import (
    "github.com/passageidentity/passage-go"
    "fmt"
)
 
func main() {
    psg, err := passage.New(PASSAGE_APP_ID, &passage.Config{
        APIKey: PASSAGE_API_KEY,
    })
 
    createMagicLinkBody := passage.CreateMagicLinkBody{
        Email: "anna@passage.id",
        RedirectURL: "/custom-path/1234",
    }
 
    magicLink, err := psg.CreateMagicLink(createMagicLinkBody)
    // use magicLink.URL
    fmt.Println(magicLink.URL)
}

Go reference

Go Reference (opens in a new tab)

For complete documentation on passage-go functions and types, check out the Go docs here (opens in a new tab).