{"record":{"id":"dc3cd44afcb11f0e","repo":"tursodatabase/turso","slug":"refusing-to-send-the-sync-auth-token-to-an-origin","errorCode":null,"errorMessage":"Refusing to send the sync auth token to an origin other than the configured remote.","messagePattern":"Refusing to send the sync auth token to an origin other than the configured remote\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data/TursoSyncDatabase.cs","lineNumber":761,"sourceCode":"            if (_disposeHttpClient)\n                _httpClient.Dispose();\n        }\n        finally\n        {\n            _operationLock.Release();\n        }\n    }\n\n    internal static void ValidateAuthTransport(\n        Uri requestUri,\n        Uri configuredRemoteUri,\n        string? authToken)\n    {\n        if (string.IsNullOrWhiteSpace(authToken))\n            return;\n        if (!HasSameOrigin(requestUri, configuredRemoteUri))\n        {\n            throw new InvalidOperationException(\n                \"Refusing to send the sync auth token to an origin other than the configured remote.\");\n        }\n        if (requestUri.Scheme != Uri.UriSchemeHttps && !requestUri.IsLoopback)\n        {\n            throw new InvalidOperationException(\n                \"Auth Token requires HTTPS sync requests unless the host is localhost or loopback.\");\n        }\n    }\n\n    private static bool HasSameOrigin(Uri left, Uri right)\n    {\n        return left.Scheme.Equals(right.Scheme, StringComparison.OrdinalIgnoreCase)\n               && left.IdnHost.Equals(right.IdnHost, StringComparison.OrdinalIgnoreCase)\n               && left.Port == right.Port;\n    }\n\n    private static Uri NormalizeRemoteUri(Uri uri)\n    {","sourceCodeStart":743,"sourceCodeEnd":779,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data/TursoSyncDatabase.cs#L743-L779","documentation":"This InvalidOperationException is thrown by ValidateAuthTransport before an HTTP sync request is sent. If an AuthToken is configured, the library refuses to attach it to any request whose URI origin (scheme, host, port) differs from the configured remote origin, preventing credential leakage to third-party endpoints such as redirects or redirect-target rewrites.","triggerScenarios":"Calling sync operations on a TursoSyncDatabase with an AuthToken set while HandleHttpCoreAsync is about to issue a request whose requestUri has a different origin than configuredRemoteUri (e.g. after a redirect, a rewritten base URL, or pointing the request at a mirror/proxy host).","commonSituations":"Server-side redirects from the configured remote to a different host (CDN, load balancer) that the client follows with the token attached; misconfigured remote URLs pointing to a proxy while requests are redirected elsewhere; custom HttpClient handlers that rewrite request URLs.","solutions":["Ensure the sync remote never redirects to a different origin; configure the canonical origin (scheme+host+port) as the remoteUri","Remove the AuthToken if you intentionally need to talk to a non-configured origin, and use a different auth mechanism","Use a HttpClient handler that disables automatic cross-origin redirect following (AllowAutoRedirect=false) and handle redirects explicitly","Verify the request URL construction: the effective request URI must match the scheme, host, and port of the remote passed to TursoSyncDatabaseOptions"],"exampleFix":"// before: handler follows redirects, token leaks to redirect target\nvar client = new HttpClient(new SocketsHttpHandler { AllowAutoRedirect = true });\nvar db = new TursoSyncDatabase(new TursoSyncDatabaseOptions(path, remote) { AuthToken = token, HttpClient = client });\n// after: disable redirects so requests never go to a different origin\nvar client = new HttpClient(new SocketsHttpHandler { AllowAutoRedirect = false });\nvar db = new TursoSyncDatabase(new TursoSyncDatabaseOptions(path, remote) { AuthToken = token, HttpClient = client });","handlingStrategy":"validation","validationCode":"bool TokenTransportIsSafe(Uri requestUri, Uri configuredRemote, string? authToken) =>\n    string.IsNullOrWhiteSpace(authToken) ||\n    (requestUri.Scheme == configuredRemote.Scheme && requestUri.Host == configuredRemote.Host && requestUri.Port == configuredRemote.Port);\nvar handler = new SocketsHttpHandler { AllowAutoRedirect = false };\nvar client = new HttpClient(handler);","typeGuard":null,"tryCatchPattern":"try\n{\n    await db.SyncAsync(ct);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Refusing to send the sync auth token\"))\n{\n    logger.LogError(ex, \"Sync attempted to send auth token to a different origin than the configured remote.\");\n    throw; // do not retry with credentials at risk\n}","preventionTips":["Disable automatic redirects (AllowAutoRedirect = false) when an AuthToken is configured","Always use the exact canonical origin returned by the Turso platform as the remoteUri","Never point the same AuthToken client at mirrors or proxies on other origins"],"tags":["dotnet","sync","security","auth-token"],"backgroundTag":"cross-origin-credential-leak","analyzedSha":"6c7252267988c76e632af00a671e4b9788dfae13","analyzedAt":"2026-08-31T11:17:35.598Z","contentChangedAt":"2026-08-31T11:17:35.598Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}