Supabase.Gotrue
8.1.0
dotnet add package Supabase.Gotrue --version 8.1.0
NuGet\Install-Package Supabase.Gotrue -Version 8.1.0
<PackageReference Include="Supabase.Gotrue" Version="8.1.0" />
<PackageVersion Include="Supabase.Gotrue" Version="8.1.0" />
<PackageReference Include="Supabase.Gotrue" />
paket add Supabase.Gotrue --version 8.1.0
#r "nuget: Supabase.Gotrue, 8.1.0"
#:package Supabase.Gotrue@8.1.0
#addin nuget:?package=Supabase.Gotrue&version=8.1.0
#tool nuget:?package=Supabase.Gotrue&version=8.1.0
Supabase.Gotrue
A C# client for Supabase Auth (GoTrue) — email/password, OAuth providers, SSO, magic links, and user management.
Part of the Supabase C# SDK. Most projects
use it through the Supabase meta-package (supabase.Auth); reference this
package directly to use Auth on its own. The client is written to be platform-agnostic and works on
.NET, Xamarin, MAUI, and Unity — see the Unity session-persistence example.
Installation
dotnet add package Supabase.Gotrue
Targets .NET Standard 2.1.
Getting started
Against the Supabase hosted service, point the client at your project's auth URL and pass your
apikey header:
using Supabase.Gotrue;
var client = new Client(new ClientOptions
{
Url = "https://PROJECT_ID.supabase.co/auth/v1",
Headers = new Dictionary<string, string> { { "apikey", SUPABASE_PUBLIC_KEY } }
});
var session = await client.SignUp("new-user@example.com", "password");
There is also a StatelessClient for one-off API calls that carry their options per request rather
than holding a session:
var options = new StatelessClientOptions { Url = "https://example.com/auth/v1" };
await new StatelessClient().SignUp("new-user@example.com", "password", options);
Sessions: persist, retrieve, destroy
The client is agnostic about where sessions are stored. ClientOptions exposes callbacks for saving,
loading, and destroying a session; when they are set together with AutoRefreshToken, the client
restores and refreshes an existing session as it initializes.
async void Initialize()
{
var persistence = new GotrueSessionPersistence(SaveSession, LoadSession, DestroySession);
var client = new Client(new ClientOptions
{
Url = GOTRUE_URL,
AllowUnconfirmedUserSessions = true,
SessionPersistence = persistence
});
// Listen to token-refresh problems and auth-state changes.
client.AddDebugListener(LogDebug);
client.AddStateChangedListener(AuthStateListener);
// Restore a persisted session and refresh it.
client.LoadSession();
await client.RetrieveSessionAsync();
}
// Example: persist the session to the user's cache folder.
bool SaveSession(Session session)
{
var path = Path.Join(FileSystem.CacheDirectory, ".gotrue.cache");
File.WriteAllText(path, JsonSerializer.Serialize(session));
return true;
}
OAuth (PKCE flow)
For third-party OAuth the PKCE flow is preferred. Configure a callback URL in the Supabase dashboard,
generate a sign-in request, store the PKCEVerifier, and exchange the returned code for a session in
your callback:
var state = await client.SignIn(Constants.Provider.Github, new SignInOptions
{
FlowType = Constants.OAuthFlowType.PKCE,
RedirectTo = "http://localhost:3000/oauth/callback"
});
// Send the user to state.Uri, and stash state.PKCEVerifier for the callback.
// In the callback (URL is http://REDIRECT_TO_URL?code=CODE):
var session = await client.ExchangeCodeForSession(state.PKCEVerifier, code);
Single Sign-On (SSO)
SSO lets an enterprise account sign in across many apps (Okta, Microsoft Entra, Google Workspace, …). Add an SSO provider to your project via the Supabase CLI first — see the SSO guide. The flow mirrors OAuth; the GoTrue server handles the SAML exchange and appends session info to your redirect URL:
var ssoResponse = await client.SignInWithSSO("supabase.io", new SignInWithSSOOptions
{
RedirectTo = "https://localhost:3000/welcome"
});
// Send the user to ssoResponse.Uri. On return (URL carries the session), exchange it:
var session = await client.GetSessionFromUrl(url);
Token refresh
GoTrue servers typically expire the access token after an hour, and the client refreshes it in the
background when ~20% of that time remains. If your server issues long-lived tokens (up to a week), you
can cap how long the client waits between refreshes with MaximumRefreshWaitTime (seconds, default
14400 — four hours). With a one-hour expiry nothing changes; with a week-long expiry, a user who
opens the app at least once a week never has to re-authenticate.
Offline support
The client supports online/offline usage through an Online flag, which you can drive from device
network status:
var client = new Client(new ClientOptions { AllowUnconfirmedUserSessions = true });
var status = new NetworkStatus { Client = client };
await status.StartAsync();
This applies only to the stateful Client and its managed sessions — admin JWT methods and the
StatelessClient are unaffected. By default this changes nothing for existing code.
Observability (OpenTelemetry)
The client emits traces and metrics through System.Diagnostics, so you can wire them into
OpenTelemetry (or any ActivityListener / MeterListener) without taking a dependency on the
OpenTelemetry packages. Emission is zero-cost while nothing is listening, so it is always on and stays
silent until you subscribe.
Register the client's ActivitySource and Meter by name. Use the GotrueDiagnostics.SourceName
constant rather than hardcoding the string, so a typo becomes a compile error instead of a silent
no-op:
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using Supabase.Gotrue;
// Requires OpenTelemetry.Extensions.Hosting and an exporter package (e.g. OTLP) in your app.
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddSource(GotrueDiagnostics.SourceName)
.AddOtlpExporter())
.WithMetrics(metrics => metrics
.AddMeter(GotrueDiagnostics.SourceName)
.AddOtlpExporter());
Once subscribed you get:
- A span per public operation (
gotrue.sign_in,gotrue.refresh_token, …) with a child client span for the underlying HTTP call following OpenTelemetry HTTP conventions (method, status code, and a sanitized URL — the query string, which carries grant types and API keys, is never recorded). - A
supabase.gotrue.http.request.durationhistogram (seconds), tagged with method, host, path, and status code.
If you are not using the OpenTelemetry SDK, a raw listener works too:
using System.Diagnostics;
using Supabase.Gotrue;
using var listener = new ActivityListener
{
ShouldListenTo = source => source.Name == GotrueDiagnostics.SourceName,
Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllData,
ActivityStopped = activity => Console.WriteLine($"{activity.OperationName} {activity.Duration.TotalMilliseconds}ms {activity.Status}")
};
ActivitySource.AddActivityListener(listener);
The older
AddDebugListener-based debug surface remains for logging, but OpenTelemetry is the recommended path for tracing and metrics.
Troubleshooting
I created a user but signing in throws an exception. Provided the credentials are correct, make sure the user has confirmed their email. Handling email confirmation in a desktop or mobile app means registering platform URL handlers, which can be fiddly (Windows, Apple, Android). Many find it simpler to deploy a small web page to handle confirmation, then have the app inspect the returned user to see if it is confirmed.
Contributing
Contributions are welcome. See the repository root for how to build and test the SDK.
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Supabase.Core (>= 8.1.0)
- System.Diagnostics.DiagnosticSource (>= 8.0.1)
- System.IdentityModel.Tokens.Jwt (>= 7.5.1)
- System.Text.Json (>= 8.0.5)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Supabase.Gotrue:
| Package | Downloads |
|---|---|
|
Supabase
A C# implementation of the Supabase client |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 8.1.0 | 325 | 9/7/2026 |
| 8.0.0 | 507 | 9/3/2026 |
| 6.3.2 | 2,432 | 8/28/2026 |
| 6.3.0 | 7,202 | 8/5/2026 |
| 6.2.0 | 7,615 | 7/22/2026 |
| 6.1.0 | 3,856 | 7/15/2026 |
| 6.0.3 | 699,972 | 7/26/2024 |
| 6.0.2 | 2,918 | 7/25/2024 |
| 6.0.1 | 368 | 7/19/2024 |
| 6.0.0 | 1,512 | 7/14/2024 |
| 5.0.6 | 21,454 | 6/29/2024 |
| 5.0.5 | 15,920 | 6/11/2024 |
| 5.0.4 | 382 | 6/9/2024 |
| 5.0.3 | 476 | 5/31/2024 |
| 5.0.2 | 5,790 | 5/20/2024 |
| 5.0.1 | 9,790 | 5/16/2024 |
| 5.0.0 | 22,720 | 4/21/2024 |