Protect a Web API
Validate Signward access tokens in your ASP.NET Core or FastAPI backend in under 10 lines.
Any REST backend can delegate authentication to Signward by validating the JWT access token on every request. No cookies, no redirects — just a bearer header.
How it works
- Your frontend (SPA, mobile, server-rendered app) obtains an access token from Signward via the OIDC flow.
- It calls your backend with
Authorization: Bearer <jwt>. - Your backend validates the token against Signward's JWKS (public keys at
/.well-known/jwks.json) — signature, issuer, audience, expiration. - If valid, the token's claims (
sub,tenant_id,roles,email) are available on the request context.
JWKS is cached on the backend; Signward rotates keys without breaking verification — the JWT's kid header points to the active key.
ASP.NET Core
The official SDK wraps the setup. See the .NET SDK page for install instructions.
using IdServer.Client.Middleware;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddIdServerAuth(o =>
{
o.Authority = "https://api.signward.com";
o.Audience = "your-api-audience";
o.UseCookieAuth = false;
});
var app = builder.Build();
app.UseIdServerAuth();
app.MapGet("/api/me", (ClaimsPrincipal user) => new
{
sub = user.GetUserId(),
email = user.GetEmail(),
tenantId = user.GetTenantId(),
roles = user.FindAll("roles").Select(c => c.Value)
}).RequireAuthorization();
app.Run();
Role-based policies
[HttpDelete("/api/users/{id}")]
[IdServerAuthorize("admin", "owner")]
public IActionResult Delete(Guid id) { /* ... */ }
IdServerAuthorize accepts Signward's built-in roles (admin, owner, user) and any custom roles defined per-tenant in the Portal.
Without the SDK
If you need to integrate with an existing auth stack, bypass the SDK and wire up AddJwtBearer directly:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o =>
{
o.Authority = "https://api.signward.com";
o.Audience = "your-api-audience";
o.RequireHttpsMetadata = true;
o.TokenValidationParameters.NameClaimType = "sub";
o.TokenValidationParameters.RoleClaimType = "roles";
});
The handler discovers the JWKS URL from /.well-known/openid-configuration automatically.
FastAPI
from fastapi import FastAPI, Depends
from idserver import IdServerClient, IdServerOptions
from idserver.fastapi import IdServerAuth, CurrentUser
client = IdServerClient(options=IdServerOptions(
authority="https://api.signward.com",
client_id="your-api",
audience="your-api-audience",
))
auth = IdServerAuth(client)
app = FastAPI()
@app.get("/api/me")
async def me(user: CurrentUser = Depends(auth.current_user)):
return {
"id": str(user.user_id),
"email": user.email,
"tenant_id": str(user.tenant_id),
"roles": user.roles,
}
@app.delete("/api/users/{user_id}")
async def delete(user_id: str, user: CurrentUser = Depends(auth.require_role("admin", "owner"))):
return {"ok": True}
See the Python SDK page for install + async details.
Audience claim
Every Signward access token carries an aud claim matching the Jwt:Audience configured on the server. Set the same value on your backend — this is the third defense line after signature + issuer.
If you run multiple APIs, register a distinct OIDC client per API and request the relevant audience during the authorization flow. Signward's token endpoint will refuse tokens that aren't scoped to the requested audience.
Tenant isolation
Tokens are scoped to one tenant. The tenant_id claim is populated from the signed-in user's tenant. Your backend should enforce tenant isolation on every DB query — never trust a tenantId coming from the request body over the claim.
var tenantId = user.GetTenantId();
var reports = await db.Reports.Where(r => r.TenantId == tenantId).ToListAsync();
What to test
- Wrong audience → 401. Set a different
Audiencein your test and make sure validation fails. - Expired token → 401 with
WWW-Authenticate: Bearer error="invalid_token". - Missing
rolesclaim → your policy-gated endpoints return 403. - Cross-tenant query → return 403 / 404, never leak data.
Next steps
- Webhooks — react to user lifecycle server-to-server
- API reference — full endpoint list