Reference
AuthServer API Reference
Complete method reference for login, signup, SSO, OIDC, token management, and admin operations.
Complete reference for every public method in the AuthServer module.
| Task | Start here |
|---|---|
| Login / signup | SqlOSAuthService — password and Email OTP sections below |
| MFA / TOTP | SqlOSAuthService MFA methods and SqlOSSettingsService MFA policy methods |
| Token validation | ValidateAccessTokenAsync |
| Admin CRUD | SqlOSAdminService |
| OIDC social | SqlOSOidcAuthService — Google, Microsoft, GitHub, Apple, and custom providers |
| SAML SSO | SqlOSSsoAuthorizationService |
Core authentication service. Handles login, signup, sessions, tokens, and password management.
Start, resolve, approve, deny, and poll a CLI/device OAuth request.
var start = await authService.StartDeviceAuthorizationAsync(
new SqlOSDeviceAuthorizationStartRequest(
ClientId: "acme-cli",
Scope: "openid offline_access",
Resource: "https://api.acme.com"),
httpContext,
ct);
var resolved = await authService.ResolveDeviceAuthorizationAsync(
start.UserCode,
currentUser,
ct);
await authService.ApproveDeviceAuthorizationAsync(
new SqlOSDeviceAuthorizationApprovalRequest(start.UserCode, organizationId),
currentUser,
authenticationMethod: "password",
httpContext,
ct);
var tokenResult = await authService.PollDeviceAuthorizationAsync(
new SqlOSDeviceTokenPollRequest("acme-cli", start.DeviceCode, "https://api.acme.com"),
httpContext,
ct);Browser/CLI clients normally use the RFC endpoints instead:
POST /sqlos/auth/device_authorizationGET /sqlos/auth/devicePOST /sqlos/auth/token with grant_type=urn:ietf:params:oauth:grant-type:device_codeHeadless browser UIs still start with GET /sqlos/auth/device?user_code=.... SqlOS creates a normal headless authorization request, then your app loads /sqlos/auth/headless/requests/{requestId} and approves or denies with /sqlos/auth/headless/device/approve or /sqlos/auth/headless/device/deny using the requestId.
See CLI OAuth.
Authenticate a user with email and password. If the user belongs to multiple organizations and no OrganizationId is specified, returns RequiresOrganizationSelection = true with a PendingAuthToken and the list of organizations.
var result = await authService.LoginWithPasswordAsync(
new SqlOSPasswordLoginRequest(
Email: request.Email,
Password: request.Password,
ClientId: "my-app",
OrganizationId: null),
httpContext);
if (result.RequiresOrganizationSelection)
return Results.Ok(new
{
requiresOrgSelection = true,
pendingAuthToken = result.PendingAuthToken,
organizations = result.Organizations
});
return Results.Ok(result.Tokens);Parameters
| Name | Type | Description |
|---|---|---|
request | SqlOSPasswordLoginRequest | Login credentials. |
httpContext | HttpContext | Current HTTP context (used for IP and user agent). |
cancellationToken | CancellationToken | Optional cancellation token. |
SqlOSPasswordLoginRequest
| Field | Type | Description |
|---|---|---|
Email | string | User's email address. |
Password | string | User's password. |
ClientId | string? | Client application ID. |
OrganizationId | string? | If set, skips org selection and logs in directly. |
Returns
Task<SqlOSLoginResult>
| Field | Type | Description |
|---|---|---|
RequiresOrganizationSelection | bool | true if the user must pick an org before tokens can be issued. |
PendingAuthToken | string? | Temporary token for SelectOrganizationAsync. |
Organizations | IReadOnlyList<SqlOSOrganizationOption> | Available organizations. |
Tokens | SqlOSTokenResponse? | Issued tokens (null if org selection required). |
RequiresMfa | bool | true if a second-factor challenge is required before tokens can be issued. |
MfaToken | string? | Temporary token for the MFA challenge or forced enrollment flow. |
RequiresMfaEnrollment | bool | true if the user must enroll a TOTP authenticator before continuing. |
MfaMethods | IReadOnlyList<string>? | Available factors such as totp and recovery_code. |
Inspect the user's MFA status:
var status = await authService.GetMfaStatusAsync(userId, organizationId, ct);List confirmed and pending authenticators:
var authenticators = await authService.ListMfaAuthenticatorsAsync(userId, ct);Start voluntary account enrollment:
var enrollment = await authService.StartTotpEnrollmentAsync(
userId,
new SqlOSTotpEnrollmentStartRequest("Authenticator app"),
organizationId,
ct);SqlOSTotpEnrollmentStartResult includes Secret, ProvisioningUri, QrCodeDataUrl, EnrollmentToken, and ExpiresAt.
Verify enrollment:
var result = await authService.VerifyTotpEnrollmentAsync(
new SqlOSTotpEnrollmentVerifyRequest(enrollment.EnrollmentToken, code),
httpContext,
ct);SqlOSTotpEnrollmentVerifyResult includes the confirmed AuthenticatorId and one-time RecoveryCodes.
When LoginWithPasswordAsync, SignUpAsync, Email OTP verification, hosted OAuth, or headless OAuth returns RequiresMfa = true, finish the challenge with:
var result = await authService.VerifyMfaChallengeAsync(
new SqlOSMfaChallengeVerifyRequest(mfaToken, code),
httpContext,
ct);For forced enrollment:
var enrollment = await authService.StartTotpEnrollmentForChallengeAsync(
mfaToken,
new SqlOSTotpEnrollmentStartRequest("Authenticator app"),
ct);
var result = await authService.VerifyTotpEnrollmentAsync(
new SqlOSTotpEnrollmentVerifyRequest(
enrollment.EnrollmentToken,
code,
mfaToken),
httpContext,
ct);Direct HTTP endpoints:
| Endpoint | Purpose |
|---|---|
POST /sqlos/auth/mfa/challenge/verify | Verify TOTP or recovery code for an MFA token |
POST /sqlos/auth/mfa/challenge/totp/enroll/start | Start forced TOTP enrollment for an MFA token |
POST /sqlos/auth/mfa/challenge/totp/enroll/verify | Verify forced TOTP enrollment and complete the MFA challenge |
POST /sqlos/auth/headless/mfa/verify | Headless MFA challenge verification |
POST /sqlos/auth/headless/mfa/totp/enroll/start | Headless forced TOTP enrollment start |
POST /sqlos/auth/headless/mfa/totp/enroll/verify | Headless forced TOTP enrollment verification |
See MFA and TOTP.
Create a new user with email and password. Optionally creates an organization at the same time.
var result = await authService.SignUpAsync(
new SqlOSSignupRequest(
DisplayName: "Jane Doe",
Email: "jane@example.com",
Password: "s3cureP@ss",
OrganizationName: "Acme Corp",
ClientId: "my-app",
OrganizationId: null),
httpContext);
return Results.Ok(result.Tokens);Parameters
| Name | Type | Description |
|---|---|---|
request | SqlOSSignupRequest | Signup details. |
httpContext | HttpContext | Current HTTP context. |
SqlOSSignupRequest
| Field | Type | Description |
|---|---|---|
DisplayName | string | User's display name. |
Email | string | User's email address. |
Password | string | User's password. |
OrganizationName | string? | If set, a new organization is created and the user is added. |
ClientId | string? | Client application ID. |
OrganizationId | string? | Join existing org instead of creating one. |
Returns
Task<SqlOSLoginResult> — same shape as LoginWithPasswordAsync.
Start and verify passwordless sign-in for an existing user.
var start = await authService.RequestEmailOtpAsync(
new SqlOSEmailOtpStartRequest(
Email: "jane@example.com",
ClientId: "my-app",
OrganizationId: null),
httpContext,
ct);
var result = await authService.VerifyEmailOtpAsync(
new SqlOSEmailOtpVerifyRequest(
ChallengeToken: start.ChallengeToken,
Code: codeFromEmail),
httpContext,
ct);RequestEmailOtpAsync returns ChallengeToken, MaskedEmail, ExpiresAt, and NextAllowedSendAt. VerifyEmailOtpAsync returns SqlOSLoginResult.
Start and verify passwordless signup.
var start = await authService.RequestEmailOtpSignupAsync(
new SqlOSEmailOtpSignupStartRequest(
DisplayName: "Jane Doe",
Email: "jane@example.com",
ClientId: "my-app",
OrganizationName: "Acme",
OrganizationId: null,
CustomFields: null),
httpContext,
ct);
var result = await authService.VerifyEmailOtpSignupAsync(
new SqlOSEmailOtpSignupVerifyRequest(
SignupToken: start.SignupToken,
ChallengeToken: start.ChallengeToken,
Code: codeFromEmail),
httpContext,
ct);Signup verification creates the user, marks the primary email verified, creates the organization or membership, creates a session, and returns SqlOSLoginResult.
Create and optionally send an organization membership invitation.
var invite = await authService.CreateEmailInvitationAsync(
new SqlOSCreateEmailInvitationRequest(
OrganizationId: org.Id,
Email: "teammate@example.com",
Role: "member",
ClientId: "my-app",
RedirectUri: "https://app.example.com/auth/callback",
CustomFields: null),
httpContext,
ct);The returned InviteUrl contains the opaque token. SqlOS stores only the token hash.
Accept an invitation for an already-authenticated or already-created user.
var acceptance = await authService.AcceptEmailInvitationAsync(
new SqlOSAcceptEmailInvitationRequest(
InvitationToken: token,
UserId: user.Id),
httpContext,
ct);The invited email must match the user's normalized email. Acceptance creates or reactivates membership, marks the email verified, and consumes the invitation.
Create a passwordless invited user and return tokens without sending a second OTP code.
var result = await authService.AcceptEmailInvitationSignupAsync(
new SqlOSAcceptEmailInvitationSignupRequest(
InvitationToken: token,
DisplayName: "Jane Doe",
ClientId: "my-app",
CustomFields: null),
httpContext,
ct);Use this for backend-owned invite signup flows. Hosted and headless browser flows use their invitation endpoints.
var resent = await authService.ResendEmailInvitationAsync(
new SqlOSResendEmailInvitationRequest(invite.Id),
httpContext,
ct);
var revoked = await authService.RevokeEmailInvitationAsync(
new SqlOSRevokeEmailInvitationRequest(invite.Id, "wrong-email"),
httpContext,
ct);Resending invalidates the previous token. Revocation prevents future acceptance.
Complete login by selecting an organization. Called when LoginWithPasswordAsync returns RequiresOrganizationSelection = true.
var tokens = await authService.SelectOrganizationAsync(
new SqlOSSelectOrganizationRequest(
PendingAuthToken: result.PendingAuthToken!,
OrganizationId: selectedOrgId),
httpContext);
return Results.Ok(tokens);Parameters
| Name | Type | Description |
|---|---|---|
request.PendingAuthToken | string | The pending auth token from the login result. |
request.OrganizationId | string | The selected organization ID. |
httpContext | HttpContext | Current HTTP context. |
Returns
Task<SqlOSTokenResponse>
| Field | Type | Description |
|---|---|---|
AccessToken | string | JWT access token. |
RefreshToken | string | Opaque refresh token. |
SessionId | string | Session identifier. |
ClientId | string | Client application ID. |
OrganizationId | string? | Organization the user is logged into. |
AccessTokenExpiresAt | DateTime | Access token expiry (UTC). |
RefreshTokenExpiresAt | DateTime | Refresh token expiry (UTC). |
Exchange a refresh token for new access and refresh tokens.
var tokens = await authService.RefreshAsync(
new SqlOSRefreshRequest(
RefreshToken: request.RefreshToken,
OrganizationId: null));
return Results.Ok(tokens);Parameters
| Name | Type | Description |
|---|---|---|
request.RefreshToken | string | The current refresh token. |
request.OrganizationId | string? | Optionally switch organization during refresh. |
Returns
Task<SqlOSTokenResponse> — new token pair. The previous refresh token is revoked.
Revoke a session by refresh token or session ID. Provide at least one.
await authService.LogoutAsync(
refreshToken: request.RefreshToken,
sessionId: null);
return Results.Ok();Parameters
| Name | Type | Description |
|---|---|---|
refreshToken | string? | The refresh token to revoke. |
sessionId | string? | The session ID to revoke. |
Returns
Task — completes when the session/token is invalidated.
Revoke all sessions for a user.
await authService.LogoutAllAsync(userId);Parameters
| Name | Type | Description |
|---|---|---|
userId | string | The user whose sessions to revoke. |
Returns
Task
Validate a JWT access token for a protected resource server and extract the claims principal. The expected audience is required so a token minted for another API cannot be accepted by this API.
var validated = await authService.ValidateAccessTokenAsync(
rawToken,
expectedAudience: "https://api.example.com");
if (validated is null)
return Results.Unauthorized();
var userId = validated.UserId;
var orgId = validated.OrganizationId;Parameters
| Name | Type | Description |
|---|---|---|
rawToken | string | The raw JWT access token string. |
expectedAudience | string | The required JWT aud value for this resource server. |
Returns
Task<SqlOSValidatedToken?> — null if the token is invalid or expired.
| Field | Type | Description |
|---|---|---|
Principal | ClaimsPrincipal | The validated claims principal. |
SessionId | string | The session the token belongs to. |
UserId | string? | The authenticated user's ID. |
OrganizationId | string? | The organization from the token. |
ClientId | string? | The client application ID. |
Audience | string? | The JWT audience claim. |
Validates issuer, signature, lifetime, and session state without validating the JWT aud claim. This method is obsolete and is only for diagnostics or token introspection flows that do not authenticate a protected API request.
Resource servers must use ValidateAccessTokenAsync(rawToken, expectedAudience, cancellationToken).
Exchange an authorization code for tokens. Used in SSO callback flows.
var tokens = await authService.ExchangeCodeAsync(
new SqlOSExchangeCodeRequest(
Code: code,
ClientId: "my-app"),
httpContext);Parameters
| Name | Type | Description |
|---|---|---|
request.Code | string | The authorization code. |
request.ClientId | string | The client application ID. |
httpContext | HttpContext | Current HTTP context. |
Returns
Task<SqlOSTokenResponse>
Create a one-time password reset token and send the built-in password reset email. Public endpoints use this flow and return an enumeration-safe response; they do not return the raw reset token.
var result = await authService.RequestPasswordResetEmailAsync(
new SqlOSSendPasswordResetEmailRequest(
Email: request.Email,
ResetUrlTemplate: "https://app.example.com/reset-password?token={token}",
ClientId: "web"),
httpContext,
ct);Use ResetUrlTemplate: null to link to SqlOS' hosted reset form at /sqlos/auth/password/reset?token=....
Public routes:
POST /sqlos/auth/password/forgot
POST /sqlos/auth/password/reset-email
POST /sqlos/auth/headless/password/forgot
POST /sqlos/auth/headless/password/reset/password/forgot and /password/reset-email return masked email, expiry, next send time, and a generic message whether or not the email maps to a resettable local-password account.
Generate a one-time password reset token for custom server-side reset flows. Most apps should use RequestPasswordResetEmailAsync, which sends the built-in auth.password-reset template and keeps bearer tokens out of browser-facing responses.
var token = await authService.CreatePasswordResetTokenAsync(
new SqlOSForgotPasswordRequest(Email: request.Email));
Parameters
| Name | Type | Description |
|---|---|---|
request.Email | string | The user's email address. |
Returns
Task<string> — the raw reset token to deliver to the user.
Generate a reset token and send a password reset email with delivery details. Use this for trusted server/admin workflows; use RequestPasswordResetEmailAsync for public browser or headless flows.
var result = await authService.SendPasswordResetEmailAsync(
new SqlOSSendPasswordResetEmailRequest(
Email: request.Email,
ResetUrlTemplate: "https://app.example.com/reset-password?token={token}"),
httpContext);Parameters
| Name | Type | Description |
|---|---|---|
request.Email | string | The user's email address. |
request.ResetUrlTemplate | string? | Optional reset URL template. If it includes {token}, SqlOS replaces it with the escaped reset token. |
request.ClientId | string? | Optional client/application key used for rate limiting and audit context. |
Returns
Task<SqlOSPasswordResetEmailResult> — masked email, expiry, delivery id/status, provider message id, and sanitized failure detail.
Consume a password reset token and set the new password for an active user that already has a local password credential.
await authService.ResetPasswordAsync(
new SqlOSResetPasswordRequest(
Token: request.Token,
NewPassword: request.NewPassword));Parameters
| Name | Type | Description |
|---|---|---|
request.Token | string | The reset token from the delivered password reset link. |
request.NewPassword | string | The new password. |
Returns
Task
Generate an email verification token. Send the returned token to the user via email.
var token = await authService.CreateEmailVerificationTokenAsync(
new SqlOSCreateVerificationTokenRequest(Email: request.Email));Parameters
| Name | Type | Description |
|---|---|---|
request.Email | string | The email to verify. |
Returns
Task<string> — the raw verification token.
Consume a verification token and mark the email as verified.
await authService.VerifyEmailAsync(
new SqlOSVerifyEmailRequest(Token: request.Token));Parameters
| Name | Type | Description |
|---|---|---|
request.Token | string | The verification token. |
Returns
Task
Directly issue session tokens for a user. Used after OIDC/SSO flows complete, when you have a resolved user but need to create the SqlOS session.
var tokens = await authService.CreateSessionTokensForUserAsync(
user, client, organizationId: org.Id,
authenticationMethod: "oidc",
userAgent: httpContext.Request.Headers.UserAgent,
ipAddress: httpContext.Connection.RemoteIpAddress?.ToString());Parameters
| Name | Type | Description |
|---|---|---|
user | SqlOSUser | The authenticated user entity. |
client | SqlOSClientApplication | The client application. |
organizationId | string? | The organization to scope the session to. |
authenticationMethod | string | How the user authenticated (e.g., "password", "oidc", "saml"). |
userAgent | string? | Browser user agent. |
ipAddress | string? | Client IP address. |
Returns
Task<SqlOSTokenResponse>
Administrative operations for managing organizations, users, memberships, clients, and SSO connections.
Create a new organization.
var org = await adminService.CreateOrganizationAsync(
new SqlOSCreateOrganizationRequest(
Name: "Acme Corp",
Slug: "acme",
PrimaryDomain: "acme.com"));Parameters
| Name | Type | Description |
|---|---|---|
request.Name | string | Organization display name. |
request.Slug | string? | URL-safe slug. Auto-generated from name if null. |
request.PrimaryDomain | string? | Primary email domain for SSO/home-realm discovery. |
Returns
Task<SqlOSOrganization> — the created organization entity.
Create a new user.
var user = await adminService.CreateUserAsync(
new SqlOSCreateUserRequest(
DisplayName: "Jane Doe",
Email: "jane@acme.com",
Password: "s3cureP@ss"));Parameters
| Name | Type | Description |
|---|---|---|
request.DisplayName | string | Display name. |
request.Email | string | Email address (normalized and deduplicated). |
request.Password | string? | Password. If null, the user can only log in via SSO/OIDC. |
Returns
Task<SqlOSUser> — the created user entity.
Add a user to an organization with a role.
var membership = await adminService.CreateMembershipAsync(
organizationId: org.Id,
new SqlOSCreateMembershipRequest(
UserId: user.Id,
Role: "admin"));Parameters
| Name | Type | Description |
|---|---|---|
organizationId | string | The organization to add the user to. |
request.UserId | string | The user to add. |
request.Role | string | The membership role (e.g., "admin", "member"). |
Returns
Task<SqlOSMembership> — the created membership.
Register a client application.
var client = await adminService.CreateClientAsync(
new SqlOSCreateClientRequest(
ClientId: "my-app",
Name: "My Application",
Audience: "https://api.example.com",
RedirectUris: ["https://example.com/callback"]));Parameters
| Name | Type | Description |
|---|---|---|
request.ClientId | string | Unique client identifier. |
request.Name | string | Display name. |
request.Audience | string | The JWT audience claim. |
request.RedirectUris | List<string> | Allowed redirect URIs. |
Returns
Task<SqlOSClientApplication> — the created client.
Create a SAML SSO connection draft. After creating the draft, upload IdP metadata with ImportSsoMetadataAsync.
var draft = await adminService.CreateSsoConnectionDraftAsync(
new SqlOSCreateSsoConnectionDraftRequest(
OrganizationId: org.Id,
DisplayName: "Acme Okta SSO",
PrimaryDomain: "acme.com",
AutoProvisionUsers: true,
AutoLinkByEmail: true));
// Now import the metadata:
await adminService.ImportSsoMetadataAsync(
draft.Id,
new SqlOSImportSsoMetadataRequest(MetadataXml: xml));Parameters
| Name | Type | Description |
|---|---|---|
request.OrganizationId | string | The organization this connection belongs to. |
request.DisplayName | string | Display name for the connection. |
request.PrimaryDomain | string? | Email domain for home-realm discovery. |
request.AutoProvisionUsers | bool | Create users on first SSO login. |
request.AutoLinkByEmail | bool | Link existing users by email during SSO. |
Returns
Task<SqlOSSsoConnectionDraft> — the created draft with an ID.
Upload SAML IdP metadata XML for an existing SSO connection draft.
await adminService.ImportSsoMetadataAsync(
connectionId,
new SqlOSImportSsoMetadataRequest(MetadataXml: metadataXml));Parameters
| Name | Type | Description |
|---|---|---|
connectionId | string | The SSO connection ID. |
request.MetadataXml | string | The raw SAML IdP metadata XML. |
Returns
Task
Register an OIDC/social login provider (Google, Microsoft, GitHub, Apple, or custom).
var conn = await adminService.CreateOidcConnectionAsync(
new SqlOSCreateOidcConnectionRequest(
ProviderType: SqlOSOidcProviderType.Google,
DisplayName: "Sign in with Google",
ClientId: "google-client-id",
ClientSecret: "google-client-secret",
AllowedCallbackUris: ["https://example.com/callback"],
UseDiscovery: true,
DiscoveryUrl: "https://accounts.google.com/.well-known/openid-configuration",
// remaining fields null/default
Issuer: null, AuthorizationEndpoint: null,
TokenEndpoint: null, UserInfoEndpoint: null,
JwksUri: null, MicrosoftTenant: null,
Scopes: null, ClaimMapping: null,
ClientAuthMethod: null, UseUserInfo: null));Parameters
| Name | Type | Description |
|---|---|---|
request.ProviderType | SqlOSOidcProviderType | Google, Microsoft, GitHub, Apple, or Custom. |
request.DisplayName | string | Display name for the provider. |
request.ClientId | string | OAuth client ID from the provider. |
request.ClientSecret | string? | OAuth client secret. |
request.AllowedCallbackUris | List<string> | Allowed callback URIs. |
request.UseDiscovery | bool | Whether to use OIDC discovery. |
request.DiscoveryUrl | string? | The .well-known/openid-configuration URL. |
request.MicrosoftTenant | string? | Azure AD tenant ID (Microsoft only). |
request.Scopes | List<string>? | Custom scopes to request. |
Returns
Task<SqlOSOidcConnection> — the created connection.
Seed a GitHub social login connection from startup code. Use this for repeatable local, preview, and production environments where the dashboard should already show GitHub after the first boot.
options.AuthServer.SeedGitHubConnection(
clientId: builder.Configuration["SqlOS:Oidc:GitHub:ClientId"]!,
clientSecret: builder.Configuration["SqlOS:Oidc:GitHub:ClientSecret"]!,
"https://your-app.example.com/sqlos/auth/oidc/callback");Parameters
| Name | Type | Description |
|---|---|---|
clientId | string | GitHub OAuth App client ID. |
clientSecret | string | GitHub OAuth App client secret. |
allowedCallbackUris | params string[] | SqlOS provider callback URIs to allow. Default base path form is {AuthServer.PublicOrigin}/sqlos/auth/oidc/callback. |
The seeded connection uses provider type GitHub, display name GitHub, protocol OAuthProfile, default scopes read:user and user:email, and the built-in GitHub authorization/token/profile endpoints.
See GitHub OIDC.
List all organizations a user belongs to.
var orgs = await adminService.GetUserOrganizationsAsync(userId);
// Returns: [{ Id, Slug, Name, Role }, ...]Parameters
| Name | Type | Description |
|---|---|---|
userId | string | The user's ID. |
Returns
Task<List<SqlOSOrganizationOption>>
| Field | Type | Description |
|---|---|---|
Id | string | Organization ID. |
Slug | string | Organization slug. |
Name | string | Organization name. |
Role | string | The user's role in this org. |
Check if a user belongs to an organization.
var isMember = await adminService.UserHasMembershipAsync(userId, orgId);Parameters
| Name | Type | Description |
|---|---|---|
userId | string | The user's ID. |
organizationId | string | The organization ID. |
Returns
Task<bool>
Normalize an email address (lowercase, trim).
var email = SqlOSAdminService.NormalizeEmail(" Jane@ACME.com ");
// "jane@acme.com"Parameters
| Name | Type | Description |
|---|---|---|
email | string | The email to normalize. |
Returns
string
Determines how a user should authenticate based on their email domain.
Home realm discovery checks active verified organization domains first. If no verified claim matches, it falls back to the legacy operator-managed PrimaryDomain value. This lets self-serve delegated SSO setup prove ownership through DNS without breaking existing dashboard-managed tenants.
Look up the authentication method for an email address. Returns whether the domain maps to an SSO connection, OIDC provider, or password login.
var result = await hrdService.DiscoverAsync(
new SqlOSHomeRealmDiscoveryRequest(Email: request.Email));
// result.Mode: "password" | "sso" | "oidc"
// result.ConnectionId: SSO/OIDC connection ID (if applicable)
// result.OrganizationId: matched org IDParameters
| Name | Type | Description |
|---|---|---|
request.Email | string | The email to discover. |
Returns
Task<SqlOSHomeRealmDiscoveryResult>
| Field | Type | Description |
|---|---|---|
Mode | string | Authentication mode: "password", "sso", or "oidc". |
OrganizationId | string? | Matched organization. |
OrganizationName | string? | Organization display name. |
PrimaryDomain | string? | The matched domain. |
ConnectionId | string? | SSO or OIDC connection ID to use. |
Manages self-serve organization domain claims for delegated SSO setup. The default verification path is DNS TXT through ISqlOSDomainDnsVerifier; hosts can replace that interface without depending on Azure or any specific DNS provider.
Create or reuse a pending domain claim and return the TXT ownership record.
var domain = await organizationDomainService.StartVerificationAsync(
organizationId,
new SqlOSSsoPortalDomainRequest("acme.com"),
httpContext,
userId,
ct);The ownership record is shaped as:
| Field | Example |
|---|---|
Type | TXT |
Name | _sqlos-verify.acme.com |
Value | sqlos-domain-verification=... |
Hosts can customize the TXT record name and value prefixes with SsoPortal.DomainVerificationRecordPrefix and SsoPortal.DomainVerificationRecordValuePrefix.
Check the TXT record and mark the claim active when the expected value is present.
var active = await organizationDomainService.ConfirmOwnershipAsync(
organizationId,
domainId,
httpContext,
ct);SqlOSOrganizationDomainResult.Status is pending_ownership, active, or revoked.
SAML SSO authorization flow.
Start a SAML SSO login flow. Returns the IdP authorization URL to redirect the user to.
var ssoResult = await ssoService.StartAuthorizationAsync(
new SqlOSSsoAuthorizationStartRequest(
Email: request.Email,
ClientId: "my-app",
RedirectUri: "https://example.com/callback",
State: state,
CodeChallenge: codeChallenge,
CodeChallengeMethod: "S256"));
// Redirect the user:
return Results.Redirect(ssoResult.AuthorizationUrl);Parameters
| Name | Type | Description |
|---|---|---|
request.Email | string | User's email (determines the SSO connection via domain). |
request.ClientId | string | Client application ID. |
request.RedirectUri | string | Where to redirect after SSO. |
request.State | string | CSRF state parameter. |
request.CodeChallenge | string | PKCE code challenge. |
request.CodeChallengeMethod | string | "S256". |
Returns
Task<SqlOSSsoAuthorizationStartResult>
| Field | Type | Description |
|---|---|---|
AuthorizationUrl | string | The SAML IdP URL to redirect to. |
OrganizationId | string | The matched organization. |
OrganizationName | string | Organization name. |
PrimaryDomain | string | The matched domain. |
Exchange a PKCE authorization code for tokens after the SAML SSO callback.
var tokens = await ssoService.ExchangeCodeAsync(
new SqlOSPkceExchangeRequest(
Code: code,
ClientId: "my-app",
RedirectUri: "https://example.com/callback",
CodeVerifier: codeVerifier),
httpContext);Parameters
| Name | Type | Description |
|---|---|---|
request.Code | string | The authorization code. |
request.ClientId | string | Client application ID. |
request.RedirectUri | string | Must match the original redirect URI. |
request.CodeVerifier | string | The PKCE code verifier. |
httpContext | HttpContext | Current HTTP context. |
Returns
Task<SqlOSTokenResponse>
OIDC/social login authorization flow — Google, Microsoft, GitHub, Apple, or custom providers.
List all enabled OIDC providers available for login.
var providers = await oidcService.ListEnabledProvidersAsync();
// [{ ConnectionId, ProviderType, DisplayName, ... }]Returns
Task<List<SqlOSOidcProviderInfo>>
Start an OIDC authorization flow. Returns the provider's authorization URL.
var result = await oidcService.StartAuthorizationAsync(
new SqlOSStartOidcAuthorizationRequest(
ConnectionId: connectionId,
Email: request.Email,
ClientId: "my-app",
CallbackUri: "https://example.com/oidc/callback",
State: state,
Nonce: nonce,
CodeChallenge: codeChallenge,
CodeChallengeMethod: "S256"),
ipAddress: httpContext.Connection.RemoteIpAddress?.ToString());
return Results.Redirect(result.AuthorizationUrl);Parameters
| Name | Type | Description |
|---|---|---|
request.ConnectionId | string | The OIDC connection to use. |
request.Email | string | User's email. |
request.ClientId | string | Client application ID. |
request.CallbackUri | string | OAuth callback URI. |
request.State | string | CSRF state. |
request.Nonce | string | Token replay prevention nonce. |
request.CodeChallenge | string | PKCE code challenge. |
request.CodeChallengeMethod | string | "S256". |
ipAddress | string? | Client IP for audit logging. |
Returns
Task<SqlOSStartOidcAuthorizationResult>
| Field | Type | Description |
|---|---|---|
AuthorizationUrl | string | Provider URL to redirect to. |
ConnectionId | string | The OIDC connection used. |
ProviderType | SqlOSOidcProviderType | Google, Microsoft, GitHub, Apple, or Custom. |
DisplayName | string | Provider display name. |
Complete the OIDC callback. Exchanges the authorization code with the provider, resolves the user, and returns session info.
var result = await oidcService.CompleteAuthorizationAsync(
new SqlOSCompleteOidcAuthorizationRequest(
ConnectionId: connectionId,
ClientId: "my-app",
CallbackUri: "https://example.com/oidc/callback",
Code: code,
CodeVerifier: codeVerifier,
Nonce: nonce,
UserPayloadJson: null),
ipAddress: httpContext.Connection.RemoteIpAddress?.ToString());
// result.UserId, result.Email, result.OrganizationId
// Now create a session:
var tokens = await authService.CreateSessionTokensForUserAsync(
user, client, result.OrganizationId,
result.AuthenticationMethod, userAgent, ipAddress);Parameters
| Name | Type | Description |
|---|---|---|
request.ConnectionId | string | The OIDC connection. |
request.ClientId | string | Client application ID. |
request.CallbackUri | string | Must match the original callback URI. |
request.Code | string | The authorization code from the provider. |
request.CodeVerifier | string | PKCE code verifier. |
request.Nonce | string | Must match the original nonce. |
Returns
Task<SqlOSCompleteOidcAuthorizationResult>
| Field | Type | Description |
|---|---|---|
UserId | string | Resolved or created user ID. |
Email | string | User's email from the provider. |
DisplayName | string | User's display name from the provider. |
OrganizationId | string? | Matched organization (if any). |
AuthenticationMethod | string | e.g., "oidc_google". |
Manage runtime security settings.
Get the effective security settings (with defaults applied).
var settings = await settingsService.GetResolvedSecuritySettingsAsync();
// settings.RefreshTokenLifetime, settings.SessionIdleTimeout, etc.Returns
Task<SqlOSResolvedSecuritySettings>
| Field | Type | Description |
|---|---|---|
RefreshTokenLifetime | TimeSpan | How long refresh tokens are valid. |
SessionIdleTimeout | TimeSpan | Session expires after this idle period. |
SessionAbsoluteLifetime | TimeSpan | Maximum session lifetime regardless of activity. |
Update the security settings.
await settingsService.UpdateSecuritySettingsAsync(
new SqlOSUpdateSecuritySettingsRequest(
RefreshTokenLifetimeMinutes: 1440,
SessionIdleTimeoutMinutes: 60,
SessionAbsoluteLifetimeMinutes: 10080));Parameters
| Name | Type | Description |
|---|---|---|
request.RefreshTokenLifetimeMinutes | int | Refresh token lifetime in minutes. |
request.SessionIdleTimeoutMinutes | int | Idle timeout in minutes. |
request.SessionAbsoluteLifetimeMinutes | int | Absolute lifetime in minutes. |
Returns
Task
Read and update global MFA settings:
var settings = await settingsService.GetMfaSettingsAsync(ct);
await settingsService.UpdateMfaSettingsAsync(
new SqlOSUpdateMfaSettingsRequest(
Enabled: true,
TotpEnabled: true,
UserSelfEnrollmentEnabled: true,
RecoveryCodesEnabled: true,
RequireForAllUsers: false,
RequireForOwnersAndAdmins: true,
RequiredRoles: ["owner", "admin"],
AvailableFactors: ["totp", "recovery_code"]),
ct);Read and update organization MFA policy:
var policy = await settingsService.GetOrganizationMfaPolicyAsync(
organizationId,
ct);
await settingsService.UpdateOrganizationMfaPolicyAsync(
organizationId,
new SqlOSUpdateOrganizationMfaPolicyRequest(
IsEnabled: true,
RequireMfaForAllUsers: true,
RequireMfaForOwnersAndAdmins: false,
UserSelfEnrollmentEnabled: true,
RecoveryCodesEnabled: true,
RequiredRoles: ["owner", "admin"],
AvailableFactors: ["totp", "recovery_code"]),
ct);Admin HTTP endpoints:
| Endpoint | Purpose |
|---|---|
GET /sqlos/admin/auth/api/settings/mfa | Read global MFA settings |
PUT /sqlos/admin/auth/api/settings/mfa | Update global MFA settings |
GET /sqlos/admin/auth/api/organizations/{organizationId}/mfa-policy | Read an organization's MFA policy |
PUT /sqlos/admin/auth/api/organizations/{organizationId}/mfa-policy | Update an organization's MFA policy |
Returned by all successful authentication flows.
public sealed record SqlOSTokenResponse(
string AccessToken,
string RefreshToken,
string SessionId,
string ClientId,
string? OrganizationId,
DateTime AccessTokenExpiresAt,
DateTime RefreshTokenExpiresAt);Returned by LoginWithPasswordAsync and SignUpAsync.
public sealed record SqlOSLoginResult(
bool RequiresOrganizationSelection,
string? PendingAuthToken,
IReadOnlyList<SqlOSOrganizationOption> Organizations,
SqlOSTokenResponse? Tokens,
bool RequiresMfa = false,
string? MfaToken = null,
bool RequiresMfaEnrollment = false,
IReadOnlyList<string>? MfaMethods = null);Returned by ValidateAccessTokenAsync.
public sealed record SqlOSValidatedToken(
ClaimsPrincipal Principal,
string SessionId,
string? UserId,
string? OrganizationId,
string? ClientId,
string? Audience);Used in multi-org selection flows.
public sealed record SqlOSOrganizationOption(
string Id,
string Slug,
string Name,
string Role);