netbirdio/netbird · error
identity provider issuer does not match the issuer returned
Error message
identity provider issuer does not match the issuer returned by the provider
What it means
Sentinel error types.ErrIdentityProviderIssuerMismatch (management/server/types/identity_provider.go:16), returned by validateOIDCIssuer when the discovery document was fetched successfully but its top-level "issuer" claim differs from the configured Issuer string. Per OIDC Discovery (RFC 8414 section 3), the provider must advertise its own issuer at that URL, and NetBird enforces exact string equality.
Source
Thrown at management/server/types/identity_provider.go:16
package types
import (
"errors"
"net/url"
)
// Identity provider validation errors
var (
ErrIdentityProviderNameRequired = errors.New("identity provider name is required")
ErrIdentityProviderTypeRequired = errors.New("identity provider type is required")
ErrIdentityProviderTypeUnsupported = errors.New("unsupported identity provider type")
ErrIdentityProviderIssuerRequired = errors.New("identity provider issuer is required")
ErrIdentityProviderIssuerInvalid = errors.New("identity provider issuer must be a valid URL")
ErrIdentityProviderIssuerUnreachable = errors.New("identity provider issuer is unreachable")
ErrIdentityProviderIssuerMismatch = errors.New("identity provider issuer does not match the issuer returned by the provider")
ErrIdentityProviderClientIDRequired = errors.New("identity provider client ID is required")
)
// IdentityProviderType is the type of identity provider
type IdentityProviderType string
const (
// IdentityProviderTypeOIDC is a generic OIDC identity provider
IdentityProviderTypeOIDC IdentityProviderType = "oidc"
// IdentityProviderTypeZitadel is the Zitadel identity provider
IdentityProviderTypeZitadel IdentityProviderType = "zitadel"
// IdentityProviderTypeEntra is the Microsoft Entra (Azure AD) identity provider
IdentityProviderTypeEntra IdentityProviderType = "entra"
// IdentityProviderTypeGoogle is the Google identity provider
IdentityProviderTypeGoogle IdentityProviderType = "google"
// IdentityProviderTypeOkta is the Okta identity provider
IdentityProviderTypeOkta IdentityProviderType = "okta"
// IdentityProviderTypePocketID is the PocketID identity providerView on GitHub (pinned to 93e97f4bf1)
Solutions
- Read the error's expected/got values and configure the Issuer exactly as the provider advertises it in its discovery document
- Fix the proxy/IdP so the advertised issuer matches the URL the discovery document is served under (X-Forwarded-Host / Forwarded headers)
- Remove or add the trailing slash so both strings are byte-identical
Example fix
// before idp.Issuer = "https://auth.example.com/realms/nb" // provider advertises .../realms/nb/ // after idp.Issuer = "https://auth.example.com/realms/nb/"
Defensive patterns
Strategy: validation
Validate before calling
// Verify the provider advertises exactly this issuer before saving
func issuerMatchesDiscovery(ctx context.Context, issuer string) error {
if err := issuerReachable(ctx, issuer); err != nil { return err }
body, _ := fetchDiscovery(ctx, issuer)
var doc struct{ Issuer string `json:"issuer"` }
if err := json.Unmarshal(body, &doc); err != nil { return err }
if doc.Issuer != issuer {
return fmt.Errorf("provider advertises %q; use that as the issuer", doc.Issuer)
}
return nil
} Try / catch
err := saveIdP(ctx, idp)
if err != nil && errors.Is(err, types.ErrIdentityProviderIssuerMismatch) {
// parse 'expected X got Y' from the message and re-save with Y as issuer
} Prevention
- Always copy the issuer from the provider's discovery document, not from its admin UI URL
- Configure reverse proxies (X-Forwarded-Proto/Host) so the advertised issuer matches the external URL
- Watch for trailing-slash differences; OIDC requires byte-exact issuer equality
When it happens
Trigger: Configured issuer "https://auth.example.com/realms/nb" while the discovery document at that URL advertises "https://auth.example.com/realms/nb/" (trailing slash), a proxy-rewritten host, or a completely different external URL. The error message includes expected vs got.
Common situations: Reverse proxy in front of the IdP rewrites the Host header or strips path prefixes; IdP behind a public domain while advertising its internal URL (or vice versa); trailing-slash differences between what you configure and what the provider advertises; multi-tenant realms with canonical URLs.
Related errors
- identity provider name is required
- identity provider type is required
- unsupported identity provider type
- identity provider issuer is required
- identity provider issuer must be a valid URL
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/dedeff91a399ca62.
Report an issue: GitHub.