frontegg

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2026 License: MIT Imports: 11 Imported by: 0

README

Frontegg

Frontegg Go SDK

Drop-in authentication, authorization, and entitlements for your Go backend.

Validate Frontegg JWTs, guard your routes, check feature entitlements, and call the Frontegg API — in a few lines of idiomatic Go.

Go Reference CI Go Report Card

Full guide · Quickstart · Guides · Frontegg docs · Report a bug


Why this SDK

Frontegg gives SaaS teams production-grade auth, user management, and entitlements out of the box. This SDK brings that to your Go services with first-class Go ergonomics:

  • 🔐 Auth in ~5 lines — guard any net/http route with WithAuthentication. Bearer JWTs and API keys, roles, permissions, and step-up MFA all handled.
  • 🎟️ Entitlements at the edge — evaluate feature flags and plan rules locally, in-memory, with zero per-check network calls. A faithful port of Frontegg's entitlements engine.
  • Built for production — goroutine-safe, context.Context-aware, automatic token refresh, pluggable in-memory or Redis caching.
  • 🧩 Idiomatic & unsurprising — errors as values (errors.Is/errors.As), functional options, standard-library HTTP. No magic, no globals you didn't ask for.
  • Battle-tested — ~89% test coverage, race-tested, CI on every push.

Idiomatic Go counterpart to the official @frontegg/client Node SDK, with feature parity.

Contents

Install

go get github.com/frontegg/go-sdk

Requires Go 1.24+.

Quickstart

Protect a route in one snippet — initialize once, then wrap any handler:

package main

import (
	"net/http"

	"github.com/frontegg/go-sdk"
	"github.com/frontegg/go-sdk/middleware"
)

func main() {
	// Initialize the package-level client once at startup.
	frontegg.Init(frontegg.Credentials{
		ClientID: "<YOUR_CLIENT_ID>",
		APIKey:   "<YOUR_API_KEY>",
	})

	// Guard a route: requires a valid token with the "admin" role.
	protected := frontegg.WithAuthentication(middleware.Options{
		Roles: []string{"admin"},
	})

	mux := http.NewServeMux()
	mux.Handle("/admin", protected(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		user, _ := middleware.UserFromContext(r.Context())
		// user.ID(), user.Email, user.TenantID, user.Roles, user.Permissions …
		_, _ = w.Write([]byte("hello " + user.Email))
	})))

	_ = http.ListenAndServe(":8080", mux)
}

The middleware reads the token from the Authorization: Bearer … header or the x-api-key header, validates the signature and claims, enforces any required roles/permissions, and puts the decoded user on the request context. Unauthorized requests get 401; insufficient role/permission gets 403.

Capabilities

Capability Package What it does
Auth middleware middleware net/http guard for Bearer JWT / API-key auth, roles & permissions
Identity identity Validate JWTs and access tokens, roles/permissions, step-up MFA
Entitlements entitlements Local feature-flag & plan evaluation with background snapshot refresh
Hosted login hostedlogin OAuth 2.1 authorize URL + PKCE code exchange
Audit logs audits Send and query Managed Audit Logs
Events events Trigger Frontegg events and read delivery status
REST client httpclient Authenticated client for the full Frontegg API
M2M auth authenticator Vendor token with automatic refresh
Caching cache, cache/redisstore In-memory (default) or Redis-backed token cache
Entry point frontegg One Client that builds all of the above

Design principles: errors are values (errors.Is/errors.As), every network call takes a context.Context, all clients are safe for concurrent use, and configuration is read from the standard FRONTEGG_* environment variables.

Guides

📖 Prefer a single end-to-end walkthrough? See the full integration guide.

Protect HTTP routes

WithAuthentication works with the standard library and any router built on it (chi, gorilla, http.ServeMux, …):

guard := frontegg.WithAuthentication(middleware.Options{
	Roles:       []string{"admin", "owner"}, // any one is sufficient
	Permissions: []string{"fe.secure.read"}, // any one is sufficient
})

mux.Handle("/reports", guard(reportsHandler))

Need a dedicated client instead of the package-level default? Build one and pass its identity validator:

c := frontegg.New(frontegg.Credentials{ClientID: id, APIKey: key})
guard := middleware.WithAuthentication(c.Identity(), middleware.Options{Roles: []string{"admin"}})

Validate a token manually

c := frontegg.New(frontegg.Credentials{ClientID: id, APIKey: key})
ident := c.Identity()

user, err := ident.ValidateToken(ctx, bearerToken, &identity.ValidateTokenOptions{
	Roles:                   []string{"admin"},
	Permissions:             []string{"fe.secure.read"},
	WithRolesAndPermissions: true,                              // hydrate roles/permissions
	StepUp:                  &identity.StepUpOptions{MaxAge: 3600}, // require step-up MFA
}, identity.JWTHeader)
if err != nil {
	// errors.Is(err, identity.ErrInsufficientRole), etc.
}

Entitlements

Evaluate feature and permission entitlements locally — no network round-trip per check. The client keeps an in-memory snapshot fresh in the background.

ent := c.Entitlements()
if err := ent.Start(ctx); err != nil {
	log.Fatal(err)
}
defer ent.Close()

if err := ent.Ready(ctx); err != nil { // wait for the first snapshot
	log.Fatal(err)
}

// Scope to a user/tenant straight from their token …
scoped, err := ent.ForFronteggToken(ctx, token)
// … or from an already-validated entity:
//   scoped := ent.ForUser(entity)

if res := scoped.IsEntitledToFeature(ctx, "advanced-analytics", nil); res.Result {
	// entitled
} else {
	log.Printf("not entitled: %s", res.Justification) // missing-feature | bundle-expired | …
}

// Permissions, or the unified entry point:
_ = scoped.IsEntitledToPermission(ctx, "fe.secure.read", nil)
_, _ = scoped.IsEntitledTo(ctx, "advanced-analytics", "", nil)

Hosted login (OAuth 2.1 + PKCE)

The hosted-login flow uses PKCE, as required by OAuth 2.1. RequestAuthorize returns a code_verifier you must persist (e.g. in the user's session, keyed by state) and pass back to CodeExchange.

hl := c.HostedLogin("https://app.acme.com/oauth/callback")

// 1. Build the redirect and stash the verifier.
authReq, err := hl.RequestAuthorize(ctx, "csrf-state-token")
//    → redirect the user to authReq.URL
//    → save authReq.CodeVerifier, keyed by authReq.State

// 2. On the callback (?code=…&state=…), exchange the code.
res, err := hl.CodeExchange(ctx, code, state, savedCodeVerifier)
//    res.User, res.AccessToken, res.RefreshToken

The redirect_uri must exactly match an allowed callback configured on your Frontegg application.

Call the Frontegg REST API

auth := c.NewAuthenticator()
if err := auth.Init(ctx, id, key); err != nil {
	log.Fatal(err)
}
api := c.HTTPClient(auth, httpclient.WithBaseURL("https://api.frontegg.com"))

resp, err := api.Post(ctx, "identity/resources/auth/v1/user",
	map[string]string{"email": "john@acme.com", "password": "…"},
	map[string]string{"frontegg-vendor-host": "acme.frontegg"}, // optional per-request headers
)
// resp.StatusCode, resp.JSON(&v)

The client injects the vendor x-access-token on every request and refreshes it automatically before expiry.

Audits & events

// Managed Audit Logs
audits := c.Audits()
_ = audits.Init(ctx, "<CLIENT_ID>", "<AUDITS_KEY>")
_ = audits.SendAudit(ctx, audits.SendAuditParams{
	TenantID: "my-tenant",
	Severity: audits.SeverityMedium,
	Fields:   map[string]any{"user": "info@frontegg.com", "action": "Login", "ip": "1.2.3.4"},
})
page, _ := audits.GetAudits(ctx, audits.GetAuditsParams{TenantID: "my-tenant", Offset: 0, Count: 50})

// Events
ev := c.Events(auth)
id, _ := ev.Send(ctx, "my-tenant", events.EventTrigger{
	EventKey: "user.invited",
	Data:     events.EventProperties{Title: "You're invited", Description: "Join the team"},
})
status, _ := ev.GetStatus(ctx, id)

Caching access tokens

The in-memory cache is the default. To share a cache across instances, use the Redis backend (only consumers who import it pull in go-redis):

import (
	"github.com/redis/go-redis/v9"
	"github.com/frontegg/go-sdk/cache/redisstore"
)

rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
store := redisstore.New[MyType](rdb) // satisfies cache.Cache[MyType]

Configuration

Credentials are passed explicitly, or fall back to the environment. Service URLs default to the public Frontegg gateway and can be overridden — handy for EU/regional or self-hosted deployments.

Variable Default Purpose
FRONTEGG_CLIENT_ID Vendor client ID (fallback when not passed in code)
FRONTEGG_API_KEY Vendor API key (fallback when not passed in code)
FRONTEGG_API_GATEWAY_URL https://api.frontegg.com Base URL for all services
FRONTEGG_AUTHENTICATOR_NUMBER_OF_TRIES 3 Auth retry attempts
FRONTEGG_IDENTITY_SERVICE_URL <base>/identity Override the identity service
FRONTEGG_ENTITLEMENTS_SERVICE_URL <base>/entitlements Override the entitlements service

Per-service overrides also exist for audits, events, metadata, vendors, and OAuth (FRONTEGG_*_SERVICE_URL). See config.

Error handling

Errors are typed and inspectable. Identity failures carry an HTTP status and match sentinels:

_, err := ident.ValidateToken(ctx, token, opts, identity.JWTHeader)
switch {
case errors.Is(err, identity.ErrInsufficientRole):       // 403
case errors.Is(err, identity.ErrInsufficientPermission): // 403
case errors.Is(err, identity.ErrFailedToAuthenticate):   // 401
}

var sce *identity.StatusCodeError
if errors.As(err, &sce) {
	http.Error(w, sce.Message, sce.StatusCode)
}

Testing

go test ./...            # unit tests (no network — fully stubbed with httptest)
go test -race ./...      # race detector
go test -tags e2e ./...  # end-to-end against a real tenant (see .env.e2e.example)

Contributing

Issues and pull requests are welcome. Before opening a PR:

gofmt -l .      # must be clean
go vet ./...    # must pass
go test ./...   # must pass

License

MIT © Frontegg

Documentation

Overview

Package frontegg is the entry point to the Frontegg Go SDK. It mirrors the Node SDK's @frontegg/client: a backend client for the Frontegg platform with authentication, JWT/access-token validation, entitlements, audits, events and hosted login.

The Client struct is the idiomatic entry point — construct it once with your vendor credentials and use its factory methods to build sub-clients. A package-level default (Init/DefaultIdentity/WithAuthentication) is also provided so the HTTP middleware can be used with zero wiring, mirroring the Node SDK's global FronteggContext convenience.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultIdentity

func DefaultIdentity() *identity.Client

DefaultIdentity returns the package-level identity client set by Init (nil if Init was not called).

func Init

func Init(creds Credentials, opts ...Option)

Init configures the package-level default identity client used by WithAuthentication, mirroring the Node SDK's FronteggContext.init.

func WithAuthentication

func WithAuthentication(opts middleware.Options) func(http.Handler) http.Handler

WithAuthentication returns net/http middleware using the package-level default identity client. Call Init first.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the SDK entry point. It holds shared configuration and builds sub-clients on demand.

func New

func New(creds Credentials, opts ...Option) *Client

New returns a Client for the given credentials.

func (*Client) Audits

func (c *Client) Audits() *audits.Client

Audits returns an audits client (call Init on it to authenticate).

func (*Client) Entitlements

func (c *Client) Entitlements(opts ...entitlements.Option) *entitlements.Client

Entitlements returns an entitlements client (call Start on it to begin loading).

func (*Client) Events

func (c *Client) Events(auth *authenticator.Authenticator) *events.Client

Events returns an events client backed by the given authenticator.

func (*Client) HTTPClient

func (c *Client) HTTPClient(auth *authenticator.Authenticator, opts ...httpclient.Option) *httpclient.Client

HTTPClient returns an authenticated REST client backed by the given authenticator.

func (*Client) HostedLogin

func (c *Client) HostedLogin(redirectURI string) *hostedlogin.Client

HostedLogin returns a hosted-login client for the given redirect URI.

func (*Client) Identity

func (c *Client) Identity() *identity.Client

Identity returns an IdentityClient.

func (*Client) NewAuthenticator

func (c *Client) NewAuthenticator() *authenticator.Authenticator

NewAuthenticator returns an initialised authenticator.

type Credentials

type Credentials = identity.Credentials

Credentials are the vendor client ID and API key.

type Option

type Option func(*Client)

Option configures a Client.

func WithConfig

func WithConfig(cfg config.Config) Option

WithConfig overrides the resolved service configuration.

func WithHTTPClient

func WithHTTPClient(h *http.Client) Option

WithHTTPClient sets the underlying *http.Client for all sub-clients.

func WithLogger

func WithLogger(l logger.Logger) Option

WithLogger sets the logger.

Directories

Path Synopsis
Package audits provides the Managed Audit Logs client, mirroring the Node SDK's AuditsClient.
Package audits provides the Managed Audit Logs client, mirroring the Node SDK's AuditsClient.
Package authenticator maintains a backend-to-backend (M2M) session with Frontegg, mirroring the Node SDK's FronteggAuthenticator.
Package authenticator maintains a backend-to-backend (M2M) session with Frontegg, mirroring the Node SDK's FronteggAuthenticator.
Package cache provides the access-token cache abstraction used by the SDK, mirroring the Node SDK's src/cache module.
Package cache provides the access-token cache abstraction used by the SDK, mirroring the Node SDK's src/cache module.
redisstore
Package redisstore is a Redis-backed cache.Cache implementation built on go-redis.
Package redisstore is a Redis-backed cache.Cache implementation built on go-redis.
Package config resolves Frontegg service URLs from the environment, mirroring the Node SDK's src/config module.
Package config resolves Frontegg service URLs from the environment, mirroring the Node SDK's src/config module.
Package entitlements provides the entitlements client and user-scoped entitlement checks, mirroring the Node SDK's EntitlementsClient.
Package entitlements provides the entitlements client and user-scoped entitlement checks, mirroring the Node SDK's EntitlementsClient.
apitypes
Package apitypes models the vendor-entitlements v1 snapshot DTO.
Package apitypes models the vendor-entitlements v1 snapshot DTO.
engine
Package engine is a Go port of @frontegg/entitlements-javascript-commons — the local feature-flag / plan rule-evaluation engine.
Package engine is a Go port of @frontegg/entitlements-javascript-commons — the local feature-flag / plan rule-evaluation engine.
storage
Package storage builds the in-memory read models the entitlements client queries, mirroring the Node SDK's SourcesMapper + InMemoryEntitlementsCache.
Package storage builds the in-memory read models the entitlements client queries, mirroring the Node SDK's SourcesMapper + InMemoryEntitlementsCache.
Package events provides the Events client, mirroring the Node SDK's EventsClient.
Package events provides the Events client, mirroring the Node SDK's EventsClient.
Package hostedlogin provides the Frontegg hosted-login client, mirroring the Node SDK's HostedLoginClient (OAuth authorize URL + code exchange).
Package hostedlogin provides the Frontegg hosted-login client, mirroring the Node SDK's HostedLoginClient (OAuth authorize URL + code exchange).
Package httpclient is an authenticated wrapper over net/http that injects the vendor access token on every request, mirroring the Node SDK's HttpClient.
Package httpclient is an authenticated wrapper over net/http that injects the vendor access token on every request, mirroring the Node SDK's HttpClient.
Package identity validates Frontegg JWTs and access tokens, mirroring the Node SDK's IdentityClient and its token resolvers.
Package identity validates Frontegg JWTs and access tokens, mirroring the Node SDK's IdentityClient and its token resolvers.
internal
logger
Package logger provides the SDK's pluggable logger, backed by log/slog.
Package logger provides the SDK's pluggable logger, backed by log/slog.
retry
Package retry implements retry-with-jitter, mirroring the Node SDK's src/utils retry helper.
Package retry implements retry-with-jitter, mirroring the Node SDK's src/utils retry helper.
Package middleware provides a net/http authentication guard, mirroring the Node SDK's Express withAuthentication middleware.
Package middleware provides a net/http authentication guard, mirroring the Node SDK's Express withAuthentication middleware.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL