Skip to content

Authentication

OAuth2 authentication base classes and client implementation.

Auth Base

Authentication provider framework base classes and mixins

Implement custom auth providers by subclassing BaseAuthProvider and, where appropriate, implementing the HTTPHeadersMixin to supply HTTP headers and LoginLogoutMixin for interactive flows. Optional TokenMixin defines a canonical way to expose tokens.

Creating a custom provider (example)::

from typing import Dict, Any
from qlam_core.auth.base import BaseAuthProvider, HTTPHeadersMixin, LoginLogoutMixin


class MyTokenProvider(BaseAuthProvider, HTTPHeadersMixin, LoginLogoutMixin):
    name = "mytoken"  # used by registry

    def __init__(self, context_name: str, token: str | None = None) -> None:
        # Expose `context_name` publicly: AuthClient uses it to scope
        # registered-provider reuse to the owning context.
        self.context_name = context_name
        self._token = token

    def is_authenticated(self) -> bool:
        return bool(self._token)

    def get_auth_context(self) -> JsonDict:
        return {"context": self.context_name, "has_token": self.is_authenticated()}

    def get_headers(self) -> Dict[str, str]:
        return {"Authorization": f"Bearer {self._token}"} if self._token else {}

    def login(self) -> None:
        # Implement a real flow; for example, prompt the user or exchange credentials
        self._token = "...obtained..."

Registering the provider:

  • Either rely on dynamic discovery in qlam_core.auth.registry if placed under qlam_core.auth.providers, or call auth_registry.register_factory("mytoken", factory).

BaseAuthProvider

Bases: ABC


              flowchart TD
              qlam_core.auth.base.BaseAuthProvider[BaseAuthProvider]

              

              click qlam_core.auth.base.BaseAuthProvider href "" "qlam_core.auth.base.BaseAuthProvider"
            

Abstract base class implementing core AuthProvider interface.

Provides only the required methods - other capabilities are mixed in via protocols.

description abstractmethod property

description: str

Human-readable description of this authentication provider.

Returns:

Type Description
str

Description suitable for help text and user interfaces.

build_from_settings classmethod

build_from_settings(*, context_name: str, provider_name: str | None, provider_config: Any) -> 'BaseAuthProvider'

Create provider instance from settings configuration.

Parameters:

Name Type Description Default
context_name str

Context name for the provider.

required
provider_name str | None

Optional provider name for identification.

required
provider_config Any

Provider configuration object from settings.

required

Returns:

Type Description
'BaseAuthProvider'

Configured provider instance.

Raises:

Type Description
NotImplementedError

If provider doesn't implement this method.

Source code in qlam_core/auth/base.py
128
129
130
131
132
133
134
135
136
137
138
139
140
@classmethod
def build_from_settings(
    cls, *, context_name: str, provider_name: str | None, provider_config: Any
) -> "BaseAuthProvider":
    """Create provider instance from settings configuration.

    :param context_name: Context name for the provider.
    :param provider_name: Optional provider name for identification.
    :param provider_config: Provider configuration object from settings.
    :return: Configured provider instance.
    :raises NotImplementedError: If provider doesn't implement this method.
    """
    raise NotImplementedError(f"Provider {cls.__name__} must implement build_from_settings")

extra_info_from_config classmethod

extra_info_from_config(provider_config: Any) -> JsonDict

Extract extra display information from provider configuration.

Parameters:

Name Type Description Default
provider_config Any

Provider configuration object from settings.

required

Returns:

Type Description
JsonDict

Dictionary of extra information for display purposes.

Source code in qlam_core/auth/base.py
142
143
144
145
146
147
148
149
@classmethod
def extra_info_from_config(cls, provider_config: Any) -> JsonDict:
    """Extract extra display information from provider configuration.

    :param provider_config: Provider configuration object from settings.
    :return: Dictionary of extra information for display purposes.
    """
    return {}

get_auth_context abstractmethod

get_auth_context() -> JsonDict

Get authentication context for use by clients.

Returns:

Type Description
JsonDict

Dictionary describing authentication state and metadata.

Source code in qlam_core/auth/base.py
75
76
77
78
79
80
81
@abstractmethod
def get_auth_context(self) -> JsonDict:
    """Get authentication context for use by clients.

    :return: Dictionary describing authentication state and metadata.
    """
    ...

get_credential abstractmethod

get_credential() -> CredentialBase | None

Return a credential payload as a Pydantic model.

Providers may return a credential with a non-authenticated status (e.g. status="Not authenticated") to convey metadata such as refresh capability. Return None only when the provider has no credential data at all.

Source code in qlam_core/auth/base.py
83
84
85
86
87
88
89
90
91
92
@abstractmethod
def get_credential(self) -> CredentialBase | None:
    """Return a credential payload as a Pydantic model.

    Providers may return a credential with a non-authenticated status
    (e.g. ``status="Not authenticated"``) to convey metadata such as
    refresh capability.  Return ``None`` only when the provider has no
    credential data at all.
    """
    ...

get_user_info

get_user_info(api_base_url: str, *, timeout: float = 30.0, verify_ssl: bool | str = True, follow_redirects: bool = True, headers: dict[str, str] | None = None) -> UserInfo

Return the current authenticated user profile.

Default raises ConfigurationError with usage-error semantics. OAuth providers override this to fetch {api_base_url}/userinfo.

Parameters:

Name Type Description Default
api_base_url str

API base URL used to build the userinfo endpoint.

required
timeout float

Request timeout in seconds.

30.0
verify_ssl bool | str

SSL verification setting or CA bundle path.

True
follow_redirects bool

Whether to follow HTTP redirects.

True
headers dict[str, str] | None

Non-authentication headers to include in the request.

None

Returns:

Type Description
UserInfo

Typed user profile from the identity provider.

Raises:

Type Description
ConfigurationError

If this provider does not support userinfo lookup.

Source code in qlam_core/auth/base.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
def get_user_info(
    self,
    api_base_url: str,
    *,
    timeout: float = 30.0,
    verify_ssl: bool | str = True,
    follow_redirects: bool = True,
    headers: dict[str, str] | None = None,
) -> UserInfo:
    """Return the current authenticated user profile.

    Default raises [`ConfigurationError`][qlam_core.errors.ConfigurationError] with
    usage-error semantics. OAuth providers override this to fetch
    ``{api_base_url}/userinfo``.

    :param api_base_url: API base URL used to build the userinfo endpoint.
    :param timeout: Request timeout in seconds.
    :param verify_ssl: SSL verification setting or CA bundle path.
    :param follow_redirects: Whether to follow HTTP redirects.
    :param headers: Non-authentication headers to include in the request.
    :return: Typed user profile from the identity provider.
    :raises ConfigurationError: If this provider does not support userinfo lookup.
    """
    provider_name = (
        getattr(self, "provider_name", None)
        or getattr(self, "name", None)
        or self.__class__.__name__
    )
    raise ConfigurationError(
        f"Provider '{provider_name}' does not support user info lookup. "
        "Use an OAuth provider.",
        exit_code=ExitCode.USAGE_ERROR,
    )

is_authenticated abstractmethod

is_authenticated() -> bool

Check if the provider has valid authentication.

Returns:

Type Description
bool

True if authenticated, False otherwise.

Source code in qlam_core/auth/base.py
67
68
69
70
71
72
73
@abstractmethod
def is_authenticated(self) -> bool:
    """Check if the provider has valid authentication.

    :return: True if authenticated, False otherwise.
    """
    ...

HTTPHeadersMixin

Bases: Protocol


              flowchart TD
              qlam_core.auth.base.HTTPHeadersMixin[HTTPHeadersMixin]

              

              click qlam_core.auth.base.HTTPHeadersMixin href "" "qlam_core.auth.base.HTTPHeadersMixin"
            

Protocol for auth providers that can generate HTTP headers.

This protocol defines the interface for providers that can generate authentication headers for HTTP requests. Implementation is left to the concrete provider classes.

get_headers

get_headers() -> Dict[str, str]

Get authentication headers for HTTP requests.

Returns:

Type Description
Dict[str, str]

Dictionary of HTTP headers for authentication

Source code in qlam_core/auth/base.py
161
162
163
164
165
166
def get_headers(self) -> Dict[str, str]:
    """Get authentication headers for HTTP requests.

    :return: Dictionary of HTTP headers for authentication
    """
    ...

LoginLogoutMixin

Mixin providing default login/logout implementations.

login

login() -> None

Default login implementation (no-op).

Override to implement provider-specific login logic.

Source code in qlam_core/auth/base.py
172
173
174
175
176
177
def login(self) -> None:
    """Default login implementation (no-op).

    Override to implement provider-specific login logic.
    """
    pass

logout

logout() -> None

Default logout implementation (no-op).

Override to implement provider-specific logout logic.

Source code in qlam_core/auth/base.py
179
180
181
182
183
184
def logout(self) -> None:
    """Default logout implementation (no-op).

    Override to implement provider-specific logout logic.
    """
    pass

RefreshCredentialsMixin

Bases: ABC


              flowchart TD
              qlam_core.auth.base.RefreshCredentialsMixin[RefreshCredentialsMixin]

              

              click qlam_core.auth.base.RefreshCredentialsMixin href "" "qlam_core.auth.base.RefreshCredentialsMixin"
            

Mixin for auth providers that can refresh cached credentials.

Providers that support refresh should inherit this mixin and implement the required methods. This gives us a clear, explicit contract (no attribute introspection needed) and works well with dynamic provider loading.

can_refresh_credentials abstractmethod

can_refresh_credentials() -> bool

Return True if cached credentials can be refreshed non-interactively right now.

Source code in qlam_core/auth/base.py
216
217
218
@abstractmethod
def can_refresh_credentials(self) -> bool:
    """Return True if cached credentials can be refreshed non-interactively right now."""

refresh_credentials abstractmethod

refresh_credentials(*, force: bool = False) -> bool

Refresh credentials for this provider, updating the cache if needed.

Source code in qlam_core/auth/base.py
212
213
214
@abstractmethod
def refresh_credentials(self, *, force: bool = False) -> bool:
    """Refresh credentials for this provider, updating the cache if needed."""

TokenMixin

Bases: Protocol


              flowchart TD
              qlam_core.auth.base.TokenMixin[TokenMixin]

              

              click qlam_core.auth.base.TokenMixin href "" "qlam_core.auth.base.TokenMixin"
            

Protocol for token-based authentication providers.

This protocol defines the interface for providers that work with access tokens. Implementation of token management is left to concrete provider classes.

token

token() -> str

Return an access token to be injected into requests.

Returns:

Type Description
str

Access token string.

Source code in qlam_core/auth/base.py
196
197
198
199
200
201
def token(self) -> str:
    """Return an access token to be injected into requests.

    :return: Access token string.
    """
    ...

supports_refresh_credentials

supports_refresh_credentials(provider: object) -> bool

Return True if provider supports non-interactive credential refresh.

Note

This is intentionally a contract-based check: refresh-capable providers must inherit RefreshCredentialsMixin.

Source code in qlam_core/auth/base.py
221
222
223
224
225
226
227
228
def supports_refresh_credentials(provider: object) -> bool:
    """Return True if ``provider`` supports non-interactive credential refresh.

    !!! note
        This is intentionally a contract-based check: refresh-capable providers must
        inherit [`RefreshCredentialsMixin`][qlam_core.auth.base.RefreshCredentialsMixin].
    """
    return isinstance(provider, RefreshCredentialsMixin)

Auth Client

AuthClient - programmatic authentication operations.

This module defines the programmatic API for authentication management, designed for use by any consumer (Bloqade, web apps, notebooks, CLI shells).

Usage: from qlam_core.auth.client import AuthClient from qlam_core.common.context import AppContext

with AuthClient(AppContext()) as client:
    # Login to a specific provider
    client.login(provider="oauth")

    # Check authentication status
    providers = client.list_providers()

    # Logout
    client.logout(provider="oauth")

AuthClient

AuthClient(ctx: AppContext)

Client for authentication operations.

This provides a presentation-free API for authentication functionality.

Notes: - This module provides a presentation-free API. It raises domain exceptions (e.g. QlamCoreError) which consumers handle at their application boundary.

Initialize the auth client.

Parameters:

Name Type Description Default
ctx AppContext

Application context containing configuration

required
Source code in qlam_core/auth/client.py
45
46
47
48
49
50
def __init__(self, ctx: AppContext):
    """Initialize the auth client.

    :param ctx: Application context containing configuration
    """
    self.ctx = ctx

__enter__

__enter__() -> 'AuthClient'

Context manager entry.

Source code in qlam_core/auth/client.py
52
53
54
def __enter__(self) -> "AuthClient":
    """Context manager entry."""
    return self

__exit__

__exit__(exc_type, exc_val, exc_tb) -> None

Context manager exit.

Source code in qlam_core/auth/client.py
56
57
58
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
    """Context manager exit."""
    pass

get_credential

get_credential(provider: str) -> CredentialBase | None

Get the credential for a specific provider.

Returns the provider's credential model (e.g. OAuthCredential, BasicCredential). A returned credential may have a non-authenticated status; callers should inspect the status field. Returns None only when the provider has no credential data at all.

Parameters:

Name Type Description Default
provider str

Provider name to retrieve the credential for.

required

Returns:

Type Description
CredentialBase | None

Provider-specific credential model, or None.

Raises:

Type Description
ConfigurationError

If the provider is unknown or misconfigured.

AuthenticationError

If the provider raises an expected error.

Source code in qlam_core/auth/client.py
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
def get_credential(self, provider: str) -> CredentialBase | None:
    """Get the credential for a specific provider.

    Returns the provider's credential model (e.g. ``OAuthCredential``,
    ``BasicCredential``).  A returned credential may have a
    non-authenticated status; callers should inspect the ``status`` field.
    Returns ``None`` only when the provider has no credential data at all.

    :param provider: Provider name to retrieve the credential for.
    :return: Provider-specific credential model, or None.
    :raises ConfigurationError: If the provider is unknown or misconfigured.
    :raises AuthenticationError: If the provider raises an expected error.
    """
    auth_provider = self._require_provider(provider)
    return self._call_provider_action(
        action=auth_provider.get_credential,
        failure_prefix="Get credential failed",
    )

get_user_info

get_user_info(provider: str | None = None) -> UserInfo

Return the current authenticated user profile from {api}/userinfo.

When provider is omitted, resolves current_context.defaults.auth_provider. The profile is fetched from the context's api_base_url (/userinfo), not the IdP endpoint.

Parameters:

Name Type Description Default
provider str | None

Auth provider name, or None to use the context default.

None

Returns:

Type Description
UserInfo

Typed user profile from the provider.

Raises:

Type Description
ConfigurationError

If no context default or API base URL exists, the provider is unknown/misconfigured, or it does not support userinfo.

AuthenticationError

If the provider raises an expected error.

QlamCoreError

Typed OAuth/domain errors.

Source code in qlam_core/auth/client.py
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
def get_user_info(self, provider: str | None = None) -> UserInfo:
    """Return the current authenticated user profile from ``{api}/userinfo``.

    When ``provider`` is omitted, resolves
    ``current_context.defaults.auth_provider``. The profile is fetched from
    the context's ``api_base_url`` (``/userinfo``), not the IdP endpoint.

    :param provider: Auth provider name, or None to use the context default.
    :return: Typed user profile from the provider.
    :raises ConfigurationError: If no context default or API base URL exists,
        the provider is unknown/misconfigured, or it does not support userinfo.
    :raises AuthenticationError: If the provider raises an expected error.
    :raises QlamCoreError: Typed OAuth/domain errors.
    """
    if provider is None:
        defaults = self.ctx.config.current_context.defaults
        provider = defaults.auth_provider if defaults else None
        if not provider:
            raise ConfigurationError(
                "No default auth provider configured in the current context. "
                "Pass provider=... or set defaults.auth_provider.",
                exit_code=ExitCode.USAGE_ERROR,
            )

    auth_provider = self._require_provider(provider)
    from qlam_core.clients.http.resolver import ClientConfigResolver

    resolver = ClientConfigResolver(self.ctx)
    return self._call_provider_action(
        action=lambda: auth_provider.get_user_info(
            resolver.resolve_base_url(),
            timeout=resolver.resolve_timeout(),
            verify_ssl=resolver.resolve_verify_ssl(),
            follow_redirects=resolver.resolve_follow_redirects(),
            headers=resolver.resolve_headers(),
        ),
        failure_prefix="Get user info failed",
    )

is_authenticated

is_authenticated(provider: str | None = None) -> bool

Check if authentication is active.

Source code in qlam_core/auth/client.py
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
def is_authenticated(self, provider: str | None = None) -> bool:
    """Check if authentication is active."""
    from qlam_core.auth.registry import auth_registry

    if provider:
        # Check one provider: try registry first, else create from config.
        auth_provider = auth_registry.get_provider(provider)
        if not auth_provider:
            auth_provider = self._create_provider_from_config(provider)

        if auth_provider:
            try:
                # Query authenticated state (best-effort errors treated as False).
                return auth_provider.is_authenticated()
            except (AttributeError, RuntimeError, ValueError, QlamCoreError):
                return False
        return False

    # Check all providers: any authenticated provider counts as authenticated.
    authenticated = self._get_authenticated_providers()
    return len(authenticated) > 0

list_providers

list_providers() -> list[dict[str, Any]]

List all authentication providers in the current context.

Source code in qlam_core/auth/client.py
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
def list_providers(self) -> list[dict[str, Any]]:
    """List all authentication providers in the current context."""
    from qlam_core.auth.registry import auth_registry

    current_context = self.ctx.config.current_context
    if not current_context.auth_providers:
        return []

    provider_data: list[dict[str, Any]] = []
    for auth_provider_config in current_context.auth_providers:
        provider_name = auth_provider_config.name
        provider_type = auth_provider_config.provider

        # Determine status ("authenticated", "available", "error", etc.).
        status = self._provider_status(
            provider_name=provider_name,
            provider_type=provider_type,
            provider_config=auth_provider_config,
        )

        # Gather static metadata/capabilities and optional extra info.
        capabilities = auth_registry.get_capabilities(provider_type)
        description = capabilities.get("description", f"{provider_type} authentication")
        extra_info = self._provider_extra_info(
            provider_type=provider_type,
            provider_config=auth_provider_config,
        )

        provider_info = {
            "name": provider_name,
            "type": provider_type,
            "status": status,
            "description": description,
        }
        provider_info.update(extra_info)
        provider_data.append(provider_info)

    return provider_data

login

login(provider: str | None = None) -> dict[str, bool]

Perform authentication login.

Parameters:

Name Type Description Default
provider str | None

Specific provider name to login to. If None, logs in to all providers.

None

Returns:

Type Description
dict[str, bool]

Dictionary mapping provider names to success status

Raises:

Type Description
ValueError

If provider is unknown or doesn't support login

AuthenticationError

If login fails for the specific-provider path.

QlamCoreError

Provider/flow typed domain errors.

Source code in qlam_core/auth/client.py
306
307
308
309
310
311
312
313
314
315
316
317
318
def login(self, provider: str | None = None) -> dict[str, bool]:
    """Perform authentication login.

    :param provider: Specific provider name to login to. If None, logs in to all providers.
    :return: Dictionary mapping provider names to success status
    :raises ValueError: If provider is unknown or doesn't support login
    :raises AuthenticationError: If login fails for the specific-provider path.
    :raises QlamCoreError: Provider/flow typed domain errors.
    """
    if provider:
        return {provider: self._login_one(provider)}

    return self._login_all()

logout

logout(provider: str | None = None) -> dict[str, bool]

Clear cached credentials.

Parameters:

Name Type Description Default
provider str | None

Specific provider name to logout from. If None, logs out from all.

None

Returns:

Type Description
dict[str, bool]

Dictionary mapping provider names to success status

Raises:

Type Description
ValueError

If provider is unknown or doesn't support logout

AuthenticationError

If logout fails for the specific-provider path.

QlamCoreError

Provider/flow typed domain errors.

Source code in qlam_core/auth/client.py
366
367
368
369
370
371
372
373
374
375
376
377
378
def logout(self, provider: str | None = None) -> dict[str, bool]:
    """Clear cached credentials.

    :param provider: Specific provider name to logout from. If None, logs out from all.
    :return: Dictionary mapping provider names to success status
    :raises ValueError: If provider is unknown or doesn't support logout
    :raises AuthenticationError: If logout fails for the specific-provider path.
    :raises QlamCoreError: Provider/flow typed domain errors.
    """
    if provider:
        return {provider: self._logout_one(provider)}

    return self._logout_all()

refresh_credentials

refresh_credentials(provider: str | None = None, *, force: bool = False) -> dict[str, bool]

Refresh cached credentials non-interactively (and persist updates).

This is a programmatic API intended for SDK and application usage.

Semantics: - If provider is provided, errors are surfaced as typed exceptions so callers can handle specific failures. - If provider is None, this method returns best-effort results and does not raise for per-provider failures (only for configuration/usage errors).

Source code in qlam_core/auth/client.py
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
def refresh_credentials(self, provider: str | None = None, *, force: bool = False) -> dict[str, bool]:
    """Refresh cached credentials non-interactively (and persist updates).

    This is a programmatic API intended for SDK and application usage.

    Semantics:
    - If `provider` is provided, errors are surfaced as typed exceptions so callers
      can handle specific failures.
    - If `provider` is None, this method returns best-effort results and does not
      raise for per-provider failures (only for configuration/usage errors).
    """
    if provider:
        return {provider: self._refresh_one(provider, force=force)}

    return self._refresh_all(force=force)

Credential Models

BasicCredential

Bases: CredentialBase


              flowchart TD
              qlam_core.auth.credentials.models.BasicCredential[BasicCredential]
              qlam_core.auth.credentials.models.CredentialBase[CredentialBase]

                              qlam_core.auth.credentials.models.CredentialBase --> qlam_core.auth.credentials.models.BasicCredential
                


              click qlam_core.auth.credentials.models.BasicCredential href "" "qlam_core.auth.credentials.models.BasicCredential"
              click qlam_core.auth.credentials.models.CredentialBase href "" "qlam_core.auth.credentials.models.CredentialBase"
            

Credential for username/password-based authentication providers.

Parameters:

Name Type Description Default
username

Authenticated username.

required
login_time

ISO-formatted timestamp of the last login, if known.

required
auth_source

Backend or service that validated the credentials, if known.

required

CredentialBase

Bases: BaseModel


              flowchart TD
              qlam_core.auth.credentials.models.CredentialBase[CredentialBase]

              

              click qlam_core.auth.credentials.models.CredentialBase href "" "qlam_core.auth.credentials.models.CredentialBase"
            

Base credential model returned by authentication providers.

All provider-specific credential types extend this base.

Parameters:

Name Type Description Default
name

Provider name that issued this credential.

required
status

Current authentication state.

required

OAuthCredential

Bases: CredentialBase


              flowchart TD
              qlam_core.auth.credentials.models.OAuthCredential[OAuthCredential]
              qlam_core.auth.credentials.models.CredentialBase[CredentialBase]

                              qlam_core.auth.credentials.models.CredentialBase --> qlam_core.auth.credentials.models.OAuthCredential
                


              click qlam_core.auth.credentials.models.OAuthCredential href "" "qlam_core.auth.credentials.models.OAuthCredential"
              click qlam_core.auth.credentials.models.CredentialBase href "" "qlam_core.auth.credentials.models.CredentialBase"
            

Credential for OAuth-based authentication providers.

Parameters:

Name Type Description Default
client_id

OAuth client identifier.

required
access_token

Current access token, if authenticated.

required
refresh_token

Refresh token for obtaining new access tokens, if available.

required
expires_at

Expiration time of the access token, if known.

required
allows_refresh

Whether this credential supports non-interactive token refresh.

required

User Profile Model

Typed current-user profile from the OIDC UserInfo endpoint.

QuEra namespaced claims of the form https://v2/{environment}/{claim} are normalized into canonical fields; unrecognized claims go in extra_claims.

UserInfo

Bases: BaseModel


              flowchart TD
              qlam_core.auth.user_info.UserInfo[UserInfo]

              

              click qlam_core.auth.user_info.UserInfo href "" "qlam_core.auth.user_info.UserInfo"
            

Current authenticated user profile from {api_base_url}/userinfo.

Standard OIDC claims are accepted as-is. QuEra claims https://v2/{environment}/{claim} for user_id, tenant_id, roles, groups, and permissions fold into the matching fields. Unrecognized claims (for example timestamp) are preserved in extra_claims.