Commit Graph
72 Commits
Author SHA1 Message Date
Tim MöhlmannandGitHub eb22b58756 feat(telemetry): improved instrumentation for observability (#11159)
# Which Problems Are Solved

Zitadel did not provide easy correlation between errors, logs, traces
and metrics. The configuration for those instrumentations was also not
consistent, with some supporting different exporters then others.
Implementation and parsing of config was also spaghettified over
multiple packages, with awkward parsing and inconsistent naming of
options.

# How the Problems Are Solved

All telemetry is now merged under the name "instrumentation". Why?
1. We thought it was a good idea in the past to call the milestone
exporter `Telemtry` in the runtime config. Calling this `TelemetryV2`
looks weird.
2. Not everything is a meter and not everything is sent (tele...). 
3. It's also
[defined](https://opentelemetry.io/docs/concepts/instrumentation/) as
such by the OTEL documentation.

## New features

- Adds structured, context based logging with trace-ID awareness
- Static log fields are added to the context, such as service and
request path
- Static log fields are injected in each logline emitted by the
application
- Structured logs can also be send to an otel exporter
- Structured logs can be printed to StdErr in text and JSON format
- Error sinks make sure every error is logged at the correct level:
- Warnings for client side errors (HTTP 400 range, Invalid request etc)
  - Error for server side errors (Internal server errors)
- Metrics can now also be send to a OTEL collector. (previously they
could only be scraped from `/debug/metrics` with prometheus)

## Exporters

This change adds all the exporters supported by OTEL upstream and some
google specific exporters for our cloud deployment.

- StdOut / StdErr: all instrumentations
- OTEL gRPC / HTTP: all instrumentations
- Google: all instrumentations except logging
- Prometheus (pull-based): only metrics

The exception is profiling, which only supports the google exporting due
to lack of support by OTEL upstream.

## Configuration and structure 

- All instrumentation is moved into the new `backend/v3/instrumentation`
package. It reuses configuration types, so both code and runtime
configuration are easier to understand.
- The `internal/telemetry` packages are removed.
- Instrumentation is started with a single function and a proper
shutdown function is now provided.
- Legacy configuration is still parsed from the runtime config, as long
as the new configuration is disabled. This allows backporting this
feature to v4 without breaking existing configurations.

# Additional Changes

- Devcontainer: set `$PATH` variable so installed go binaries can be run
individually, without NX.
- NX: install GCI tool to fix imports

# Additional Context

- Closes https://github.com/zitadel/zitadel/issues/8408
- Closes https://github.com/zitadel/zitadel/issues/6664
- Backport to v4
2026-01-12 05:51:39 +00:00
RamonandGitHub 20b6c9869a chore: update deps (#11273)
# Which Problems Are Solved
Fix failing compliance alert because of old depedencies.

# How the Problems Are Solved
Updated our npm dependencies

# Additional Changes
- Updated Docusaurus to React 19 to unify our react versions
- Fixed flaky e2e test
2026-01-07 09:48:30 +01:00
9f1119823b fix(login): cleanup server logs (#11195)
Closes #11184

# Which Problems Are Solved

- loginName: This information is already retrievable from the URL
parameters during the authentication flow, so logging it presented no
additional exposure.
- idpIntent: This was being logged to the server console (server-side
logs), so it was never exposed to the client/browser.
These changes simply clean up the server logs to prevent unnecessary
data noise.

# How the Problems Are Solved

- Removed idpIntent logging from 
`apps/login/src/lib/server/idp-intent.ts`
- Removed loginName logging from 
`apps/login/src/lib/server/password.ts`

---------

Co-authored-by: Livio Spring <[email protected]>
2026-01-05 13:46:09 +00:00
Max PeintnerandGitHub 072755f85a fix(login): delete custom request headers when their value is empty (#11263)
# Which Problems Are Solved

The application automatically appends the x-zitadel-public-host header
when a public host is configured. In some deployment scenarios where the
host is determined by default or via other means, sending this header
allows for improper routing or is simply redundant. The existing
CUSTOM_REQUEST_HEADERS configuration only supported adding or
overwriting headers, offering no way to remove headers that were set by
default logic.

# How the Problems Are Solved

Extended the `CUSTOM_REQUEST_HEADERS` handling in `src/lib/zitadel.ts`.
The logic now checks for empty header values. If a header is defined in
`CUSTOM_REQUEST_HEADERS` with an empty value (e.g.,
x-zitadel-public-host:), the interceptor will delete that header from
the request instead of setting it to an empty string. This allows users
to opt-out of default headers via configuration.
2026-01-05 13:44:19 +01:00
Max PeintnerandGitHub 7963cdd713 fix(login): enable explicit IDP linking using existing session id (#11225)
Closes #11191 

# Which Problems Are Solved

This PR fixes the IDP linking for accounts with no authentication
method.
We strictly validate session ownership and generate a hash of the
sessionId + the user's fingerprintId cookie. This hash is passed to the
IDP as linkFingerprint.

This PR addtionally addresses TypeScript errors regarding unknown types
in catch blocks within the IDP intent processing logic. It ensures that
errors occurring during IDP linking are safely handled, and that
meaningful error messages are propagated to the client-side redirect
URLs.

# How the Problems Are Solved

- Safely handle unknown errors: Updated catch blocks in
`processIDPCallback` to check if the caught object is an instance of
Error before accessing error.message.
- Fix "IDP Taken" check: Implemented a safe check for the gRPC error
code 6 (Already Exists) by casting the error, resolving the Property
'code' does not exist on type 'unknown' build error.
- Error Propagation: The specific error message is now passed to the
linking-failed page params, allowing for better user feedback instead of
generic errors.
2025-12-30 14:32:37 +00:00
c9b89b97ab feat(login): Add Dutch (nl) locale (#11139)
# Which Problems Are Solved

* Missing Dutch (nl) translations in the login UI v2.

# How the Problems Are Solved

* Adds nl.json with Dutch translations.
* The same data is added to v2-default.json, because otherwise English
was overriding nl.json content.
* Adds Dutch to the language dropdown in somewhat alphabetical order.

# Additional Changes

None.

# Additional Context

None.

---------

Co-authored-by: thomas-swennenhuis <[email protected]>
2025-12-22 12:38:02 +00:00
82c774dab3 feat(languages): add French localization (#11050)
# Which Problems Are Solved

Previous login app had french localization and the new app doesn't have
it anymore. It simply re-add this missing locale.

# How the Problems Are Solved

Simply add french localization.

# Additional Changes

None

# Additional Context

I don't know how to add it by default in backend, i will happily make
the changes for adding by default this langage.

Co-authored-by: Marco A. <[email protected]>
Co-authored-by: Wim Van Laer <[email protected]>
2025-12-16 16:35:14 +01:00
Max PeintnerandGitHub 9bbf0096b6 fix: update pnpm, react, react-dom (#11197)
Closes #11192 

# Which Problems Are Solved

Update pnpm, react and react-dom to the latest version

# How the Problems Are Solved

the version references are updated as part of the package.json files
2025-12-16 15:04:31 +00:00
2221b5ef74 fix(login): CVE-2025-55184 and CVE-2025-55183, update next (#11179)
# Which Problems Are Solved

Updates `next` to version `15.5.9` to address the following security
vulnerabilities:

- **CVE-2025-55184**
- **CVE-2025-55183**

# How the Problems Are Solved

- Bump `next` from `15.5.7` to `15.5.9` in `apps/login/package.json`

---------

Co-authored-by: PhenixH <[email protected]>
2025-12-12 13:01:05 +01:00
aafc15b8c3 fix: [CVE-2025-55182] [CVE-2025-66478] Quick update react and Nextjs for #11140 (#11143)
# Which Problems Are Solved

Temporary update of nextjs and react to fix major CVE (described #11140)

Build passing and force dependency for old deps, but we will need to
update packages (I update qrcode-react, minimal impact, not feasible for
react-hook-form which needs more work).

# How the Problems Are Solved

Upgrade dependencies to patched version of the same major and minor,
remove experimental flag dynamicIO and added flag useCache (used in
code)

# Additional Changes



# Additional Context

- https://nextjs.org/blog/CVE-2025-66478 
-
https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components

Co-authored-by: Max Peintner <[email protected]>
2025-12-12 10:30:49 +00:00
41cdc7805f feat(i18n): add Ukrainian language support (#10696)
## Summary
  - Add comprehensive Ukrainian language support to ZITADEL
  - Complete translation of all user-facing interfaces
  - Integration with existing language configuration system

  ## Changes Made
- ✅ **Console translations**: Complete Ukrainian translation for admin
console (2,861 translated strings)
- ✅ **Login interface**: Ukrainian translations for authentication flows
(535 strings)
- ✅ **Email notifications**: Ukrainian translations for system emails
(68 strings)
- ✅ **Common texts**: Ukrainian translations for success/error messages
(1,417 strings)
- ✅ **Language configuration**: Added Ukrainian to supported languages
and Angular locale registration
- ✅ **UI integration**: Added Ukrainian option to language selection
forms

  ## Translation Quality
  - Professional translations using established Ukrainian IT terminology
  - Formal language appropriate for business software
- Consistent terminology across all components (Users→Користувачі,
Organization→Організація, etc.)
  - Preserved all technical placeholders, HTML tags, and formatting

  ## Contributing Guidelines Compliance
  - ✅ Followed semantic commit message format
  - ✅ Added Ukrainian to all required configuration files
  - ✅ Maintained consistent file structure with existing languages
  - ✅ Used formal Ukrainian appropriate for business software

The Ukrainian translation is now ready for review by the ZITADEL team! 🚀

---------

Co-authored-by: Marco A. <[email protected]>
2025-12-11 15:37:31 +01:00
Livio SpringandGitHub 541f8058cb chore(tests): fix login unit-tests (#11155)
# Which Problems Are Solved

The unit-tests on main currently fail. Most likely some nx cache issue.

# How the Problems Are Solved

Fix the unit tests.

# Additional Changes

none

# Additional Context

Noted on multiple PRs
2025-12-09 10:45:23 +00:00
df75be96ff Merge commit from fork
* fix: Improve host header handling and deployment mode detection

* ZITADEL_CLOUD env

* refactor service config

* service config

* cleanup

* cleanup

* util for original and public host

* instanceHost, publicHost

* cleanup constructUrl

* cleanup middleware

* add x-zitadel-forward-host as fallback for current cloud setup

* fix build

* fix: lint

* fix: update test mocks

* fix: provide basepath to unit tests

* host handling

* unit tests

* imports

* fix: getPublicHost instead of getInstanceHost

* unit tests

* update nextjs, implement jwt verify for logout_token

* pass logout information in jwt to login v2

* handle hosts in jwks url

* point idp callbacks to the api and not the login UI

* logout_hint out of logout token, typecheck

* rm unused imports

* fix oidc integration test

---------

Co-authored-by: Livio Spring <[email protected]>
2025-12-08 10:01:49 +01:00
b4732579cb fix(RT): correct restricting null columns (#11123)
# Which Problems Are Solved

`IS NULL` and `IS NOT NULL` conditions were incorrectly marked as
restricting columns,
and currently fails unit tests. The restricting columns are mostly used
to ensure single row selection during DELETE and UPDATE . When a `IS NOT
NULL` condition is passed, the filter may (unintentionally) apply to all
rows, while still allowing the query to execute.

Settings and other repositories (still to be done) have unified tables
for instance-level settings and organization-level settings. In those
cases the organization ID may be null or have a value. The unique
condition is a compound of multiple columns, in which case `IS NULL` is
valid as part of the other restricting columns.

# How the Problems Are Solved

In order to prevent unsafe usage of null related filters and not break
settings:

- null conditions are no longer considered restricting columns
- A function to force the restricting column state on a condition is
provided
- The settings unique condition function forces restricting column state
on the returned condition.

# Additional Changes

- add `backend/v3` to the NX build.

# Additional Context

- [pipeline
failures](https://github.com/zitadel/zitadel/actions/runs/19852295780/job/56881654340?pr=11115#step:13:3197)

---------

Co-authored-by: Elio Bischof <[email protected]>
2025-12-03 16:15:49 +00:00
86cce629c7 chore(login): add unit tests for core business logic (#11083)
# Which Problems Are Solved

- Adds basic unit tests for core business logic
- Adds playwright tests for core flows

# How the Problems Are Solved

- Extends unit tests for session
- Adds unit tests for other core business logic (oidc, idp, auth etc)

# Additional Changes

- N/A

---------

Co-authored-by: Max Peintner <[email protected]>
2025-11-27 16:55:40 +00:00
33c51deb20 Merge commit from fork
* validate IDP linking permissions

* fix: check policy before linking

* apply suggested review comments

---------

Co-authored-by: Max Peintner <[email protected]>
2025-11-12 13:48:40 +01:00
75791361f3 fix(login): Organization Discovery for Login Without Org Context (#10996)
# Which Problems Are Solved

When users accessed the login page without an organization context and
entered a login name with a domain suffix (e.g., [[email protected]], the
system would return "user not found" instead of performing organization
discovery.

# How the Problems Are Solved

Added organization discovery logic that triggers after a global user
search returns no results. When no organization context is provided:

- Extracts the domain suffix from the loginName (e.g., @company.com)
- Queries for organizations with that domain as their primary domain
- If exactly one organization is found with allowDomainDiscovery
enabled, uses it as the discovered organization
- Redirects users to the appropriate flow (IDP, registration, or
password) with the discovered organization context

---------

Co-authored-by: Ramon <[email protected]>
2025-11-12 13:14:09 +01:00
d7e9eddb76 fix(user): Updating user info when authenticating with external IDP (#11046)
# Which Problems Are Solved

User profile updates were not propagated when using External OIDC IDP +
Login V2

# How the Problems Are Solved

* `UpdateHumanUserRequest` is added to
`RetrieveIdentityProviderIntentResponse`
* `UpdateHumanUserRequest` is returned in the
`RetrieveIdentityProviderIntentResponse` when the user already exists
during external IDP auth, which is then used in the frontend to update
the user info

# Additional Changes

* Moved integration tests related to user intent to a separate test file
* Fix redirection after external IDP user registration

# Additional Context
- Closes #10838 
- Follow up: https://github.com/zitadel/zitadel/issues/11053

---------

Co-authored-by: Max Peintner <[email protected]>
2025-11-10 09:50:36 +01:00
66e04b1dad fix(login): Add default organization fallback for IDP user creation #11025 (#11026)
# Which Problems Are Solved

When users authenticate via IDP (Identity Provider) without explicit
organization context, the flow could fail or create users without proper
organization assignment. This occurred when:

- No organization parameter was provided in the IDP callback
- Domain discovery didn't find a matching organization
- OIDC requests didn't include organization scopes

# How the Problems Are Solved

Implemented a fallback mechanism that ensures organization context is
always available:

- Centralized organization resolution in `resolveOrganizationForUser()`
  - First: Use explicitly provided organization
  - Second: Attempt domain discovery from username
  - Third: Fallback to default organization (NEW)
- Explicit error handling: Users are never created without organization
context. If no organization can be determined (including no default
org), the flow fails gracefully with a clear error message.
- Applied to both creation flows:
  - CASE 4: Auto-creation of users
  - CASE 5: Manual user registration

Co-authored-by: Ramon <[email protected]>
2025-11-04 08:58:41 +01:00
Max PeintnerandGitHub c913904df3 fix(login): idp success url (#10997)
# Which Problems Are Solved

An IDP Intent could not be completed due to a missing change of
successUrl property in a recent PR.

# How the Problems Are Solved

The /success page has been replaced by /process to finish the IDP flow
in all occurences.
2025-10-29 10:54:28 +01:00
Max PeintnerandGitHub fa524e3b05 fix(login): Return promise from passkey authentication to fix automatic prompt (#10991)
# Which Problems Are Solved

The passkey login page was not rendering properly in production (Cloud
Run) deployments, with the submit button and component content not
appearing. Additionally, the automatic passkey prompt was not triggering
correctly.

# How the Problems Are Solved

Added the missing return statement before navigator.credentials.get() in
the submitLoginAndContinue function. This ensures the promise is
properly returned and chained in the useEffect hook, fixing the
automatic passkey prompt flow.

Removes the recently introduces guides to passkeys that could result in
a hydration error due to the <a> tag being rendered differently on
server / client environement

# Additional Changes

This issue was most probably introduced in PR #10971. The component uses
promise chaining (.then().catch().finally()) which requires the promise
to be returned, unlike the RegisterPasskey component which uses
async/await and works correctly without an explicit return.
2025-10-28 12:35:47 +00:00
Max PeintnerandGitHub d5d68aed4b fix(login): Improve Passkey Authentication Error Handling & Testing (#10971)
# Which Problems Are Solved

This PR enhances the passkey authentication flow with comprehensive
error handling, full internationalization support, and extensive test
coverage.

# How the Problems Are Solved

I18n:
- Replaced all hard-coded error messages with i18n translation keys
- Consistent error messaging throughout the passkey flow
- Added specific error handling for passkey cancellation
(NotAllowedError)
- Implemented fallback errors for undefined/missing responses
- Better error messages for:
  - Session retrieval failures
  - Challenge request failures
  - User verification errors
  - Redirect determination issues

Tests:
- Added `login-passkey.test.tsx` with 100+ test cases covering:
  - Successful verification flows
  - Error scenarios and edge cases
  - Props handling
  - Component lifecycle
- Added passkeys.test.ts with server-side function tests:
  - Session cookie retrieval
  - User validation
  - Custom lifetime handling
  - Critical fallback error paths
  
Try-catch blocks around critical user retrieval operations
Defensive checks for undefined responses from completeFlowOrGetUrl
Support for custom lifetime parameters
Cleaner error propagation
2025-10-27 14:38:04 +00:00
9dc127ddb5 fix(login): Prevent double execution of IDP callback token and improve architecture (#10948)
Closes #10828 

# Which Problems Are Solved

The IDP callback flow was calling retrieveIDPIntent() twice, causing
single-use token failures with error: "Intent Token is invalid". This
occurred due to Next.js 15's dynamicIO feature triggering double renders

# How the Problems Are Solved

Completely refactored the IDP callback architecture to ensure single-use
tokens are consumed exactly once:

- Centralized Business Logic: Moved all IDP callback logic into a single
server action (processIDPCallback) that:
   - Consumes the token once
- Handles all 6 business scenarios (login, linking, auto-linking,
auto-creation, manual registration, account not found)
   - Integrates session creation in the same action
- Returns `{ redirect?: string; error?: string }` for client-side
navigation
- Client Component Invocation: Created `IdpProcessHandler` client
component that:
- Calls the server action from browser context (enables cookie
modification)
   - Prevents double execution with useRef
   - Handles loading states and error display
- Clean Architecture:
   - Removed 403-line success page with complex logic
   - Removed component files from `/components/idps/pages/` folder
   - Moved all UI directly into server pages
   - Created dedicated result pages with minimal params

# Additional Changes

- Added translations to all 8 supported languages

---------

Co-authored-by: Ramon <[email protected]>
2025-10-27 14:34:39 +01:00
Max PeintnerandGitHub 5d75e41d00 fix(login): generate code for passkey (#10966)
# Which Problems Are Solved

When the passkey registration page (/passkey/set) is accessed externally
with only a loginName parameter, users encounter a "Missing code in
response" error. This occurs because the registration code is only
generated for invalid sessions, but external calls typically have valid
sessions.

# How the Problems Are Solved

- Moved registration code generation outside the session validity check
in `registerPasskeyLink()`
- Code is now generated for both valid and invalid sessions when not
provided
- Simplified logic: use provided code if available, otherwise generate a
new one
2025-10-27 09:17:01 +00:00
e7ec430dbc feat(i18n): add Turkish translation file (#10922)
Add complete Turkish (tr.json) translation for authentication UI,
including login, registration, password management, MFA setup

# Which Problems Are Solved
- Turkish language support is missing in the authentication UI
- Turkish-speaking users cannot use the application in their native
language

# How the Problems Are Solved
- Added complete Turkish (tr.json) translation file for the
authentication UI
- Translated all authentication-related strings including login,
registration, password management, MFA setup, error messages, and user
verification flows
- Technical terms (Passkey, SSO, LDAP, IDP, etc.) are kept in English
for consistency

# Additional Changes
- None

# Additional Context
- Closes #10851
- This translation follows the same structure as the existing en.json
file
- All user-facing strings in the authentication flow are now available
in Turkish

Co-authored-by: Max Peintner <[email protected]>
Co-authored-by: Gayathri Vijayan <[email protected]>
2025-10-27 08:11:01 +00:00
16b21569db fix(login): improve duration undefined check (#10949)
# Which Problems Are Solved
In the login we often check if a GRPC Duration is not defined however it
can also be set to 0. Using the API it's possible to set the password
check lifetime to zero which broke the login v2.

# How the Problems Are Solved
Also check if the GRPC Duration seconds field is not 0

# Additional Context
- May help if the issue here is actually accidentally setting password
lifetime check to 0 using the API #10865

Co-authored-by: Max Peintner <[email protected]>
2025-10-27 09:03:32 +01:00
b080ed8884 chore: release tarballs (#10956)
# Which Problems Are Solved

This PR makes sure that the tarballs containing the API binary and the
standalone login are separately downloadable from the release pages
again.

# How the Problems Are Solved

Because the `Pack` workflow uploads a single GitHub artifact containing
all tarballs since #10571, we download this artifact so that it
correctly unpacks into the correct folder structure configured in
`.releaserc.js`

The changes are tested [with this action
run](https://github.com/eliobischof/zitadel/actions/runs/18745783976),
which [created this
release](https://github.com/eliobischof/zitadel/releases/tag/v1.0.0-release-archives.5).

# Additional Changes

- The term `standalone` is removed from the login tarball, as it should
be clear that it is a standalone build.
- The go builds and the login archiving are less verbose
- The pipelines go versions are pinned to *v1.25*, a minor above the
minimally required go version *v1.24.0* described in the go.mod file.
This makes sure that we build using newer patches for security and
performance.

# Additional Context

- The archives weren't published anymore since #10571 
- Closes #10896

---------

Co-authored-by: Silvan <[email protected]>
2025-10-23 20:08:24 +02:00
Max PeintnerandGitHub d10be4c09a fix(login): send invite codes only for users with unverified email (#10943)
# Which Problems Are Solved

When a user with no authentication methods attempted to log in, the
system always set `invite=true` in the verification flow, regardless of
whether their email was already verified. This could cause errors when
trying to send invite codes to already initialized users.

# How the Problems Are Solved

Added conditional logic to determine whether to send an invite code
based on the user's email verification status:

This prevents errors when attempting to send invite codes to users who
have already verified their email and been initialized, while still
properly handling new users who need invitation flows.
2025-10-21 13:44:31 +00:00
ff869482b1 fix(login): fallback for idp login (#10876)
Closes #10671

# Which Problems Are Solved

Users with password authentication disabled in their organization were
seeing "Username Password not allowed!" error instead of being
redirected to their organization's configured Identity Provider. This
affected domain discovery and multi-tenancy use cases in Login V2.

# How the Problems Are Solved

- Updated `redirectUserToIDP` to accept optional `userId` and
`organization` parameters
- Added fallback logic to check organization-level IDPs via
`getActiveIdentityProviders`
- Updated all call sites to pass appropriate organization context
- Added test coverage for the fallback behavior

# Additional Changes

- Consolidated duplicate logic by removing
`redirectUserToSingleIDPIfAvailable` function, which is now handled by
the unified `redirectUserToIDP` function
- improved error handling on verification page

---------

Co-authored-by: Ramon <[email protected]>
2025-10-21 11:04:33 +02:00
Max PeintnerandGitHub 2ad5cf141f fix(login): Add Organization Scoping to IDP Auto-Linking (#10931)
This PR fixes an issue in the IDP auto-linking feature where user
searches were performed globally instead of being scoped to the current
organization context. This could result in IDP links being created for
users in unintended organizations.

# Which Problems Are Solved

When IDP auto-linking was enabled (by email or username), the system
would search for existing users across all organizations instead of
restricting the search to the current organization context.

# How the Problems Are Solved

Added organization scoping to all three auto-linking code paths
2025-10-21 10:56:34 +02:00
27c248fa11 feat(login): add Japanese localization for login frontend app (#10811)
<!--
Please inform yourself about the contribution guidelines on submitting a
PR here:
https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#submit-a-pull-request-pr.
Take note of how PR/commit titles should be written and replace the
template texts in the sections below. Don't remove any of the sections.
It is important that the commit history clearly shows what is changed
and why.
Important: By submitting a contribution you agree to the terms from our
Licensing Policy as described here:
https://github.com/zitadel/zitadel/blob/main/LICENSING.md#community-contributions.
-->

# Which Problems Are Solved

- Japanese users cannot use the Login UI in their native language, as
only other locales (English, German, Italian, Spanish, Polish, Chinese,
Russian, Turkish) are currently supported
- The Login UI language selection does not include Japanese as an option

# How the Problems Are Solved

- Updated the `LANGS` array in `apps/login/src/lib/i18n.ts` to include
Japanese (`{ name: "日本語", code: "ja" }`)
- Enables Japanese language selection in the Login UI through browser
language detection or manual locale setting

# Additional Changes

- No additional changes were necessary as other components (Console,
email notifications, common messages, Go templates) already have
Japanese locale support (`ja.json`/`ja.yaml` files exist)

# Additional Context

- This contribution enhances ZITADEL's internationalization support for
Japanese-speaking users
- The translation follows the same structure and key naming conventions
as existing locale files
- Testing can be performed by setting browser language to Japanese or
using `NEXT_LOCALE=ja` cookie

Co-authored-by: Max Peintner <[email protected]>
2025-10-17 14:37:37 +02:00
Max PeintnerandGitHub 00beaf6ddc fix(login): provide a postError redirect url for idp flows (#10883)
# Which Problems Are Solved

Improves the user experience when IDP authentication succeeds but user
creation/linking fails by introducing a `postErrorRedirectUrl` parameter
and dedicated error pages instead of generic error screens.

<img width="580" height="636" alt="Screenshot 2025-10-16 at 09 21 07"
src="https://github.com/user-attachments/assets/db653c8f-b648-4cfe-922a-2f237f3b70b3"
/>

# How the Problems Are Solved

## New Pages
- **`/idp/[provider]/account-not-found`**: Displayed when no user
account exists and creation/linking is not allowed
- **`/idp/[provider]/registration-failed`**: Displayed when user
registration fails due to organization resolution issues

## Flow Improvements
- Added `postErrorRedirectUrl` parameter to track where the IDP flow was
initiated
- Each entry point (loginname, register, idp, authenticator/set)
specifies its own redirect URL
- Users are now redirected to appropriate error pages with clear
messaging instead of generic error screens
- All context (`requestId`, `organization`, `postErrorRedirectUrl`) is
preserved throughout the flow

## Updated Components
- `SignInWithIdp`: Now accepts and passes `postErrorRedirectUrl`
parameter
- `redirectToIdp` server action: Extracts and forwards
`postErrorRedirectUrl` through the IDP flow
- IDP success page: Routes to appropriate error pages based on failure
reason

## i18n
Added new translation keys:
- `idp.accountNotFound.*` - For missing account scenarios
- `idp.registrationFailed.*` - For organization resolution failures
2025-10-16 11:24:54 +02:00
19b744ca67 fix(login): use default titles for password pages (#10904)
# Which Problems Are Solved

This change shows the default titles for password pages instead of
dynamically showing the user name.

# How the Problems Are Solved

Both pages now show only the translated title text (verify.title and
change.title respectively) instead of falling back to showing the user's
display name.

Co-authored-by: Livio Spring <[email protected]>
2025-10-16 07:22:27 +02:00
Livio SpringandGitHub 53dcd0eb0a fix(login): ensure css is served (#10894)
# Which Problems Are Solved

The newest release (v4.3.2) was not serving the `zitadel.css` for the
login anymore. The previous file was served from cache, making it not
directly visible.
The problem was caused due to the CI change (#10571) where the generate
was moved from a makefile to Nx commands, which run in parallel.
Depending on timing, the generated css file might be embedded into the
login or not.

# How the Problems Are Solved

- Configure the commands to run sequentially.

# Additional Changes

none

# Additional Context

- relates to #10571 
- requires backport to v4.x
2025-10-13 06:58:54 +00:00
Elio BischofandGitHub 5aa2ca58ca chore: fix vercel build (#10887)
# Which Problems Are Solved

By default, the login redirects in all cases from its
`NEXT_PUBLIC_BASE_PATH` to `NEXT_PUBLIC_BASE_PATH/loginname` now. This
is the expected behavior.

# How the Problems Are Solved

Deployments to Vercel use the `apps/login/.env` file for their defaults.
As the .env file had DEBUG=true, redirects from root to ./loginname were
disabled.
DEBUG=true is not needed anywhere, so it's deleted from the .env file.
2025-10-10 13:38:10 +00:00
Livio SpringandGitHub e742d649c8 chore(ci): fix release (#10886)
# Which Problems Are Solved

The new pipeline did not correctly build the release. Console was not
built into the binary. Also there were some pipeline permission errors.

# How the Problems Are Solved

- add `build-console` as dependency to pack binaries
- streamline permissions and only pass necessary into steps

# Additional Changes

none

# Additional Context

- relates to #10571
2025-10-10 13:16:20 +00:00
Max PeintnerandGitHub 434aeb275a feat(login): comprehensive theme system (#10848)
# Which Problems Are Solved

This PR introduces a comprehensive theme customization system for the
login application with responsive behavior and enhanced visual options.

<img width="1122" height="578" alt="Screenshot 2025-08-19 at 09 55 24"
src="https://github.com/user-attachments/assets/cdcc8948-533d-4e13-bf45-fdcc24acfb2b"
/>

# How the Problems Are Solved

## ✨ Features Added

- **🔄 Responsive Layout System**: Automatic switching between
side-by-side and top-to-bottom layouts based on screen size
- **🖼️ Background Image Support**: Custom background images configurable
via environment variables
- **⚙️ Theme Configuration**: Complete theme system with roundness,
spacing, appearance, and layout options
- **📱 Mobile-First Design**: Intelligent layout adaptation for different
screen sizes
- **🎯 Enhanced Typography**: Improved visual hierarchy with larger
titles in side-by-side mode

## 🏗️ Architecture

- **Server-Safe Theme Functions**: Theme configuration accessible on
both server and client
- **SSR-Safe Hooks**: Proper hydration handling for responsive layouts
- **Component Separation**: Clear boundaries between server and client
components
- **Two-Section Layout**: Consistent content structure across all login
pages

## 🔧 Configuration Options

All theme options are configurable via environment variables:

- `NEXT_PUBLIC_THEME_ROUNDNESS`: `edgy` | `mid` | `full`
- `NEXT_PUBLIC_THEME_LAYOUT`: `side-by-side` | `top-to-bottom`
- `NEXT_PUBLIC_THEME_APPEARANCE`: `flat` | `material`
- `NEXT_PUBLIC_THEME_SPACING`: `regular` | `compact`
- `NEXT_PUBLIC_THEME_BACKGROUND_IMAGE`: Custom background image URL

## 📄 Pages Updated

Updated all major login pages to use the new two-section responsive
layout:
- Login name entry
- Password verification
- MFA verification
- User registration
- Account selection
- Device authorization
- Logout confirmation

## 📚 Documentation

- **THEME_ARCHITECTURE.md**: Complete technical documentation of the
theme system
- **THEME_CUSTOMIZATION.md**: User-friendly guide with examples and
troubleshooting

## 🚀 Benefits

- **Better UX**: Responsive design that works seamlessly across all
devices
- **Brand Flexibility**: Easy customization to match any brand identity
- **Maintainable Code**: Clean separation of concerns and
well-documented architecture
- **Future-Proof**: Extensible system for additional theme options


<img width="580" height="680" alt="Screenshot 2025-08-19 at 09 22 23"
src="https://github.com/user-attachments/assets/9de8da37-6d56-4fe9-b337-5d8ad2a3ba59"
/>
<img width="599" height="689" alt="Screenshot 2025-08-19 at 09 23 45"
src="https://github.com/user-attachments/assets/26a30cc7-4017-4f4b-8b87-a49466c42b94"
/>
<img width="595" height="681" alt="Screenshot 2025-08-19 at 09 23 17"
src="https://github.com/user-attachments/assets/a3d31088-4545-4f36-aafe-1aae1253d677"
/>
2025-10-10 10:26:06 +02:00
Elio BischofandGitHub 7ba6870baf feat: await initial database connection (#10869)
# Which Problems Are Solved

When Postgres was not ready when the API was started, the API failed
immediately.
This made task orchestration hard, especially in a platform agnostic
way:

- The current health check in the Nx target `@zitadel/api:prod` uses the
timeout command, which is not installed on all platforms and behaves
unpredictably
- The current health check in the Nx target `@zitadel/api:prod` requires
the DB to have been started using `@zitadel/zitadel:db`

# How the Problems Are Solved

- Additional configuration option `Database.Postgres.AwaitInitialConn`
is added and defaults to *0m* for backwards compatibility.
- If a duration is configured, the API retries to ping the database
until it succeeds
- The API sleeps for a second between each ping.
- It emits an info-level log with the error on each try.
- When the configured duration times out before the ping is successful,
the error is returned and the command exits with a failure code.
- When the ping succeeds within the configured duration, the API goes on
with the init, setup or start phase.

# Additional Context

- Relates to internally reported problems with the current DB health
check command
[here](https://zitadel.slack.com/archives/C07EUL5H83A/p1759915009839269?thread_ts=1759912259.410789&cid=C07EUL5H83A)
and
[here](https://zitadel.slack.com/archives/C07EUL5H83A/p1759918324246249?thread_ts=1759912259.410789&cid=C07EUL5H83A).
2025-10-09 11:18:34 +00:00
64e14de091 feat(login): translations (#10849)
# Which Problems Are Solved

Replace this example text with a concise list of problems that this PR
solves.
For example:
- password complexity requirements have hardcoded English text
- password, loginname, register and verify components have hardcoded
Engilsh error messages/alerts

# How the Problems Are Solved

Replace this example text with a concise list of changes that this PR
introduces.
For example:
- adds i18n for password complexity requirements
- adds i18n for password, loginname, register and verify components
error messages/alerts

# Additional Changes

- small change in code/styles for icons in PasswordComplexity to make
sure that icons keep size

# Additional Context

N.A

---------

Co-authored-by: Adam Kida <[email protected]>
2025-10-09 11:11:03 +02:00
794054c075 fix(login): fix translation key typo for logout.verifiedAt (#10504)
# Which Problems Are Solved

- login UI was complaining about a missing translation key:
```
Error: MISSING_MESSAGE: logout.verfiedAt (en)
zitadel-login-1               |     at t (.next/server/chunks/1119.js:3:8993)
zitadel-login-1               |     at u (.next/server/chunks/1119.js:3:9149)
zitadel-login-1               |     at v (.next/server/chunks/1119.js:3:10482)
zitadel-login-1               |     at f (.next/server/chunks/2293.js:1:10127) {
zitadel-login-1               |   code: 'MISSING_MESSAGE',
zitadel-login-1               |   originalMessage: 'logout.verfiedAt (en)'
zitadel-login-1               | }
```

# How the Problems Are Solved

- fixes a typo in the translation key name

# Additional Changes

None.

# Additional Context

None.

Co-authored-by: Max Peintner <[email protected]>
Co-authored-by: Ramon <[email protected]>
2025-10-09 08:59:22 +00:00
3b0ad1e9b6 fix(login): serve UI on both IPv4 and IPv6 (#10554)
# Which Problems Are Solved

Currently, the HTTP server is listening on IPv4 only.

# How the Problems Are Solved

This PR makes it listen on IPv4 and IPv6.

Co-authored-by: Elio Bischof <[email protected]>
2025-10-08 23:56:43 +02:00
f69a6ed4f3 chore: rehaul DevX (#10571)
# Which Problems Are Solved

Replaces Turbo by Nx and lays the foundation for the next CI
improvements. It enables using Nx Cloud to speed the up the pipelines
that affect any node package.
It streamlines the dev experience for frontend and backend developers by
providing the following commands:

| Task | Command | Notes |
|------|---------|--------|
| **Production** | `nx run PROJECT:prod` | Production server |
| **Develop** | `nx run PROJECT:dev` | Hot reloading development server
|
| **Test** | `nx run PROJECT:test` | Run all tests |
| **Lint** | `nx run PROJECT:lint` | Check code style |
| **Lint Fix** | `nx run PROJECT:lint-fix` | Auto-fix style issues |

The following values can be used for PROJECT:

- @zitadel/zitadel (root commands)
- @zitadel/api,
- @zitadel/login,
- @zitadel/console,
- @zitadel/docs,
- @zitadel/client
- @zitadel/proto

The project names and folders are streamlined:

| Old Folder | New Folder |
| --- | --- |
| ./e2e | ./tests/functional-ui |
| ./load-test | ./benchmark |
| ./build/zitadel | ./apps/api |
| ./console | ./apps/console (postponed so the PR is reviewable) |  

Also, all references to the TypeScript repo are removed so we can
archive it.

# How the Problems Are Solved

- Ran `npx nx@latest init`
- Replaced all turbo.json by project.json and fixed the target configs
- Removed Turbo dependency
- All JavaScript related code affected by a PRs changes is
quality-checked using the `nx affected` command
- We move PR checks that are runnable using Nx into the `check`
workflow. For workflows where we don't use Nx, yet, we restore
previously built dependency artifacts from Nx.
- We only use a single and easy to understand dev container
- The CONTRIBUTING.md is streamlined
- The setup with a generated client pat is orchestrated with Nx
- Everything related to the TypeScript repo is updated or removed. A
**Deploy with Vercel** button is added to the docs and the
CONTRIBUTING.md.

# Additional Changes

- NPM package names have a consistent pattern.
- Docker bake is removed. The login container is built and released like
the core container.
- The integration tests build the login container before running, so
they don't rely on the login container action anymore. This fixes
consistently failing checks on PRs from forks.
- The docs build in GitHub actions is removed, as we already build on
Vercel.

# Additional Context

- Internal discussion:
https://zitadel.slack.com/archives/C087ADF8LRX/p1756277884928169
- Workflow dispatch test:
https://github.com/zitadel/zitadel/actions/runs/17760122959

---------

Co-authored-by: Florian Forster <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
Co-authored-by: Copilot <[email protected]>
2025-10-08 10:27:02 +02:00
Max PeintnerandGitHub 695db96745 fix(login): Redirect to IDP flow when password auth is disabled (#10839)
Closes #10671

# Which Problems Are Solved

Users with only password authentication method were immediately shown an
error "Username Password not allowed" when
`loginSettings.allowUsernamePassword` was set to false. However, the IDP
flow could potentially allow the user to register a new account or link
an existing account, providing a better user experience than a dead-end
error.

# How the Problems Are Solved

- Modified single password method case to attempt IDP redirect before
showing error
- This allows users to potentially register or link accounts through the
IDP flow instead of hitting an immediate error
- Only show error as last resort when no IDP alternative is available
2025-10-07 05:47:58 +00:00
Tim MöhlmannandGitHub a45908b364 feat(rt): project repository (#10789)
# Which Problems Are Solved

Add projects to the relational tables

# How the Problems Are Solved

- Define table migrations
- Define and implement Project and Project Role repositories.
- Provide projection handlers to populate the relational tables.

# Additional Changes

- Statement Builder now has a constructor which allows setting of a base
query with arguments.
- Certain operations, like Get, Update and Delete require the Primary
Key to be set as conditions. However, this requires knowledge of the
implementation and table definition. This PR proposes an additional
condition for repositories: `PrimaryKeyCondition`. This gives clarity on
the required IDs for these operations.
- Added couple of helpers to the repository package, to allow more DRY
code.
- getOne / getMany: generic functions for query execution and scanning.
- checkRestrictingColumns, checkPkCondition: simplify condition
checking, instead of using ladders of conditionals.
- Added a couple of helpers to the repository test package:
  - Transaction, savepoint and rollback helpers.
- Create instance and organization helpers for objects that depend on
them (like projects).

# Additional Context

- after https://github.com/zitadel/zitadel/pull/10809
- closes #10765
2025-10-01 09:47:04 +00:00
Max PeintnerandGitHub 28db24fa67 fix(login): Organization domain scope, Support for External Passkey Registration (#10729)
Closes #10727
Closes #10577

# Which Problems Are Solved

This PR fixes the organization domain scope when provided and introduces
a deep-link feature for external applications, that sends users directly
into passkey registration flow using either session-based or sessionless
flows. Previously, the `/passkey/set` page only supported session-based
registration, limiting external application integration scenarios.

The `/passkey/set` page now supports:
- `code` search parameter for automatic passkey registration
- `userId` parameter for sessionless flows (similar to `/verify` and
`/password/set` pages)
- Auto-submit functionality when verification codes are provided

# How the Problems Are Solved

The organization scope is fixed by the backend handler for OIDC flows,
now correctly submitting a `suffix` queryparam to the /loginname url
which is used to show in the input field.

The passkey code support is implemented by support multiple integration
patterns:
- **Session-based**: `/passkey/set?sessionId=123&code=abc123` (existing
flow)
- **Sessionless**: `/passkey/set?userId=123456&code=abc123` (new flow)

External Application Integration Flow
1. External app triggers passkey register and obtains code
2. User verification link containing `userId`, `code` and `id`
parameters
3. User clicks link → `/passkey/set?userId=123&code=abc&id=123`
4. Page loads user information using `userId` parameter
5. Auto-submit triggers passkey registration when `code` and `id` is
present
6. User completes WebAuthn request
7. Passkey is registered and user continues authentication flow

This enables external applications to seamlessly integrate passkey
registration into their user onboarding
2025-09-30 17:58:32 +02:00
Max PeintnerandGitHub 09d09ab337 fix(login): host utility to provide correct host behind proxies (#10770)
<!--
Please inform yourself about the contribution guidelines on submitting a
PR here:
https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#submit-a-pull-request-pr.
Take note of how PR/commit titles should be written and replace the
template texts in the sections below. Don't remove any of the sections.
It is important that the commit history clearly shows what is changed
and why.
Important: By submitting a contribution you agree to the terms from our
Licensing Policy as described here:
https://github.com/zitadel/zitadel/blob/main/LICENSING.md#community-contributions.
-->

# Which Problems Are Solved

When deploying the login application behind proxies or using Vercel
rewrites (e.g., `zitadel.com/login` → `login-zitadel-qa.vercel.app`),
the application was using the internal rewritten host instead of the
original user-facing host. This caused several issues:

1. **Broken Password Reset Emails**: Email links contained internal
hosts like `login-zitadel-qa.vercel.app` instead of `zitadel.com`
2. **Inconsistent User Experience**: Users would see different domains
in various parts of the flow
3. **Security Concerns**: Internal infrastructure details were exposed
to end users
4. **Scattered Logic**: Host detection logic was duplicated across
multiple files with inconsistent error handling

# How the Problems Are Solved

Created comprehensive host detection utilities in `/lib/server/host.ts`
and `/lib/client/host.ts`:

**Server-side utilities:**
- `getOriginalHost()` - Returns the original user-facing host
- `getOriginalHostWithProtocol()` - Returns host with proper protocol
(http/https)
2025-09-23 16:21:01 +00:00
Max PeintnerandGitHub 637b370c17 chore(login): Extract auth flow utilities and eliminate RSC request interference (#10644)
The /login route was experiencing issues with React Server Component
(RSC) requests interfering with one-time authentication callbacks. When
users navigated to /login via client-side routing (router.push()),
Next.js automatically triggered _rsc requests that could consume
single-use createCallback tokens, breaking OIDC and SAML authentication
flows.

# Which Problems Are Solved

When users attempt to log in, Next.js automatically makes requests with
the `_rsc=1` query parameter for React Server Components. The current
implementation treats these as server errors:

```typescript
// Before
if (_rsc) {
  return NextResponse.json({ error: "No _rsc supported" }, { status: 500 });
}
```

This results in:
- Spurious 500 error logs polluting monitoring systems
- False alerts for server failures 
- Difficulty distinguishing real issues from benign RSC requests

# How the Problems Are Solved

This PR implements a comprehensive refactoring that:

- Eliminates RSC interference by providing server actions for internal
auth flow completion
- Separates concerns between external flow initiation and internal flow
completion
- Extracts shared utilities to improve code maintainability and
reusability
- Maintains full backward compatibility for external applications

# Additional Context

## New Architecture
- auth-flow.ts: Shared utilities for auth flow completion with RSC
protection
- flow-initiation.ts: Extracted OIDC/SAML flow initiation logic (~400
lines)
- auth.ts: Server actions for internal components

## Route Handler Simplification
- route.ts: Reduced from ~350 lines to ~75 lines
- External-only focus: Now handles only flow initiation for external
applications
- Removed completion logic: External apps use their own callback URLs
- Enhanced validation: Early RSC blocking and parameter validation

## Flow Logic Improvements
- Early return patterns: Guard clauses eliminate deep nesting
- Better error handling: Specific error messages for different failure
modes
- Fixed SAML flow: Addressed incomplete logic
- Consistent session handling: Unified approach across OIDC and SAML
2025-09-22 16:09:20 +00:00
Max PeintnerandGitHub 0a31f4ba2b fix(login): remove image optimization entirely (#10702)
This PR completely removes Next.js image optimization from the login app
by replacing all next/image components with standard HTML <img> tags and
removing the image optimization configuration.

Closes https://github.com/zitadel/zitadel-charts/issues/381

# Which Problems Are Solved

Users were encountering issue when loading images in dedicated
environments. These happened due to nextjs imaging optimizations
creating different paths for images.

# How the Problems Are Solved

- Removed Next.js Image Optimization Config
- Removed images: { unoptimized: true } configuration from
[next.config.mjs](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
This config was redundant since we no longer use next/image components
- Replaced next/image with standard <img> tags
2025-09-22 11:49:21 +00:00
Max PeintnerandGitHub a9cd3ff9c0 fix(login): Safari Cookie Issues in Development Mode (#10594)
Safari was not creating session cookies during local development,
causing authentication failures. This was due to nextjs default setting
of SameSite cookie property.
We explicitly set "strict" for session cookies now.

Closes #10473 

# Which Problems Are Solved

Authentication Issues with Safari in local development

# How the Problems Are Solved

- Cleaner API: Replaced confusing sameSite boolean/string parameters
with iFrameEnabled boolean
- Better logic flow:

iFrameEnabled: true → sameSite: "none" (for iframe embedding)
Production → sameSite: "strict" (maximum security)
2025-09-11 15:01:24 +00:00
Max PeintnerandGitHub 1a42e99329 chore(login): Remove Vercel Analytics from login application (#10701)
This PR removes the Vercel Analytics integration from the login
application to reduce external dependencies and improve privacy.

# Which Problems Are Solved

cleaner csp

# How the Problems Are Solved

- Removed dependency: Uninstalled @vercel/analytics package from
package.json
- Updated layout component: Removed Analytics import and component usage
from layout.tsx
- Updated Content Security Policy: Removed Vercel domains
(https://va.vercel-scripts.com and https://vercel.com) from CSP
configuration in csp.js
2025-09-11 12:10:09 +00:00