### Generate Zitadel Webhook Signature Header Source: https://context7.com/zitadel/zitadel-go/llms.txt Create the `ZITADEL-Signature` header value for services emitting Zitadel-style webhooks using `actions.ComputeSignatureHeader`. The format is `t=,v1=`. Includes a round-trip validation example. ```go package main import ( "fmt" "time" "github.com/zitadel/zitadel-go/v3/pkg/actions" ) func main() { payload := []byte(`{"event":"user.created","userID":"987654321"}`) signingKey := "my-shared-signing-secret" header := actions.ComputeSignatureHeader(time.Now(), payload, signingKey) fmt.Println("ZITADEL-Signature:", header) // Output: ZITADEL-Signature: t=1700000000,v1=a3f9... // Validate immediately (round-trip test) if err := actions.ValidatePayload(payload, header, signingKey); err != nil { panic(err) } fmt.Println("signature valid") } ``` -------------------------------- ### client.New — Create a Zitadel API Client Source: https://context7.com/zitadel/zitadel-go/llms.txt Demonstrates how to create a new gRPC-backed Client connected to a Zitadel instance. It shows how to use `client.WithAuth` to configure service-user authentication, specifically with a JWT Profile key file. ```APIDOC ## client.New — Create a Zitadel API Client Creates a new gRPC-backed `Client` connected to the given Zitadel instance. Accepts one or more `Option` values, most importantly `client.WithAuth(...)` to configure the service-user authentication method. Returns a `*Client` exposing lazy-initialized service accessors. ### Request Example ```go package main import ( "context" "log/slog" "os" "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/management" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() // Connect using a JWT Profile key file (recommended for production) api, err := client.New( ctx, zitadel.New("https://example.us1.zitadel.cloud"), client.WithAuth( client.DefaultServiceUserAuthentication( "path/to/key.json", oidc.ScopeOpenID, client.ScopeZitadelAPI(), ), ), ) if err != nil { slog.Error("could not create client", "error", err) os.Exit(1) } defer api.Close() resp, err := api.ManagementService().GetMyOrg(ctx, &management.GetMyOrgRequest{}) if err != nil { slog.Error("gRPC call failed", "error", err) os.Exit(1) } slog.Info("connected", "org", resp.GetOrg().GetName()) } ``` ``` -------------------------------- ### Initialize API Authorizer with `authorization.New` Source: https://context7.com/zitadel/zitadel-go/llms.txt Initializes an `*Authorizer` to validate Bearer tokens for API servers. Requires a `VerifierInitializer`, such as `oauth.DefaultAuthorization`, to specify the token verification strategy. ```go package main import ( "context" "log/slog" "os" "github.com/zitadel/zitadel-go/v3/pkg/authorization" "github.com/zitadel/zitadel-go/v3/pkg/authorization/oauth" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authZ, err := authorization.New( ctx, zitadel.New("https://example.us1.zitadel.cloud"), oauth.DefaultAuthorization("path/to/api-key.json"), ) if err != nil { slog.Error("authorizer init failed", "error", err) os.Exit(1) } // Verify a token directly authCtx, err := authZ.CheckAuthorization(ctx, "Bearer someaccesstoken", authorization.WithRole("admin"), ) if err != nil { slog.Error("unauthorized", "error", err) return } slog.Info("authorized", "userID", authCtx.UserID(), "org", authCtx.OrganizationID()) } ``` -------------------------------- ### Configure Zitadel Instance Target Source: https://context7.com/zitadel/zitadel-go/llms.txt Initialize a Zitadel descriptor for production HTTPS instances or local development. NewWithInsecure disables TLS verification for non-production environments. ```go import "github.com/zitadel/zitadel-go/v3/pkg/zitadel" // Production cloud instance z := zitadel.New("https://my-org.us1.zitadel.cloud") // Custom domain with TLS zCustom := zitadel.New("https://auth.mycompany.com") // Local development without TLS (e.g., docker compose on :8080) zLocal := zitadel.NewWithInsecure("localhost:8080") fmt.Println(z.Domain()) // "my-org.us1.zitadel.cloud" fmt.Println(z.Origin()) // "https://my-org.us1.zitadel.cloud" fmt.Println(z.Host()) // "my-org.us1.zitadel.cloud:443" ``` -------------------------------- ### Configure the Instance Target Source: https://context7.com/zitadel/zitadel-go/llms.txt `zitadel.New` creates a `*Zitadel` descriptor for a production HTTPS instance. `NewWithInsecure` targets a local or self-signed instance (e.g., in Docker Compose development environments) and disables TLS verification. ```APIDOC ## `zitadel.New` / `zitadel.NewWithInsecure` — Configure the Instance Target `zitadel.New` creates a `*Zitadel` descriptor for a production HTTPS instance. `NewWithInsecure` targets a local or self-signed instance (e.g., in Docker Compose development environments) and disables TLS verification. ```go import "github.com/zitadel/zitadel-go/v3/pkg/zitadel" // Production cloud instance z := zitadel.New("https://my-org.us1.zitadel.cloud") // Custom domain with TLS zCustom := zitadel.New("https://auth.mycompany.com") // Local development without TLS (e.g., docker compose on :8080) zLocal := zitadel.NewWithInsecure("localhost:8080") fmt.Println(z.Domain()) // "my-org.us1.zitadel.cloud" fmt.Println(z.Origin()) // "https://my-org.us1.zitadel.cloud" fmt.Println(z.Host()) // "my-org.us1.zitadel.cloud:443" ``` ``` -------------------------------- ### Add Zitadel Go SDK to go.mod Source: https://github.com/zitadel/zitadel-go/blob/main/README.md Use this command to add the Zitadel Go SDK package to your project's go.mod file. This ensures the SDK is available for use in your Go application. ```bash go get -u github.com/zitadel/zitadel-go/v3 ``` -------------------------------- ### OIDC PKCE Code Flow Helper with Go Source: https://context7.com/zitadel/zitadel-go/llms.txt Provides a HandlerInitializer preconfigured for OIDC Authorization Code + PKCE flow using DefaultContext. Accepts optional additional scopes; defaults to openid, profile, email. ```go import ( openid "github.com/zitadel/zitadel-go/v3/pkg/authentication/oidc" "github.com/zitadel/oidc/v3/pkg/oidc" ) // Minimal — default scopes handlerInit := openid.DefaultAuthentication( "client-id", "https://myapp.example.com/auth/callback", "32-byte-cookie-encryption-key!!", ) // With extra scopes handlerInitWithScopes := openid.DefaultAuthentication( "client-id", "https://myapp.example.com/auth/callback", "32-byte-cookie-encryption-key!!", oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail, "urn:zitadel:iam:user:resourceowner", ) ``` -------------------------------- ### Load Service Key from File or Data Source: https://context7.com/zitadel/zitadel-go/llms.txt Parses a Zitadel-issued JSON key file into a KeyFile struct. Use ConfigFromKeyFile for filesystem paths and ConfigFromKeyFileData for raw byte slices. ```go package main import ( "fmt" "log" "github.com/zitadel/zitadel-go/v3/pkg/client" ) func main() { // From disk kf, err := client.ConfigFromKeyFile("path/to/key.json") if err != nil { log.Fatal(err) } fmt.Printf("KeyID: %s UserID: %s ClientID: %s\n", kf.KeyID, kf.UserID, kf.ClientID) // From environment variable / secret bytes raw := []byte(`{"type":"serviceaccount","keyId":"kid1","key":"-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n","userId":"u1"}`) kf2, err := client.ConfigFromKeyFileData(raw) if err != nil { log.Fatal(err) } fmt.Printf("Type: %s\n", kf2.Type) } ``` -------------------------------- ### Initialize Web-App Authenticator with Go Source: https://context7.com/zitadel/zitadel-go/llms.txt Initializes an Authenticator for a Go web application, managing OIDC login, callback, and logout. Registers routes automatically when mounted. ```go package main import ( "context" "log/slog" "net/http" "os" "github.com/zitadel/zitadel-go/v3/pkg/authentication" openid "github.com/zitadel/zitadel-go/v3/pkg/authentication/oidc" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authN, err := authentication.New( ctx, zitadel.New("https://example.us1.zitadel.cloud"), "32-byte-encryption-key-here!!!!", // AES encryption key for session cookie openid.DefaultAuthentication( "my-oidc-client-id", "http://localhost:8089/auth/callback", "32-byte-encryption-key-here!!!!", // optional extra scopes; defaults to openid, profile, email ), authentication.WithCookieSession[*openid.DefaultContext](), // stateless cookie mode ) if err != nil { slog.Error("init failed", "error", err) os.Exit(1) } mw := authentication.Middleware(authN) mux := http.NewServeMux() // Mount the login / callback / logout handlers mux.Handle("/auth/", authN) // Protected route — redirects to login if unauthenticated mux.Handle("/profile", mw.RequireAuthentication()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authCtx := mw.Context(r.Context()) w.Write([]byte("Hello, " + authCtx.(*openid.DefaultContext).UserInfo.Name)) }))) // Public route — populates context if session exists, but does not redirect mux.Handle("/", mw.CheckAuthentication()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if authentication.IsAuthenticated(r.Context()) { http.Redirect(w, r, "/profile", http.StatusFound) return } w.Write([]byte(`Login`)) }))) slog.Info("listening on :8089") if err = http.ListenAndServe(":8089", mux); err != nil { slog.Error("server error", "error", err) os.Exit(1) } } ``` -------------------------------- ### HTTP Authorization Middleware with `middleware.New` Source: https://context7.com/zitadel/zitadel-go/llms.txt Wraps an `*Authorizer` into an HTTP middleware for REST APIs. `RequireAuthorization()` handles token extraction, introspection, and optionally enforces role requirements, responding with 401 or 403 on failure. ```go package main import ( "context" "log/slog" "net/http" "os" "github.com/zitadel/zitadel-go/v3/pkg/authorization" "github.com/zitadel/zitadel-go/v3/pkg/authorization/oauth" httpMiddleware "github.com/zitadel/zitadel-go/v3/pkg/http/middleware" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authZ, _ := authorization.New(ctx, zitadel.New("https://example.us1.zitadel.cloud"), oauth.DefaultAuthorization("api-key.json")) mw := httpMiddleware.New(authZ) router := http.NewServeMux() // Public endpoint — no auth required router.Handle("/api/healthz", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`"OK"`)) })) // Requires a valid token (any role) router.Handle("/api/tasks", mw.RequireAuthorization()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authCtx := mw.Context(r.Context()) slog.Info("access", "user", authCtx.UserID()) w.Write([]byte(`{"tasks":[]}`)) }))) // Requires a valid token AND the "admin" role router.Handle("/api/add-task", mw.RequireAuthorization(authorization.WithRole("admin"))(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { task := r.FormValue("task") slog.Info("admin added task", "user", authorization.UserID(r.Context()), "task", task) w.Write([]byte(""task added"")) }))) slog.Info("listening on :8089") if err := http.ListenAndServe(":8089", router); err != nil { slog.Error("server error", "error", err) os.Exit(1) } } ``` -------------------------------- ### JWT Profile Authentication from Key File Source: https://context7.com/zitadel/zitadel-go/llms.txt Configures JWT Profile authentication using a service account key file. This is the preferred method for production service users and requires specifying the path to the key file and desired OAuth2 scopes. ```go package main import ( "context" "log/slog" "os" "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/user/v2" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authOpt := client.DefaultServiceUserAuthentication( "./service-account-key.json", oidc.ScopeOpenID, client.ScopeZitadelAPI(), ) api, err := client.New(ctx, zitadel.New("https://example.us1.zitadel.cloud"), client.WithAuth(authOpt)) if err != nil { slog.Error("init failed", "error", err) os.Exit(1) } defer api.Close() resp, err := api.UserServiceV2().GetUserByID(ctx, &userv2.GetUserByIDRequest{UserId: "123456789"}) if err != nil { slog.Error("GetUserByID failed", "error", err) os.Exit(1) } slog.Info("user found", "login", resp.GetUser().GetHumanUser().GetProfile().GetDisplayName()) } ``` -------------------------------- ### Authenticate with Client Credentials Grant in Go Source: https://github.com/zitadel/zitadel-go/blob/main/README.md Suitable for simple server-to-server communication in trusted environments. Requires a client ID and client secret. ```go package main import ( "context" "log" "os" "log/slog" "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/management" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { domain := "https://example.us1.zitadel.cloud" clientID := "id" clientSecret := "secret" ctx := context.Background() authOption := client.PasswordAuthentication( clientID, clientSecret, oidc.ScopeOpenID, client.ScopeZitadelAPI(), ) api, err := client.New(ctx, zitadel.New(domain), client.WithAuth(authOption)) if err != nil { slog.Error("could not create api client", "error", err) os.Exit(1) } resp, err := api.ManagementService().GetMyOrg(ctx, &management.GetMyOrgRequest{}) if err != nil { slog.Error("gRPC call failed", "error", err) os.Exit(1) } log.Printf("Successfully called API: Your organization is %s", resp.GetOrg().GetName()) } ``` -------------------------------- ### Authenticate with Personal Access Token (PAT) in Go Source: https://github.com/zitadel/zitadel-go/blob/main/README.md An easy-to-use method for development or testing scenarios, allowing authentication without exchanging credentials each time. Requires a pre-generated PAT. ```go package main import ( "context" "log" "os" "log/slog" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/management" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { domain := "https://example.us1.zitadel.cloud" token := "token" ctx := context.Background() authOption := client.PAT(token) api, err := client.New(ctx, zitadel.New(domain), client.WithAuth(authOption)) if err != nil { slog.Error("could not create api client", "error", err) os.Exit(1) } resp, err := api.ManagementService().GetMyOrg(ctx, &management.GetMyOrgRequest{}) if err != nil { slog.Error("gRPC call failed", "error", err) os.Exit(1) } log.Printf("Successfully called API: Your organization is %s", resp.GetOrg().GetName()) } ``` -------------------------------- ### authentication.New Source: https://context7.com/zitadel/zitadel-go/llms.txt Initializes an Authenticator for managing the OIDC login, callback, and logout lifecycle in a Go web application. It automatically registers sub-routes for authentication when mounted. ```APIDOC ## `authentication.New` — Initialize Web-App Authenticator Creates an `*Authenticator` that manages the full OIDC login/callback/logout lifecycle for a Go web application. Registers `/auth/login`, `/auth/callback`, and `/auth/logout` sub-routes automatically when mounted with `ServeHTTP`. ``` -------------------------------- ### Load Service Key Source: https://context7.com/zitadel/zitadel-go/llms.txt Parses a Zitadel-issued JSON key file (service account or application key) into a *KeyFile struct. ConfigFromKeyFile reads from a filesystem path; ConfigFromKeyFileData accepts a raw []byte. ```APIDOC ## `client.ConfigFromKeyFile` / `client.ConfigFromKeyFileData` — Load Service Key Parses a Zitadel-issued JSON key file (service account or application key) into a `*KeyFile` struct. `ConfigFromKeyFile` reads from a filesystem path; `ConfigFromKeyFileData` accepts a raw `[]byte` (useful when loading from an environment variable or secret store). ```go package main import ( "fmt" "log" "github.com/zitadel/zitadel-go/v3/pkg/client" ) func main() { // From disk kf, err := client.ConfigFromKeyFile("path/to/key.json") if err != nil { log.Fatal(err) } fmt.Printf("KeyID: %s UserID: %s ClientID: %s\n", kf.KeyID, kf.UserID, kf.ClientID) // From environment variable / secret bytes raw := []byte(`{"type":"serviceaccount","keyId":"kid1","key":"-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n","userId":"u1"}`) kf2, err := client.ConfigFromKeyFileData(raw) if err != nil { log.Fatal(err) } fmt.Printf("Type: %s\n", kf2.Type) } ``` ``` -------------------------------- ### Create Zitadel API Client with JWT Profile Auth Source: https://context7.com/zitadel/zitadel-go/llms.txt Creates a new gRPC client for the Zitadel API using JWT Profile authentication. This method is recommended for production environments and requires a path to a service account key JSON file. ```go package main import ( "context" "log/slog" "os" "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/management" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() // Connect using a JWT Profile key file (recommended for production) api, err := client.New( ctx, zitadel.New("https://example.us1.zitadel.cloud"), client.WithAuth( client.DefaultServiceUserAuthentication( "path/to/key.json", oidc.ScopeOpenID, client.ScopeZitadelAPI(), ), ), ) if err != nil { slog.Error("could not create client", "error", err) os.Exit(1) } defer api.Close() resp, err := api.ManagementService().GetMyOrg(ctx, &management.GetMyOrgRequest{}) if err != nil { slog.Error("gRPC call failed", "error", err) os.Exit(1) } slog.Info("connected", "org", resp.GetOrg().GetName()) } ``` -------------------------------- ### Personal Access Token (PAT) Authentication Source: https://context7.com/zitadel/zitadel-go/llms.txt Ideal for development, testing, or CI scripts where dynamic token generation is not required. Uses a static PAT. ```go package main import ( "context" "log" "log/slog" "os" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/management" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() api, err := client.New( ctx, zitadel.New("https://example.us1.zitadel.cloud"), client.WithAuth(client.PAT("my-personal-access-token")), ) if err != nil { slog.Error("init failed", "error", err) os.Exit(1) } defer api.Close() resp, err := api.ManagementService().GetMyOrg(ctx, &management.GetMyOrgRequest{}) if err != nil { slog.Error("call failed", "error", err) os.Exit(1) } log.Printf("org: %s", resp.GetOrg().GetName()) } ``` -------------------------------- ### Authenticate with Private Key JWT in Go Source: https://github.com/zitadel/zitadel-go/blob/main/README.md Use this method for production environments requiring strong security and advanced control over token settings. Ensure your private key is stored in a JSON file. ```go package main import ( "context" "log" "os" "log/slog" "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/management" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { domain := "https://example.us1.zitadel.cloud" keyPath := "path/to/jwt-key.json" ctx := context.Background() authOption := client.DefaultServiceUserAuthentication( keyPath, oidc.ScopeOpenID, client.ScopeZitadelAPI(), ) api, err := client.New(ctx, zitadel.New(domain), client.WithAuth(authOption)) if err != nil { slog.Error("could not create api client", "error", err) os.Exit(1) } resp, err := api.ManagementService().GetMyOrg(ctx, &management.GetMyOrgRequest{}) if err != nil { slog.Error("gRPC call failed", "error", err) os.Exit(1) } log.Printf("Successfully called API: Your organization is %s", resp.GetOrg().GetName()) } ``` -------------------------------- ### authorization.New — Initialize API Authorizer Source: https://context7.com/zitadel/zitadel-go/llms.txt Creates an `*Authorizer` to validate incoming Bearer tokens for an API server. It uses a `VerifierInitializer`, such as `oauth.DefaultAuthorization`, for the verification strategy. ```APIDOC ## `authorization.New` — Initialize API Authorizer Creates an `*Authorizer` that validates incoming Bearer tokens on behalf of an API server. The concrete verification strategy is supplied via a `VerifierInitializer` such as `oauth.DefaultAuthorization` (JWT-Profile-authenticated introspection). ```go package main import ( "context" "log/slog" "os" "github.com/zitadel/zitadel-go/v3/pkg/authorization" "github.com/zitadel/zitadel-go/v3/pkg/authorization/oauth" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authZ, err := authorization.New( ctx, zitadel.New("https://example.us1.zitadel.cloud"), oauth.DefaultAuthorization("path/to/api-key.json"), ) if err != nil { slog.Error("authorizer init failed", "error", err) os.Exit(1) } // Verify a token directly authCtx, err := authZ.CheckAuthorization(ctx, "Bearer someaccesstoken", authorization.WithRole("admin"), ) if err != nil { slog.Error("unauthorized", "error", err) return } slog.Info("authorized", "userID", authCtx.UserID(), "org", authCtx.OrganizationID()) } ``` ``` -------------------------------- ### Client Credentials Grant Authentication Source: https://context7.com/zitadel/zitadel-go/llms.txt Use this for service-to-service authentication. It exchanges client ID and secret for an access token. ```go package main import ( "context" "log/slog" "os" "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/management" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authOpt := client.PasswordAuthentication( "my-client-id", "my-client-secret", oidc.ScopeOpenID, client.ScopeZitadelAPI(), ) api, err := client.New(ctx, zitadel.New("https://example.us1.zitadel.cloud"), client.WithAuth(authOpt)) if err != nil { slog.Error("init failed", "error", err) os.Exit(1) } defer api.Close() resp, err := api.ManagementService().GetMyOrg(ctx, &management.GetMyOrgRequest{}) if err != nil { slog.Error("call failed", "error", err) os.Exit(1) } slog.Info("org", "name", resp.GetOrg().GetName()) } ``` -------------------------------- ### client.PAT — Personal Access Token Auth Source: https://context7.com/zitadel/zitadel-go/llms.txt Returns a `TokenSourceInitializer` backed by a static Personal Access Token (PAT). This method is ideal for development, testing, or CI scripts where dynamic token generation is not required. ```APIDOC ## `client.PAT` — Personal Access Token Auth Returns a `TokenSourceInitializer` backed by a static Personal Access Token (PAT). Ideal for development, testing, or CI scripts where dynamic token generation is not needed. ```go package main import ( "context" "log" "log/slog" "os" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/management" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() api, err := client.New( ctx, zitadel.New("https://example.us1.zitadel.cloud"), client.WithAuth(client.PAT("my-personal-access-token")), ) if err != nil { slog.Error("init failed", "error", err) os.Exit(1) } defer api.Close() resp, err := api.ManagementService().GetMyOrg(ctx, &management.GetMyOrgRequest{}) if err != nil { slog.Error("call failed", "error", err) os.Exit(1) } log.Printf("org: %s", resp.GetOrg().GetName()) } ``` ``` -------------------------------- ### Custom OIDC Code Flow with `openid.WithCodeFlow` Source: https://context7.com/zitadel/zitadel-go/llms.txt Use this constructor for custom OIDC Authorization Code flows when a custom context type is needed. Ensure you provide a valid `ClientAuthentication` like `PKCEAuthentication` or `ClientIDSecretAuthentication` and a `httphelper.CookieHandler`. ```go import ( "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/oidc/v3/pkg/client/rp" httphelper "github.com/zitadel/oidc/v3/pkg/http" openid "github.com/zitadel/zitadel-go/v3/pkg/authentication/oidc" "github.com/zitadel/zitadel-go/v3/pkg/authentication" ) type MyAuthCtx = openid.UserInfoContext[*oidc.IDTokenClaims, *oidc.UserInfo] cookieKey := []byte("32-byte-cookie-encryption-key!!") cookieHandler := httphelper.NewCookieHandler(cookieKey, cookieKey) handlerInit := openid.WithCodeFlow[*MyAuthCtx, *oidc.IDTokenClaims, *oidc.UserInfo]( openid.PKCEAuthentication( "client-id", "https://myapp.example.com/auth/callback", []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail}, cookieHandler, ), ) // Use in authentication.New as the HandlerInitializer _ = handlerInit ``` -------------------------------- ### middleware.New (HTTP) — Authorization Middleware for REST APIs Source: https://context7.com/zitadel/zitadel-go/llms.txt Wraps an `*Authorizer` into an HTTP middleware. `RequireAuthorization()` handles token extraction, introspection, and optional role enforcement, responding with 401 or 403 on failure. ```APIDOC ## `middleware.New` (HTTP) — Authorization Middleware for REST APIs Wraps an `*Authorizer` into an HTTP middleware. `RequireAuthorization()` returns a handler wrapper that extracts the `Authorization` header, introspects the token, and (optionally) enforces role requirements. On failure it responds `401 Unauthorized` or `403 Forbidden`. ```go package main import ( "context" "log/slog" "net/http" "os" "github.com/zitadel/zitadel-go/v3/pkg/authorization" "github.com/zitadel/zitadel-go/v3/pkg/authorization/oauth" httpMiddleware "github.com/zitadel/zitadel-go/v3/pkg/http/middleware" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authZ, _ := authorization.New(ctx, zitadel.New("https://example.us1.zitadel.cloud"), oauth.DefaultAuthorization("api-key.json")) mw := httpMiddleware.New(authZ) router := http.NewServeMux() // Public endpoint — no auth required router.Handle("/api/healthz", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`"OK"`)) })) // Requires a valid token (any role) router.Handle("/api/tasks", mw.RequireAuthorization()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authCtx := mw.Context(r.Context()) slog.Info("access", "user", authCtx.UserID()) w.Write([]byte(`{"tasks":[]}`))) }))) // Requires a valid token AND the "admin" role router.Handle("/api/add-task", mw.RequireAuthorization(authorization.WithRole("admin"))(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { task := r.FormValue("task") slog.Info("admin added task", "user", authorization.UserID(r.Context()), "task", task) w.Write([]byte(`"task added"`)) }))) slog.Info("listening on :8089") if err := http.ListenAndServe(":8089", router); err != nil { slog.Error("server error", "error", err) os.Exit(1) } } ``` ``` -------------------------------- ### client.DefaultServiceUserAuthentication — JWT Profile Auth from Key File Source: https://context7.com/zitadel/zitadel-go/llms.txt Explains how to use `client.DefaultServiceUserAuthentication` to configure authentication using a Zitadel service-account key JSON file. This method utilizes the OAuth2 JWT Profile Grant and is recommended for production environments. ```APIDOC ## client.DefaultServiceUserAuthentication — JWT Profile Auth from Key File Reads a Zitadel service-account key JSON file from disk and returns a `TokenSourceInitializer` that uses the OAuth2 JWT Profile Grant. Best choice for production service users. ### Request Example ```go package main import ( "context" "log/slog" "os" "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/user/v2" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authOpt := client.DefaultServiceUserAuthentication( "./service-account-key.json", oidc.ScopeOpenID, client.ScopeZitadelAPI(), ) api, err := client.New(ctx, zitadel.New("https://example.us1.zitadel.cloud"), client.WithAuth(authOpt)) if err != nil { slog.Error("init failed", "error", err) os.Exit(1) } defer api.Close() resp, err := api.UserServiceV2().GetUserByID(ctx, &userv2.GetUserByIDRequest{UserId: "123456789"}) if err != nil { slog.Error("GetUserByID failed", "error", err) os.Exit(1) } slog.Info("user found", "login", resp.GetUser().GetHumanUser().GetProfile().GetDisplayName()) } ``` ``` -------------------------------- ### authentication.Middleware Source: https://context7.com/zitadel/zitadel-go/llms.txt Provides HTTP middleware factories, `RequireAuthentication()` and `CheckAuthentication()`, to wrap an Authenticator. `RequireAuthentication` redirects unauthenticated users to login, while `CheckAuthentication` enriches the context if a session exists without redirecting. ```APIDOC ## `authentication.Middleware` — HTTP Authentication Middleware Wraps an `Authenticator` (or any `AuthenticationChecker`) into an `*Interceptor` exposing `RequireAuthentication()` and `CheckAuthentication()` middleware factories. `RequireAuthentication` redirects unauthenticated requests to the login UI; `CheckAuthentication` is non-redirecting and only enriches the context if a session exists. ``` -------------------------------- ### gRPC Authorization Middleware with `grpc/middleware.New` Source: https://context7.com/zitadel/zitadel-go/llms.txt Use this middleware to add Bearer token introspection and optional per-RPC authorization checks to your gRPC server. Ensure the `authorization` and `grpc/middleware` packages are imported. ```go package main import ( "context" "log/slog" "net" "os" "google.golang.org/grpc" "github.com/zitadel/zitadel-go/v3/pkg/authorization" "github.com/zitadel/zitadel-go/v3/pkg/authorization/oauth" grpcMiddleware "github.com/zitadel/zitadel-go/v3/pkg/grpc/middleware" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authZ, err := authorization.New(ctx, zitadel.New("https://example.us1.zitadel.cloud"), oauth.DefaultAuthorization("api-key.json")) if err != nil { slog.Error("authorizer init failed", "error", err) os.Exit(1) } // checks maps RPC full method names to required CheckOptions checks := map[string][]authorization.CheckOption{ "/example.ExampleService/AddTask": {authorization.WithRole("admin")}, } mw := grpcMiddleware.New(authZ, checks) srv := grpc.NewServer( grpc.UnaryInterceptor(mw.Unary()), grpc.StreamInterceptor(mw.Stream()), ) lis, _ := net.Listen("tcp", ":50051") slog.Info("gRPC server listening on :50051") if err = srv.Serve(lis); err != nil { slog.Error("server error", "error", err) os.Exit(1) } } ``` -------------------------------- ### openid.DefaultAuthentication Source: https://context7.com/zitadel/zitadel-go/llms.txt Configures the OIDC Authorization Code + PKCE flow using the `DefaultContext`. It accepts optional additional scopes, defaulting to `openid`, `profile`, and `email` if none are provided. ```APIDOC ## `openid.DefaultAuthentication` — PKCE Code Flow Helper Returns a `HandlerInitializer` preconfigured for the OIDC Authorization Code + PKCE flow using the `DefaultContext` type (ID token claims + UserInfo). Accepts optional additional scopes; if omitted, defaults to `openid profile email`. ``` -------------------------------- ### HTTP Authentication Middleware with Go Source: https://context7.com/zitadel/zitadel-go/llms.txt Wraps an Authenticator into an Interceptor for authentication middleware. RequireAuthentication redirects unauthenticated requests, while CheckAuthentication enriches the context if a session exists without redirecting. ```go // RequireAuthentication — redirect to login if no valid session mux.Handle("/dashboard", mw.RequireAuthentication()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authCtx := mw.Context(r.Context()) // authCtx is guaranteed non-nil and authenticated here _ = authCtx.IsAuthenticated() // true w.Write([]byte("welcome to the dashboard")) }))) // CheckAuthentication — no redirect; session info available if present mux.Handle("/public", mw.CheckAuthentication()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if authentication.IsAuthenticated(r.Context()) { authCtx := mw.Context(r.Context()) w.Write([]byte("hi " + authCtx.(*openid.DefaultContext).UserInfo.PreferredUsername)) } else { w.Write([]byte("anonymous visitor")) } }))) ``` -------------------------------- ### client.PasswordAuthentication — Client Credentials Grant Source: https://context7.com/zitadel/zitadel-go/llms.txt Returns a `TokenSourceInitializer` that exchanges a `client_id` / `client_secret` pair against the token endpoint using the OAuth2 Client Credentials Grant. This is suitable for server-to-server communication. ```APIDOC ## `client.PasswordAuthentication` — Client Credentials Grant Returns a `TokenSourceInitializer` that exchanges a `client_id` / `client_secret` pair against the token endpoint using the OAuth2 Client Credentials Grant. ```go package main import ( "context" "log/slog" "os" "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/zitadel-go/v3/pkg/client" "github.com/zitadel/zitadel-go/v3/pkg/client/zitadel/management" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authOpt := client.PasswordAuthentication( "my-client-id", "my-client-secret", oidc.ScopeOpenID, client.ScopeZitadelAPI(), ) api, err := client.New(ctx, zitadel.New("https://example.us1.zitadel.cloud"), client.WithAuth(authOpt)) if err != nil { slog.Error("init failed", "error", err) os.Exit(1) } defer api.Close() resp, err := api.ManagementService().GetMyOrg(ctx, &management.GetMyOrgRequest{}) if err != nil { slog.Error("call failed", "error", err) os.Exit(1) } slog.Info("org", "name", resp.GetOrg().GetName()) } ``` ``` -------------------------------- ### grpc/middleware.New Source: https://context7.com/zitadel/zitadel-go/llms.txt Provides Unary() and Stream() gRPC server interceptors that perform Bearer token introspection and optional per-RPC authorization checks. ```APIDOC ## grpc/middleware.New — Authorization Middleware for gRPC APIs Provides `Unary()` and `Stream()` gRPC server interceptors that perform the same Bearer token introspection as the HTTP middleware, with optional per-RPC authorization checks. ### Usage Example ```go package main import ( "context" "log/slog" "net" "os" "google.golang.org/grpc" "github.com/zitadel/zitadel-go/v3/pkg/authorization" "github.com/zitadel/zitadel-go/v3/pkg/authorization/oauth" grpcMiddleware "github.com/zitadel/zitadel-go/v3/pkg/grpc/middleware" "github.com/zitadel/zitadel-go/v3/pkg/zitadel" ) func main() { ctx := context.Background() authZ, err := authorization.New(ctx, zitadel.New("https://example.us1.zitadel.cloud"), oauth.DefaultAuthorization("api-key.json")) if err != nil { slog.Error("authorizer init failed", "error", err) os.Exit(1) } // checks maps RPC full method names to required CheckOptions checks := map[string][]authorization.CheckOption{ "/example.ExampleService/AddTask": {authorization.WithRole("admin")}, } mw := grpcMiddleware.New(authZ, checks) srv := grpc.NewServer( grpc.UnaryInterceptor(mw.Unary()), grpc.StreamInterceptor(mw.Stream()), ) lis, _ := net.Listen("tcp", ":50051") slog.Info("gRPC server listening on :50051") if err = srv.Serve(lis); err != nil { slog.Error("server error", "error", err) os.Exit(1) } } ``` ``` -------------------------------- ### oauth.NewIntrospectionVerificationWithCache Source: https://context7.com/zitadel/zitadel-go/llms.txt Wraps a ResourceServer and a TokenCache to avoid redundant introspection network calls for the same token within a configured TTL. ```APIDOC ## oauth.NewIntrospectionVerificationWithCache — Cached Token Introspection Wraps a `ResourceServer` and a `TokenCache` to avoid redundant introspection network calls for the same token within a configured TTL. The built-in `GoCacheAdapter` provides a ready-to-use `TokenCache` implementation backed by `patrickmn/go-cache`. ### Usage Example ```go package main import ( "context" "fmt" "time" gocache "github.com/patrickmn/go-cache" "github.com/zitadel/zitadel-go/v3/pkg/authorization/oauth" ) func main() { // Build a GoCacheAdapter with 5-minute default TTL and 10-minute cleanup cacheAdapter := oauth.NewGoCacheAdapter[*oauth.IntrospectionContext]( 5*time.Minute, 10*time.Minute, ) _ = cacheAdapter // inject into NewIntrospectionVerificationWithCache together with a rs.ResourceServer // Example wiring (resourceServer obtained from rs.NewResourceServerJWTProfile or similar): // // verifier := oauth.NewIntrospectionVerificationWithCache(resourceServer, cacheAdapter, 30*time.Second) // authCtx, err := verifier.CheckAuthorization(context.Background(), "Bearer mytoken") fmt.Println("cache ready") _ = context.Background() _ = gocache.New(5*time.Minute, 10*time.Minute) // illustrative } ``` ``` -------------------------------- ### openid.WithCodeFlow — Custom OIDC Code Flow Source: https://context7.com/zitadel/zitadel-go/llms.txt This function provides a lower-level constructor for the OIDC Authorization Code flow, allowing for a custom context type. It supports PKCE or ClientIDSecret authentication methods. ```APIDOC ## `openid.WithCodeFlow` — Custom OIDC Code Flow Lower-level constructor for the OIDC Authorization Code flow when you need a custom context type beyond `DefaultContext`. Use `PKCEAuthentication` or `ClientIDSecretAuthentication` as the `ClientAuthentication` argument. ```go import ( "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/oidc/v3/pkg/client/rp" httphelper "github.com/zitadel/oidc/v3/pkg/http" openid "github.com/zitadel/zitadel-go/v3/pkg/authentication/oidc" "github.com/zitadel/zitadel-go/v3/pkg/authentication" ) type MyAuthCtx = openid.UserInfoContext[*oidc.IDTokenClaims, *oidc.UserInfo] cookieKey := []byte("32-byte-cookie-encryption-key!!") cookieHandler := httphelper.NewCookieHandler(cookieKey, cookieKey) handlerInit := openid.WithCodeFlow[*MyAuthCtx, *oidc.IDTokenClaims, *oidc.UserInfo]( openid.PKCEAuthentication( "client-id", "https://myapp.example.com/auth/callback", []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail}, cookieHandler, ), ) // Use in authentication.New as the HandlerInitializer _ = handlerInit ``` ``` -------------------------------- ### Cached Token Introspection with `oauth.NewIntrospectionVerificationWithCache` Source: https://context7.com/zitadel/zitadel-go/llms.txt Implement a token introspection verifier that caches results using a `TokenCache` implementation like `GoCacheAdapter` to reduce redundant network calls. Configure cache TTL and cleanup intervals. ```go package main import ( "context" "fmt" "time" gocache "github.com/patrickmn/go-cache" "github.com/zitadel/zitadel-go/v3/pkg/authorization/oauth" ) func main() { // Build a GoCacheAdapter with 5-minute default TTL and 10-minute cleanup cacheAdapter := oauth.NewGoCacheAdapter[*oauth.IntrospectionContext]( 5*time.Minute, 10*time.Minute, ) _ = cacheAdapter // inject into NewIntrospectionVerificationWithCache together with a rs.ResourceServer // Example wiring (resourceServer obtained from rs.NewResourceServerJWTProfile or similar): // // verifier := oauth.NewIntrospectionVerificationWithCache(resourceServer, cacheAdapter, 30*time.Second) // authCtx, err := verifier.CheckAuthorization(context.Background(), "Bearer mytoken") fmt.Println("cache ready") _ = context.Background() _ = gocache.New(5*time.Minute, 10*time.Minute) // illustrative } ```