SqlOS

Fine-Grained Auth

Syncing Auth to FGA

Sync AuthServer users and memberships into FGA subjects and grants.

4 sections

When using both AuthServer and FGA, you need to sync authenticated users into the FGA model so they can be authorized. The typical pattern is to sync on login.

The pattern#

After login, ensure the user exists as an FGA subject, the organization exists as an FGA resource, and the membership is mapped to a grant:

CSHARP
public async Task EnsureUserAccessAsync(
    string userId, string organizationId, CancellationToken ct)
{
    var user = await _context.Set<SqlOSUser>()
        .FirstAsync(x => x.Id == userId, ct);
    var organization = await _context.Set<SqlOSOrganization>()
        .FirstAsync(x => x.Id == organizationId, ct);
    var membership = await _context.Set<SqlOSMembership>()
        .FirstAsync(x => x.UserId == userId
            && x.OrganizationId == organizationId
            && x.IsActive, ct);
 
    await EnsureSubjectAsync(user, organizationId, ct);
    await EnsureOrganizationResourceAsync(organization, ct);
    await EnsureMembershipGrantAsync(userId, organizationId, membership.Role, ct);
}

What each step does#

EnsureSubjectAsync -- creates or updates SqlOSFgaSubject and SqlOSFgaUser for the authenticated user.

EnsureOrganizationResourceAsync -- creates an SqlOSFgaResource for the organization under root (if it doesn't exist).

EnsureMembershipGrantAsync -- creates a grant linking the user to a role on the organization resource, mapping the auth membership role to an FGA role:

Auth roleFGA role
admin or ownerorg_admin (full access)
everything elseorg_member (read access)

When to call#

Call EnsureUserAccessAsync after successful login, during token creation:

CSHARP
if (!string.IsNullOrWhiteSpace(tokens.OrganizationId))
{
    await fgaService.EnsureUserAccessAsync(
        user.Id, tokens.OrganizationId, ct);
}

The example app calls this in the token response helper, so every login automatically ensures the user has the right FGA grants based on their auth membership.

Why sync instead of query auth directly?#

FGA subjects and grants are stored in tables optimized for the authorization query (tree walk + table-valued function). By syncing auth data into FGA at login time, authorization checks run entirely in SQL without joining against auth tables at query time.