* fix(authn): include base path in SSO callback and error-redirect URLs
The SAML ACS URL and the OIDC/Google redirect URLs were built from the
site URL host plus a hardcoded path (e.g. /api/v1/complete/saml), dropping
the base path. When SigNoz is served under a sub-path (global.external_url
with a path, e.g. https://example.com/signoz), the API is served at
<prefix>/api/v1/complete/<provider>, so the identity provider was told to
call back to a path without the prefix and hit a 404.
Thread global.Config into the SAML/OIDC/Google callback providers and the
session handler, and prepend global.Config.ExternalPath() to the callback
paths and the SSO error redirect to /login. Root deployments are
unchanged since ExternalPath() returns "" without a configured sub-path.
* fix(authn): run callbackauthn suite with base path
* refactor(tests): self-contained base-path fixture for callbackauthn
Move the base-path setup out of the shared create_signoz factory and into
a package-scoped signoz fixture in the callbackauthn suite's own conftest
(same pattern as rootuser/conftest.py). When --base-path is set the fixture
appends SIGNOZ_GLOBAL_EXTERNAL__URL and the url-config prefix locally;
without it it behaves exactly like the global fixture. The shared factory
and docker config are left untouched.
* test(authn): add base-path SSO integration suite
Adds a dedicated `basepath` integration suite that serves SigNoz under a
hardcoded /signoz prefix (SIGNOZ_GLOBAL_EXTERNAL__URL) and exercises the SAML
and OIDC happy-path logins end-to-end. Every SigNoz API call is issued under
the prefix and the IdP callback (ACS / redirect URI) is registered with the
prefix, so the flow only passes when the backend builds prefixed callback URLs.
The shared TestContainerUrlConfig and create_signoz factory are left untouched.
The suite's conftest shadows the same-named auth fixtures (create_user_admin,
get_token, get_session_context, apply_license) with base-path-aware variants and
reuses the Keycloak/browser fixtures, which are not under the base path.
Google SSO is not covered: it requires the real accounts.google.com issuer and
a real Google login, so it cannot run against the local Keycloak IdP; it shares
the identical path.Join(ExternalPath, redirectPath) callback logic that SAML
and OIDC validate.
* revert: drop in-place base-path wiring from integration harness
Removes the --base-path flag, TestContainerUrlConfig.base_path, the idp.py and
02_saml.py .get() changes, and the callbackauthn base-path conftest fixture.
Base-path SSO is now covered by the dedicated `basepath` suite, so the shared
harness (TestContainerUrlConfig, create_signoz, callbackauthn) is back to its
original root-only form.
* refactor(test): remove apply_license fixture
* refactor(test): extract base-path-aware auth factories
Extract the session-context / token / token-pair / admin-registration logic
in fixtures/auth.py into reusable factory functions that take an optional
base_path (token_getter, session_context_getter, tokens_getter, register_admin),
with the fixtures delegating to them. Default base_path="" is byte-identical for
existing callers.
The basepath suite's conftest now reuses these factories with the /signoz prefix
as thin one-line fixture overrides instead of duplicating the request logic.
* refactor(test): give base-path admin registration a distinct cache key
register_admin takes an optional cache_key (default "create_user_admin"); the
basepath suite passes a distinct key so that under --reuse the admin marker
cached against the signoz-base-path container is not restored for (or from)
other suites' default signoz instance.
* feat(serviceaccount): integrate service account
* feat(serviceaccount): integrate service account with better types
* feat(serviceaccount): fix lint and testing changes
* feat(serviceaccount): update integration tests
* feat(serviceaccount): fix formatting
* feat(serviceaccount): fix openapi spec
* feat(serviceaccount): update txlock to immediate to avoid busy snapshot errors
* feat(serviceaccount): add restrictions for factor_api_key
* feat(serviceaccount): add restrictions for factor_api_key
* feat: enabled service account and deprecated API Keys (#10715)
* feat: enabled service account and deprecated API Keys
* feat: deprecated API Keys
* feat: service account spec updates and role management changes
* feat: updated the error component for roles management
* feat: updated test case
* feat: updated the error component and added retries
* feat: refactored code and added retry to happend 3 times total
* feat: fixed feedbacks and added test case
* feat: refactored code and removed retry
* feat: updated the test cases
---------
Co-authored-by: SagarRajput-7 <162284829+SagarRajput-7@users.noreply.github.com>
* feat: user v2 apis
* fix: openapi specs
* chore: address review comments
* fix: proper handling if invalid roles are passed
* chore: address review comments
* refactor: frontend to use deprecated apis after id rename
* feat: separate apis for adding and deleting user role
* fix: invalidate token when roles are updated
* fix: openapi specs and frontend test
* fix: openapi schema
* fix: openapi spec and move to snakecasing for json
* feat: introduce user_role table
* fix: golint and register migrations
* fix: user types and order of update user
* feat: add migration to drop role column from users table
* fix: raw queries pointing to role column in users table
* chore: remove storable user struct and minor other changes
* chore: remove refs of calling vars as storable users
* chore: user 0th role instead of highest
* chore: address pr comments
* chore: rename userrolestore to user_role_store
* chore: return userroles with user in getter where possible
* chore: move user module as user setter
* chore: arrange getter and setter methods
* fix: nil pointer for update user in integration test due to half payload being passed
* chore: update openapi specs
* fix: nil errors without making frontend changes
* fix: empty array check everywhere for user roles array and minor other changes
* fix: imports
* fix: rebase changes
* chore: renaming functions
* chore: simplified getorcreateuser user setter method and call sites
* fix: golint
* fix: remove redundant authz migration, remove fk enforcement for drop migration
* fix: add new event for user activation
* feat(instrumentation): add OTel exception semantic convention log handler
Add a loghandler.Wrapper that enriches error log records with OpenTelemetry
exception semantic convention attributes (exception.type, exception.code,
exception.message, exception.stacktrace).
- Add errors.Attr() helper for standardized error logging under "exception" key
- Add exception log handler that replaces raw error attrs with structured group
- Wire exception handler into the instrumentation SDK logger chain
- Remove LogValue() from errors.base as the handler now owns structuring
* refactor: replace "error", err with errors.Attr(err) across codebase
Migrate all slog error logging from ad-hoc "error", err key-value pairs
to the standardized errors.Attr(err) helper, enabling the exception log
handler to enrich these logs with OTel semantic convention attributes.
* refactor: enforce attr-only slog style across codebase
Change sloglint from kv-only to attr-only, requiring all slog calls to
use typed attributes (slog.String, slog.Any, etc.) instead of key-value
pairs. Convert all existing kv-style slog calls in non-excluded paths.
* refactor: tighten slog.Any to specific types and standardize error attrs
- Replace slog.Any with slog.String for string values (action, key, where_clause)
- Replace slog.Any with slog.Uint64 for uint64 values (start, end, step, etc.)
- Replace slog.Any("err", err) with errors.Attr(err) in dispatcher and segment analytics
- Replace slog.Any("error", ctx.Err()) with errors.Attr in factory registry
* fix(instrumentation): use Unwrapb message for exception.message
Use the explicit error message (m) from Unwrapb instead of
foundErr.Error(), which resolves to the inner cause's message
for wrapped errors.
* feat(errors): capture stacktrace at error creation time
Store program counters ([]uintptr) in base errors at creation time
using runtime.Callers, inspired by thanos-io/thanos/pkg/errors. The
exception log handler reads the stacktrace from the error instead of
capturing at log time, showing where the error originated.
* fix(instrumentation): apply default log wrappers uniformly in NewLogger
Move correlation, filtering, and exception wrappers into NewLogger so
all call sites (including CLI loggers in cmd/) get them automatically.
* refactor(instrumentation): remove variadic wrappers from NewLogger
NewLogger no longer accepts arbitrary wrappers. The core wrappers
(correlation, filtering, exception) are hardcoded, preventing callers
from accidentally duplicating behavior.
* refactor: migrate remaining "error", <var> to errors.Attr across legacy paths
Replace all remaining "error", <variable> key-value pairs with
errors.Attr(<variable>) in pkg/query-service/ and ee/query-service/
paths that were missed in the initial migration due to non-standard
variable names (res.Err, filterErr, apiErrorObj.Err, etc).
* refactor(instrumentation): use flat exception.* keys instead of nested group
Use flat keys (exception.type, exception.code, exception.message,
exception.stacktrace) instead of a nested slog.Group in the exception
log handler.
* feat: deprecate user invite table
* fix: handle soft deleted users flow
* fix: handle edge cases for authentication and reset password flow
* feat: integration tests with fixes for new flow
* fix: array for grants
* fix: edge cases for reset token and context api
* chore: remove all code related to old invite flow
* fix: openapi specs
* fix: integration tests and minor naming change
* fix: integration tests fmtlint
* feat: improve invitation email template
* fix: role tests
* fix: context api
* fix: openapi frontend
* chore: rename countbyorgid to activecountbyorgid
* fix: a deleted user cannot recycled, creating a new one
* feat: migrate existing invites to user as pending invite status
* fix: error from GetUsersByEmailAndOrgID
* feat: add backward compatibility to existing apis using new invite flow
* chore: change ordering of apis in server
* chore: change ordering of apis in server
* fix: filter active users in role and org id check
* fix: check deleted user in reset password flow
* chore: address some review comments, add back countbyorgid method
* chore: move to bulk inserts for migrating existing invites
* fix: wrap funcs to transactions, and fix openapi specs
* fix: move reset link method to types, also move authz grants outside transation
* fix: transaction issues
* feat: helper method ErrIfDeleted for user
* fix: error code for errifdeleted in user
* fix: soft delete store method
* fix: password authn tests also add old invite flow test
* fix: callbackauthn tests
* fix: remove extra oidc tests
* fix: callback authn tests oidc
* chore: address review comments and optimise bulk invite api
* fix: use db ctx in various places
* fix: fix duplicate email invite issue and add partial invite
* fix: openapi specs
* fix: errifpending
* fix: user status persistence
* fix: edge cases
* chore: add tests for partial index too
* feat: use composite unique index on users table instead of partial one
* chore: move duplicate email check to unmarshaljson and query user again in accept invite
* fix: make 068 migratin idempotent
* chore: remove unused emails var
* chore: add a temp filter to show only active users in frontend until next frontend fix
* chore: remove one check from register flow testing until temp code is removed
* chore: remove commented code from tests
* chore: address frontend review comments
* chore: address frontend review comments
## Summary
- Adds root user support with environment-based provisioning, protection guards, and automatic reconciliation. A root user is a special admin user that is provisioned via configuration (environment variables) rather than the UI, designed for automated/headless deployments.
## Key Features
- Environment-based provisioning: Configure root user via user.root.enabled, user.root.email, user.root.password, and user.root.org_name settings
- Automatic reconciliation: A background service runs on startup that:
- Looks up the organization by configured org_name
- If no matching org exists, creates the organization and root user via CreateFirstUser
- If the org exists, reconciles the root user (creates, promotes existing user, or updates email/password to match config)
- Retries every 10 seconds until successful
- Protection guards: Root users cannot be:
- Updated or deleted through the API
- Invited or have their password changed through the UI
- Authenticated via SSO/SAML (password-only authentication enforced)
- Self-registration disabled: When root user provisioning is enabled, the self-registration endpoint (/register) is blocked to prevent creating duplicate organizations
- Idempotent password sync: On every reconciliation, the root user's password is synced with the configured value — if it differs, it's updated; if it matches, no-op
## 📄 Summary
- Instead of relying on JWT for session management, we are adding another token system: opaque. This gives the benefits of expiration and revocation.
- We are now ensuring that emails are regex checked throughout the backend.
- Support has been added for OIDC protocol