{"record":{"id":"34bca22a05f35d34","repo":"tursodatabase/turso","slug":"use-authtoken-instead-of-embedding-credentials-in","errorCode":null,"errorMessage":"Use AuthToken instead of embedding credentials in the sync URL.","messagePattern":"Use AuthToken instead of embedding credentials in the sync URL\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data/TursoSyncDatabaseOptions.cs","lineNumber":130,"sourceCode":"    public string ClientName { get; init; } = \"turso-sync-dotnet\";\n    public TimeSpan? LongPollTimeout { get; init; }\n    public bool BootstrapIfEmpty { get; init; } = true;\n    public TursoPartialSyncOptions? PartialSync { get; init; }\n    public TursoRemoteEncryptionOptions? RemoteEncryption { get; init; }\n    public long? PushOperationsThreshold { get; init; }\n    public long? PullBytesThreshold { get; init; }\n    public bool ForceLogicalMvccPull { get; init; }\n    public HttpClient? HttpClient { get; init; }\n    public string? ExperimentalFeatures { get; init; }\n\n    internal Uri GetNormalizedRemoteUri()\n    {\n        if (!RemoteUri.IsAbsoluteUri)\n            throw new ArgumentException(\"The sync remote URL must be absolute.\", nameof(RemoteUri));\n        if (!string.IsNullOrEmpty(RemoteUri.Query) || !string.IsNullOrEmpty(RemoteUri.Fragment))\n            throw new ArgumentException(\"The sync remote URL must not include a query string or fragment.\", nameof(RemoteUri));\n        if (!string.IsNullOrEmpty(RemoteUri.UserInfo))\n            throw new ArgumentException(\"Use AuthToken instead of embedding credentials in the sync URL.\", nameof(RemoteUri));\n        if (string.IsNullOrEmpty(RemoteUri.Host))\n            throw new ArgumentException(\"The sync remote URL must include a host.\", nameof(RemoteUri));\n\n        var scheme = RemoteUri.Scheme.ToLowerInvariant() switch\n        {\n            \"turso\" or \"libsql\" => Uri.UriSchemeHttps,\n            \"http\" => Uri.UriSchemeHttp,\n            \"https\" => Uri.UriSchemeHttps,\n            _ => throw new ArgumentException(\n                \"The sync remote URL must use turso, libsql, HTTP, or HTTPS.\",\n                nameof(RemoteUri)),\n        };\n        var builder = new UriBuilder(RemoteUri)\n        {\n            Scheme = scheme,\n            Port = RemoteUri.IsDefaultPort ? -1 : RemoteUri.Port,\n            UserName = string.Empty,\n            Password = string.Empty,","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/tursodatabase/turso/blob/c1e59287258d99b309e362a63f48822256e2f65f/bindings/dotnet/src/Turso.Data/TursoSyncDatabaseOptions.cs#L112-L148","documentation":"GetNormalizedRemoteUri rejects a RemoteUri containing user information (user:password@ in the URL). Credentials embedded in the sync URL are a security risk and get stripped or mishandled by normalization, so the library refuses them and directs you to the dedicated AuthToken option.","triggerScenarios":"Constructing TursoSyncDatabaseOptions with a RemoteUri like https://user:token@mydb.turso.io or libsql://admin:secret@host. Uri.UserInfo is non-empty at TursoSyncDatabaseOptions.cs:129-130.","commonSituations":"Converting libsql clients that used user:pass basic auth in URLs, pasting connection strings from other databases (Postgres/MySQL style user:password@host), reusing a URL configured for a driver that supported in-URL credentials.","solutions":["Remove the user:password@ section from the remote URL.","Pass the credential via the AuthToken property of TursoSyncDatabaseOptions instead."],"exampleFix":"// before\nvar opts = new TursoSyncDatabaseOptions(path, new Uri(\"https://admin:secret@mydb.turso.io\"));\n// after\nvar opts = new TursoSyncDatabaseOptions(path, new Uri(\"https://mydb.turso.io\")) { AuthToken = \"secret\" };","handlingStrategy":"validation","validationCode":"static void EnsureNoEmbeddedCredentials(Uri remoteUri)\n{\n    if (!string.IsNullOrEmpty(remoteUri.UserInfo))\n        throw new ArgumentException(\"Move user:password@ from the sync URL into AuthToken.\");\n}","typeGuard":"static bool HasNoUrlCredentials(Uri u) => string.IsNullOrEmpty(u.UserInfo);","tryCatchPattern":"try { var db = new TursoSyncDatabase(opts); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"AuthToken\"))\n{\n    // rebuild options with AuthToken instead of URL credentials\n}","preventionTips":["Always deliver credentials through TursoSyncDatabaseOptions.AuthToken, never the URL.","Be alert when porting connection strings from Postgres/MySQL-style user:pass@host formats.","Keep tokens in configuration/secrets, not in stored URLs."],"tags":["dotnet","sync","url-validation","credentials","security"],"backgroundTag":"credentials-in-url","analyzedSha":"c1e59287258d99b309e362a63f48822256e2f65f","analyzedAt":"2026-08-31T11:17:35.598Z","contentChangedAt":"2026-08-31T11:17:35.598Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}