Skip to content

hanko

backend/v3.1.0
teamhanko/hanko

Modern authentication, on your terms. Open source alternative to Auth0, Clerk, WorkOS, Stytch.

Version of teamhanko/hanko you run

CompareView on GitHub

Breaking changes

What to check before upgrading, taken from the notes of the last 30 releases.

Release history

All releases on GitHub
BadgeLatest version of teamhanko/hanko[![version](/badge/teamhanko/hanko)](/p/teamhanko/hanko)

Hanko v3.1

Hanko v3.1 introduces Organizations and Roles for building B2B applications, alongside Custom Claims and Mapping for bringing identity provider attributes into your application. This release also adds session lifecycle webhooks, improves user imports, and includes several security fixes.

Organizations and Roles

You can now group users into organizations within a Hanko tenant and assign roles to their memberships. This gives applications a foundation for managing customer accounts, teams, and organization-specific access.

Roles are defined at the tenant level and assigned to users within individual organizations. For example, a user can be an admin in one organization and a member in another, while your application uses the same role definitions across both.

The new APIs let you:

  • Create, list, update, and delete organizations and roles.
  • Add users to organizations and manage their role assignments.
  • Create users with organization memberships and roles in a single request.
  • Retrieve organization memberships and roles through the user APIs and session validation.
  • Check whether the current session holds any of a specified set of roles in an organization using POST /organizations/roles/check.

Your application can use these role checks to enforce access to organization-specific resources. Organizations, memberships, and role bindings are scoped to their Hanko tenant.

See [#2893](https://github.com/teamhanko/hanko/pull/2893).

Custom Claims and Mapping

Hanko now supports tenant-defined custom claims, with mappings from SAML attributes and custom OIDC/OAuth2 provider claims. This lets you normalize identity data from different providers and make it available to your application through Hanko.

For example, different customer identity providers might represent a department or group membership under different attribute names. You can map those attributes to consistent Hanko custom claims such as department or groups, then include them in your session JWT.

Define and map your claims

Declare claim names, types, and optional descriptions under custom_claims.definitions. Definitions support scalar values and lists of scalars, with up to 50 custom claim definitions per tenant.

Configure mappings for each connection:

  • SAML: Map identity provider attributes using attribute_map.custom.
  • Custom OIDC/OAuth2 providers: Map values from the provider’s raw claims using custom_claim_mapping, with GJSON paths for selecting values.

Mappings are validated against your claim definitions when saved, helping catch configuration errors before users log in.

Use claims in your application

Custom claim values are resolved and stored when a user logs in through a mapped connection. You can include them in JWT templates using references such as:

{{ .User.CustomClaims "department" }}

When a template value consists solely of a custom claim reference, Hanko preserves its underlying type, including numbers, booleans, and arrays.

Stored claims are also available through the read-only Admin API endpoint GET /users/:id/custom_claims. The new user.update.custom_claims webhook event lets your application react when claim values change.

Claim updates track their source connection: if that connection stops supplying a claim it owns, the value is cleared. An unrelated connection omitting the same claim does not clear it.

See [#2884](https://github.com/teamhanko/hanko/pull/2884).

Important for self-hosters: client IP resolution has changed

This release fixes a rate limit bypass caused by trusting client-supplied X-Forwarded-For and X-Real-IP headers.

Hanko now defaults to direct IP extraction, using the connecting network peer’s address and ignoring forwarding headers.

If you run Hanko behind a reverse proxy, load balancer, or ingress controller, update your configuration so rate limits continue to apply to individual client IPs. Without this change, clients connecting through the same proxy may share a rate limit bucket.

For a proxy using X-Forwarded-For:

server:
  ip:
    extractor: x_forwarded_for
    trusted_proxies:
      - "10.0.1.0/24" # Replace with your proxy's actual CIDR range

Use x_real_ip instead if your proxy provides the client address through X-Real-IP.

Both header-based modes require trusted_proxies. Configure only the address ranges of your own proxies, ensure they strip or overwrite client-supplied forwarding headers, and prevent clients from reaching Hanko directly when using these modes.

Deployments where clients connect directly to Hanko can keep the default direct mode.

See [#2739](https://github.com/teamhanko/hanko/pull/2739).

More improvements

  • Session lifecycle webhooks: Subscribe to session creation and deletion events, including login, administrative creation, logout, revocation, idle timeout, and session-limit eviction. See [#2838](https://github.com/teamhanko/hanko/pull/2838).
  • Tenant-scoped user IDs: The same caller-supplied user ID can now be used in separate tenants, simplifying imports and migrations. Existing users retain their externally visible IDs. See [#2826](https://github.com/teamhanko/hanko/pull/2826).
  • Improved password imports: Added support for bcrypt hashes using the $2b$ format.
  • Longer SAML certificate validity: Newly generated SP certificates now default to a validity of 10 years.
  • Additional translations: Added Korean frontend translations and Polish email translations.
  • Developer experience: Added a static passcode generator for tests, expanded Flow API type documentation, and embedded backend version information in container images.

Security and reliability

This release also prevents TOTP code replay, fixes a third-party redirect allowlist bypass and cross-tenant data leakage, and adds validation to prevent linking unverified third-party provider email addresses.

Further fixes improve SAML error handling, third-party login redirects, cancelled passkey registration handling, and support for long user-agent strings.

Thanks to everyone who contributed code, translations, bug reports, and dependency updates to this release!

What's Changed

Full release notesCompare with previous