SuperTokens 1.1.0

dotnet add package SuperTokens --version 1.1.0
                    
NuGet\Install-Package SuperTokens -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SuperTokens" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SuperTokens" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="SuperTokens" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SuperTokens --version 1.1.0
                    
#r "nuget: SuperTokens, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SuperTokens@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SuperTokens&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=SuperTokens&version=1.1.0
                    
Install as a Cake Tool

SuperTokens .NET SDK (port of supertokens-golang)

A C# / .NET port of the SuperTokens Go backend SDK. Targets .NET 10, idiomatic C# (async/await, nullable reference types, exceptions instead of (value, error) tuples), System.Text.Json, and ASP.NET Core minimal-API / middleware integration (no MVC controllers).

Solution layout

SuperTokens.sln
Directory.Build.props          # shared: net10.0, nullable, implicit usings
CONVENTIONS.md                 # Go → C# porting contract
src/SuperTokens/               # the SDK (one class library, one assembly)
  Core/                        # namespace SuperTokens  — framework core
    Exceptions, Constants, Logger, Json, UserContext, Models,
    NormalisedUrlDomain, NormalisedUrlPath, Utils, Querier,
    RecipeModule, PostInitCallbacks, UserIdMapping,
    SuperTokensInstance, SuperTokensApi
  Ingredients/
    EmailDelivery/             # SuperTokens.Ingredients.EmailDelivery (MailKit/SMTP)
    SmsDelivery/               # SuperTokens.Ingredients.SmsDelivery (Twilio)
  Recipe/
    Jwt, OpenId, Session, Multitenancy, ThirdParty, EmailVerification,
    UserRoles, EmailPassword, Passwordless, UserMetadata, Dashboard
test/SuperTokens.Tests/        # xUnit tests

Unlike Go (where each recipe is a separate package and import cycles are illegal), the entire SDK is one assembly, so recipes may reference each other freely. Namespaces still mirror the Go package tree (SuperTokens.Recipe.<Name>).

Design decisions

  • map[string]interface{}Dictionary<string, object?>. A custom InferredTypesConverter (in Core/Json.cs) makes System.Text.Json deserialize into native CLR types (double / bool / string / Dictionary / List), matching Go's encoding/json semantics.
  • Errors → exceptions. SuperTokensException (base) and BadInputException (→ HTTP 400). Functions that returned (T, error) now return T and throw.
  • IO is async. The querier uses HttpClient; everything reaching the core is async Task.
  • Overridable interfaces. Go's "struct of function pointers + Override" pattern is ported as sealed classes with nullable delegate properties.
  • Web layer. Go's net/http middleware/handler model maps to ASP.NET Core HttpContext + RequestDelegate. Register with app.UseSuperTokens().

Usage sketch (minimal API)

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

await SuperTokensApi.Init(new SuperTokensConfig
{
    Supertokens = new ConnectionInfo { ConnectionUri = "http://localhost:3567" },
    AppInfo = new AppInfo
    {
        AppName = "My App",
        ApiDomain = "http://localhost:3001",
        WebsiteDomain = "http://localhost:3000",
    },
    RecipeList = new List<RecipeFactory>
    {
        // Session.Init(), EmailPassword.Init(), ...
    },
});

app.UseSuperTokens();              // dispatches SuperTokens recipe APIs
app.MapGet("/hello", () => "hi");  // your own minimal-API endpoints
app.Run();

Protecting your own endpoints

Don't hand-roll auth checks — wrap an endpoint (or a whole route group) with RequireSession(). It verifies the access token, and on a missing / expired / invalid session it writes the correct response itself (a 401, or a "try refresh token" 401 that tells the frontend to call the refresh endpoint) and skips your handler. Inside a protected handler, read the verified session with Session.GetSessionFromRequestContext(ctx).

using SuperTokens.AspNetCore;            // RequireSession()
using SuperTokens.Recipe.Session;        // Session, VerifySessionOptions
using SuperTokens.Recipe.Session.SessModels;

app.UseSuperTokens();   // must come before your endpoints

// Protected — runs only with a valid session
app.MapGet("/user/profile", (HttpContext ctx) =>
{
    var session = Session.GetSessionFromRequestContext(ctx)!;
    return Results.Ok(new
    {
        userId  = session.GetUserId(),
        payload = session.GetAccessTokenPayload(),
    });
}).RequireSession();

// Optional session — handler still runs when there's no session
app.MapGet("/maybe", (HttpContext ctx) =>
{
    var session = Session.GetSessionFromRequestContext(ctx); // null if not signed in
    return Results.Ok(new { signedIn = session is not null });
}).RequireSession(new VerifySessionOptions { SessionRequired = false });

// Protect a whole group
var secure = app.MapGroup("/api").RequireSession();
secure.MapGet("/orders", (HttpContext ctx) => Results.Ok(/* ... */));

Notes:

  • app.UseSuperTokens() must be registered before your endpoints (it wires the /auth/* recipe routes and the shared error handler that turns session failures into proper responses).
  • For role/permission checks, pass claim validators via VerifySessionOptions.OverrideGlobalClaimValidators, or read session.GetAccessTokenPayload() and check it yourself.
  • Avoid calling Session.GetSession(req, res) directly in a custom endpoint unless you wrap it: with SessionRequired defaulting to true it throws UnauthorisedError / TryRefreshTokenError, and those only become proper HTTP responses when routed through the SuperTokens error handler — which RequireSession() does for you.

Status

Layer State
Core framework (Core/) ✅ ported & building; URL-normalisation + version tests pass
Ingredients (email/SMS) ✅ ported & building
Recipes ✅ all 11 ported & building
Integration tests ✅ 22 tests across 8 recipes verified against a live supertokens-core + Postgres

Known limitations / gaps

  • Public Suffix List. Utils.GetTopLevelDomainForSameSiteResolution uses a last-two-labels heuristic instead of the PSL that Go uses (golang.org/x/net/publicsuffix). Multi-level suffixes (e.g. .co.uk) are not resolved precisely. Consider bundling a PSL library for production.
  • Querier GET cache. The per-request core-call cache keyed by params+headers is simplified; cache invalidation hooks exist but the GET read-through cache is not fully reproduced.
  • See per-recipe notes for recipe-specific gaps.

Running the tests

# Fast unit tests (no Docker)
dotnet test test/SuperTokens.Tests

# Integration tests — require Docker. Testcontainers starts a real
# supertokens-core backed by a real PostgreSQL (both on a shared network) and the
# SDK runs emailpassword sign-up/sign-in and session create/verify/revoke against it.
dotnet test test/SuperTokens.IntegrationTests

Images (both overridable via env vars):

Container Default Override
Core supertokens/supertokens-postgresql:10.0.0 SUPERTOKENS_CORE_IMAGE
Database postgres:16-alpine SUPERTOKENS_POSTGRES_IMAGE

The core is pinned to a version that advertises CDI 3.1 (the version this SDK targets). Testcontainers' Ryuk cleans up both containers and the network automatically.

Reference source

The original Go source is cloned (git-ignored) at _src_golang/ for reference during the port.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 153 6/12/2026
1.0.0 113 6/12/2026