Enable dashboard telemetry API by default with ApiKey auth and login token exchange#16326
Enable dashboard telemetry API by default with ApiKey auth and login token exchange#16326
Conversation
- Move try/catch in TelemetryLogsCommand and TelemetrySpansCommand to wrap GetAllResourcesAsync, so 404 from /api/telemetry/resources is caught and produces a user-friendly error instead of a raw exception - Normalize login URLs passed to --dashboard-url (strip /login?t=... path) - Update DashboardApiNotEnabled message to suggest 'aspire dashboard run --enable-api' - Improve --dashboard-url option description to clarify it accepts login URLs - Add tests for resources-endpoint-404 and login URL normalization scenarios Fixes #16236
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 16326Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 16326" |
- Remove --enable-api option from 'aspire dashboard run'; API is now always enabled - Add POST /api/telemetry/validateToken endpoint to exchange browser login token for API key - Update CLI telemetry commands to auto-extract login token from dashboard URL and exchange it for an API key - Add ExtractLoginToken helper to parse login URLs - Add source-generated JSON context for camelCase serialization - Add tests for token exchange, login token extraction, and updated dashboard run defaults
Auto-generate an API key and set DASHBOARD__API__PRIMARYAPIKEY and DASHBOARD__API__AUTHMODE=ApiKey via environment variables (not CLI args) when launching the standalone dashboard. This ensures the telemetry API requires authentication by default, matching the Hosting project pattern. Skipped when --allow-anonymous is set or when the user provides their own API key via unmatched tokens/env vars.
…sage, update xlf files
…ange - Fix connection-refused showing wrong error (DashboardLoginTokenFailed instead of DashboardConnectionFailed) - Refactor validateToken endpoints to use JSON request/response bodies with shared types - Split error messages into error (what went wrong) + hints (how to fix) + log path - Add TelemetryErrorInfo record supporting multiple hints - Mention --allow-anonymous and ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS in auth/token errors - Move shared TelemetryValidateTokenRequest/Response to src/Shared for AOT-compatible serialization
- Default Api.Enabled to true (API is on by default) - Default Api.AuthMode to ApiKey (was conditional on key presence) - Auto-generate API key when AuthMode is ApiKey but no key specified - Add Api.Disabled property, mark Api.Enabled as obsolete - Add ASPIRE_DASHBOARD_API_DISABLED / Dashboard:Api:Disabled config - DashboardAspireApiDisabledName takes precedence over Enabled - Update all consumers to use Api.Disabled instead of Api.Enabled - Combine ApiEnabled/ApiDisabled tests into parameterized theory
There was a problem hiding this comment.
Pull request overview
Enables the Aspire Dashboard telemetry HTTP API by default (secured via API key) to improve the standalone aspire otel experience, including automatic auth when users paste a dashboard login URL.
Changes:
- Dashboard: default-enable telemetry API with
ApiKeyauth, auto-generate API key, and introduceApi.Disabled(withEnabledobsolete + new config keys). - CLI: remove
--enable-api, accept/normalize/login?t=...URLs, auto-exchange login token for an API key, and improve telemetry error presentation. - Add
POST /api/telemetry/validateTokenendpoint + shared DTOs, plus broadened integration/unit test coverage and updated localized strings.
Reviewed changes
Copilot reviewed 50 out of 51 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Dashboard.Tests/Integration/TelemetryApiTests.cs | Adjusts integration assertions for new API auth defaults and key auto-generation. |
| tests/Aspire.Dashboard.Tests/Integration/StartupTests.cs | Expands API enabled/disabled coverage and warning expectations. |
| tests/Aspire.Dashboard.Tests/Integration/IntegrationTestHelpers.cs | Updates default test configuration to include API auth mode. |
| tests/Aspire.Cli.Tests/Mcp/McpToolHelpersTests.cs | Adds coverage for extracting login tokens from dashboard login URLs. |
| tests/Aspire.Cli.Tests/Mcp/ListStructuredLogsToolTests.cs | Aligns MCP error assertions with new error message keys. |
| tests/Aspire.Cli.Tests/Commands/TelemetrySpansCommandTests.cs | Adds CLI test for “API not enabled” 404 handling. |
| tests/Aspire.Cli.Tests/Commands/TelemetryLogsCommandTests.cs | Adds CLI tests for login URL normalization and improved 404/connection handling. |
| tests/Aspire.Cli.Tests/Commands/TelemetryCommandTests.cs | Adds tests for token exchange behavior and request/URL correctness. |
| tests/Aspire.Cli.Tests/Commands/DashboardRunCommandTests.cs | Updates expectations for API being enabled by default and env-var key injection. |
| src/Shared/Otlp/Serialization/OtlpJsonSerializerContext.cs | Registers new validate-token request/response types for source-gen JSON. |
| src/Shared/Model/Serialization/TelemetryValidateTokenJson.cs | Adds shared request/response DTOs for /api/telemetry/validateToken. |
| src/Shared/KnownConfigNames.cs | Introduces ASPIRE_DASHBOARD_API_DISABLED known config name. |
| src/Shared/DashboardUrls.cs | Adds helper for building the validate-token exchange endpoint URL. |
| src/Shared/DashboardConfigNames.cs | Adds config name constants for Dashboard:Api:Disabled and Aspire env var mapping. |
| src/Aspire.Dashboard/Telemetry/DashboardTelemetrySender.cs | Lowers “telemetry not configured” log to Debug. |
| src/Aspire.Dashboard/Properties/launchSettings.json | Adds a launch profile exercising browser + API key configuration. |
| src/Aspire.Dashboard/Model/Assistant/ChatClientFactory.cs | Lowers AI enable/disable logs to Debug. |
| src/Aspire.Dashboard/DashboardWebApplication.cs | Switches enabled checks to Api.Disabled and adds debug visibility. |
| src/Aspire.Dashboard/DashboardEndpointsBuilder.cs | Adds /api/telemetry/validateToken and supports POST-notfound when API disabled. |
| src/Aspire.Dashboard/Configuration/ValidateDashboardOptions.cs | Updates validation assumptions around API key generation defaults. |
| src/Aspire.Dashboard/Configuration/PostConfigureDashboardOptions.cs | Implements default auth mode, API key auto-generation, and disabled/enabled precedence. |
| src/Aspire.Dashboard/Configuration/DashboardOptions.cs | Adds ApiOptions.Disabled + obsoletes Enabled with shared backing field. |
| src/Aspire.Dashboard/Components/Pages/Login.razor.js | Updates browser-token validation call to JSON-body POST. |
| src/Aspire.Dashboard/Components/Layout/MainLayout.razor.cs | Switches API warning logic to Api.Disabled. |
| src/Aspire.Dashboard/Aspire.Dashboard.csproj | Links the shared validate-token DTO file into Dashboard build. |
| src/Aspire.Dashboard/Api/ApiAuthenticationHandler.cs | Tightens API auth to require API key (or allow unsecured), removing frontend fallback behavior. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.zh-Hant.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.zh-Hans.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.tr.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.ru.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.pt-BR.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.pl.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.ko.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.ja.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.it.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.fr.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.es.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.de.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.cs.xlf | Updates telemetry error strings and adds hint strings. |
| src/Aspire.Cli/Resources/TelemetryCommandStrings.resx | Adds structured error + hint strings and updates option description text. |
| src/Aspire.Cli/Resources/TelemetryCommandStrings.Designer.cs | Regenerates designer accessors for new/renamed resource keys. |
| src/Aspire.Cli/Mcp/Tools/McpToolHelpers.cs | Adds login-token extraction helper from dashboard login URLs. |
| src/Aspire.Cli/Commands/TelemetryTracesCommand.cs | Switches to structured telemetry error reporting and updated API discovery signature. |
| src/Aspire.Cli/Commands/TelemetrySpansCommand.cs | Wraps the full fetch path in error handling and switches to structured errors. |
| src/Aspire.Cli/Commands/TelemetryLogsCommand.cs | Wraps the full fetch path in error handling and switches to structured errors. |
| src/Aspire.Cli/Commands/TelemetryCommandHelpers.cs | Adds login-token exchange, URL normalization, and structured error+hint plumbing. |
| src/Aspire.Cli/Commands/ExportCommand.cs | Updates dashboard API discovery signature and uses structured error display. |
| src/Aspire.Cli/Commands/DashboardRunCommand.cs | Removes --enable-api, always enables API by default, and injects env-var secrets safely. |
| src/Aspire.Cli/Aspire.Cli.csproj | Links shared DashboardConfigNames + validate-token DTO into CLI build. |
| localhive.sh | Cleans stale managed publish output before bundling to avoid incremental publish skipping. |
| localhive.ps1 | Cleans stale managed publish output before bundling to avoid incremental publish skipping. |
Files not reviewed (1)
- src/Aspire.Cli/Resources/TelemetryCommandStrings.Designer.cs: Language not supported
…uthMode env var - Update ApiAuthenticationHandler XML docs to reflect removal of frontend auth fallback - Remove dead EnableApiOptionDescription resource from resx, Designer.cs, and xlf files - Guard DashboardApiAuthModeName env var with ConfigSettingHasValue check
- Remove async from HandleAuthenticateAsync (no awaits remain after frontend fallback removal) - Replace bool ConnectionFailed with TokenExchangeFailureKind enum to distinguish 404/401/connection errors - Surface DashboardApiNotEnabled error when token exchange returns 404 (API disabled) - Check ASPIRE_DASHBOARD_API_DISABLED in addition to API_ENABLED before injecting default
The /api/validatetoken endpoint was changed to accept [FromBody] ValidateTokenRequest but the test was still sending the token as a query parameter.
| <data name="DashboardApiNotAvailable" xml:space="preserve"> | ||
| <value>Dashboard API is not available. Ensure the AppHost is running with Dashboard enabled.</value> | ||
| <data name="DashboardNotAvailable" xml:space="preserve"> | ||
| <value>Could not fetch telemetry data from the dashboard. The dashboard is not available.</value> |
There was a problem hiding this comment.
| <value>Could not fetch telemetry data from the dashboard. The dashboard is not available.</value> | |
| <value>Could not fetch telemetry data from the dashboard: the dashboard is not available.</value> |
There was a problem hiding this comment.
I'm not sure about this format. I applied all changes except these.
| </data> | ||
| <data name="DashboardUrlOptionDescription" xml:space="preserve"> | ||
| <value>URL of a standalone Aspire Dashboard to connect to directly (bypasses AppHost discovery)</value> | ||
| <value>Base URL of a standalone Aspire Dashboard (e.g. http://localhost:18888). Login URLs are also accepted and automatically normalized</value> |
There was a problem hiding this comment.
| <value>Base URL of a standalone Aspire Dashboard (e.g. http://localhost:18888). Login URLs are also accepted and automatically normalized</value> | |
| <value>Base URL of a standalone Aspire Dashboard (e.g. http://localhost:18888). Login URLs are also accepted and automatically normalized.</value> |
| </data> | ||
| <data name="DashboardAuthFailed" xml:space="preserve"> | ||
| <value>Authentication denied by the dashboard. Use --api-key to specify a valid API key that matches the dashboard's configured API key (Dashboard:Api:PrimaryApiKey).</value> | ||
| <value>Could not fetch telemetry data from the dashboard. Authentication was denied.</value> |
There was a problem hiding this comment.
| <value>Could not fetch telemetry data from the dashboard. Authentication was denied.</value> | |
| <value>Could not fetch telemetry data from the dashboard: authentication failed.</value> |
| <value>Could not fetch telemetry data from the dashboard. Authentication was denied.</value> | ||
| </data> | ||
| <data name="DashboardAuthFailedHint" xml:space="preserve"> | ||
| <value>Authenticate with the dashboard using a --dashboard-url value that includes a valid login token (e.g. http://localhost:18888/login?t=TOKEN), or specify --api-key with a key matching the dashboard's configured API key.</value> |
There was a problem hiding this comment.
| <value>Authenticate with the dashboard using a --dashboard-url value that includes a valid login token (e.g. http://localhost:18888/login?t=TOKEN), or specify --api-key with a key matching the dashboard's configured API key.</value> | |
| <value>Authenticate with the dashboard either with a --dashboard-url including a valid login token (e.g. http://localhost:18888/login?t=TOKEN), or with an --api-key matching the dashboard's configured API key.</value> |
| // Parse query string to find 't' parameter | ||
| var queryParams = HttpUtility.ParseQueryString(query); | ||
| var token = queryParams["t"]; | ||
| if (!string.IsNullOrEmpty(token)) |
adamint
left a comment
There was a problem hiding this comment.
Automated review: found 1 configuration issue.
- Fix DashboardUrlOptionDescription missing trailing period - Change DashboardAuthFailed from 'denied' to 'failed' - Simplify DashboardAuthFailedHint wording - Remove redundant query.Length check in McpToolHelpers.ExtractLoginToken - Update xlf translation files
|
🎬 CLI E2E Test Recordings — 72 recordings uploaded (commit View recordings
📹 Recordings uploaded automatically from CI run #24701868889 |
- Dashboard:Api:Enabled now defaults to true (API enabled by default) - Dashboard:Api:AuthMode now defaults to ApiKey - Add Dashboard:Api:Disabled as the new preferred config to disable the API - Mark Dashboard:Api:Enabled as deprecated in docs - Update PrimaryApiKey default to note auto-generation - Add --dashboard-url and --api-key options to aspire otel logs/spans/traces - Document login URL support: passing http://host/login?t=<token> auto-exchanges the token for an API key - Update aspire otel main page description to mention standalone dashboard usage Documents changes from microsoft/aspire#16326 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Pull request created: #732
|
|
📝 Documentation draft PR created on microsoft/aspire.dev The following documentation updates have been drafted to cover the user-facing changes in this PR: Changes included
|
- Dashboard:Api:Enabled now defaults to true (API enabled by default) - Dashboard:Api:AuthMode now defaults to ApiKey - Add Dashboard:Api:Disabled as the new preferred config to disable the API - Mark Dashboard:Api:Enabled as deprecated in docs - Update PrimaryApiKey default to note auto-generation - Add --dashboard-url and --api-key options to aspire otel logs/spans/traces - Document login URL support: passing http://host/login?t=<token> auto-exchanges the token for an API key - Update aspire otel main page description to mention standalone dashboard usage Documents changes from microsoft/aspire#16326 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Dashboard:Api:Enabled now defaults to true (API enabled by default) - Dashboard:Api:AuthMode now defaults to ApiKey - Add Dashboard:Api:Disabled as the new preferred config to disable the API - Mark Dashboard:Api:Enabled as deprecated in docs - Update PrimaryApiKey default to note auto-generation - Add --dashboard-url and --api-key options to aspire otel logs/spans/traces - Document login URL support: passing http://host/login?t=<token> auto-exchanges the token for an API key - Update aspire otel main page description to mention standalone dashboard usage Documents changes from microsoft/aspire#16326 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Dashboard:Api:Enabled now defaults to true (API enabled by default) - Dashboard:Api:AuthMode now defaults to ApiKey - Add Dashboard:Api:Disabled as the new preferred config to disable the API - Mark Dashboard:Api:Enabled as deprecated in docs - Update PrimaryApiKey default to note auto-generation - Add --dashboard-url and --api-key options to aspire otel logs/spans/traces - Document login URL support: passing http://host/login?t=<token> auto-exchanges the token for an API key - Update aspire otel main page description to mention standalone dashboard usage Documents changes from microsoft/aspire#16326 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Dashboard:Api:Enabled now defaults to true (API enabled by default) - Dashboard:Api:AuthMode now defaults to ApiKey - Add Dashboard:Api:Disabled as the new preferred config to disable the API - Mark Dashboard:Api:Enabled as deprecated in docs - Update PrimaryApiKey default to note auto-generation - Add --dashboard-url and --api-key options to aspire otel logs/spans/traces - Document login URL support: passing http://host/login?t=<token> auto-exchanges the token for an API key - Update aspire otel main page description to mention standalone dashboard usage Documents changes from microsoft/aspire#16326 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Dashboard:Api:Enabled now defaults to true (API enabled by default) - Dashboard:Api:AuthMode now defaults to ApiKey - Add Dashboard:Api:Disabled as the new preferred config to disable the API - Mark Dashboard:Api:Enabled as deprecated in docs - Update PrimaryApiKey default to note auto-generation - Add --dashboard-url and --api-key options to aspire otel logs/spans/traces - Document login URL support: passing http://host/login?t=<token> auto-exchanges the token for an API key - Update aspire otel main page description to mention standalone dashboard usage Documents changes from microsoft/aspire#16326 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Dashboard:Api:Enabled now defaults to true (API enabled by default) - Dashboard:Api:AuthMode now defaults to ApiKey - Add Dashboard:Api:Disabled as the new preferred config to disable the API - Mark Dashboard:Api:Enabled as deprecated in docs - Update PrimaryApiKey default to note auto-generation - Add --dashboard-url and --api-key options to aspire otel logs/spans/traces - Document login URL support: passing http://host/login?t=<token> auto-exchanges the token for an API key - Update aspire otel main page description to mention standalone dashboard usage Documents changes from microsoft/aspire#16326 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Dashboard:Api:Enabled now defaults to true (API enabled by default) - Dashboard:Api:AuthMode now defaults to ApiKey - Add Dashboard:Api:Disabled as the new preferred config to disable the API - Mark Dashboard:Api:Enabled as deprecated in docs - Update PrimaryApiKey default to note auto-generation - Add --dashboard-url and --api-key options to aspire otel logs/spans/traces - Document login URL support: passing http://host/login?t=<token> auto-exchanges the token for an API key - Update aspire otel main page description to mention standalone dashboard usage Documents changes from microsoft/aspire#16326 Co-authored-by: aspire-repo-bot[bot] <268009190+aspire-repo-bot[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Description
Improve the standalone dashboard experience for
aspire otelcommands by enabling the telemetry API by default with API key authentication, and adding automatic authentication via login token exchange.Dashboard API defaults
Api.Enabledtotrue— The dashboard API is now enabled by default. Previously it defaulted to disabled unless explicitly configured.Api.AuthModetoApiKey— The API authentication mode now defaults toApiKeyinstead of being conditional on whether a key was provided.AuthModeisApiKeybut noPrimaryApiKeyis specified, a 128-bit key is auto-generated (matching the existingBrowserTokenpattern inPostConfigureDashboardOptions).Api.Disabledproperty — NewDisabledproperty onApiOptions.Api.Enabledis marked[Obsolete]and delegates toDisabledvia a shared backing field. Setting either property updates the other.ASPIRE_DASHBOARD_API_DISABLED/Dashboard:Api:Disabledconfig — New config names (DashboardAspireApiDisabledName,DashboardApiDisabledName).DashboardAspireApiDisabledNametakes precedence overDashboardAspireApiEnabledNameinPostConfigureDashboardOptions.CLI changes
Enable telemetry API by default in
aspire dashboard run— Removed the--enable-apioption. The API is now always enabled unless explicitly overridden via unmatched tokens or environment variable.Auto-exchange login token for API key — When a user passes a login URL (e.g.
http://localhost:18888/login?t=abc123) to--dashboard-url, the CLI automatically extracts the browser token from thetquery parameter and exchanges it for an API key via thePOST /api/telemetry/validateTokenendpoint. Users can copy-paste the login URL from dashboard output andaspire otel logsjust works.Improved error messages — Better error messages in telemetry commands when the dashboard API is not enabled or authentication fails. The
DashboardApiNotEnabledmessage now suggests the CLI command alongside the raw config key.Error handling fix — In
TelemetryLogsCommandandTelemetrySpansCommand, the initial/api/telemetry/resourcescall was outside theHttpRequestExceptiontry/catch block. When the API was disabled, the 404 surfaced as a raw exception. Moved the try/catch to wrap the entire fetch method body.Dashboard endpoint
POST /api/telemetry/validateToken— New endpoint that accepts a frontend browser token and returns the telemetry API key (or null if unsecured). Uses constant-time comparison viaCompareHelpers.CompareKey. Returns 401 for invalid tokens.Other
--dashboard-urlstrips/loginpath and query string automatically.Fixes #16236
Checklist
ApiOptions.Disabledproperty (new)ApiOptions.Enabledmarked[Obsolete]validateTokenendpoint validates the browser token before returning the API key. It usesCompareHelpers.CompareKey(constant-time comparison) and requires the frontend auth mode to beBrowserToken. The endpoint is scoped under/api/telemetryand returns 401 for invalid tokens. API keys are auto-generated usingRandomNumberGeneratorwith 128-bit entropy.