Rwd.IAM.Client
2.0.2
dotnet add package Rwd.IAM.Client --version 2.0.2
NuGet\Install-Package Rwd.IAM.Client -Version 2.0.2
<PackageReference Include="Rwd.IAM.Client" Version="2.0.2" />
<PackageVersion Include="Rwd.IAM.Client" Version="2.0.2" />
<PackageReference Include="Rwd.IAM.Client" />
paket add Rwd.IAM.Client --version 2.0.2
#r "nuget: Rwd.IAM.Client, 2.0.2"
#:package Rwd.IAM.Client@2.0.2
#addin nuget:?package=Rwd.IAM.Client&version=2.0.2
#tool nuget:?package=Rwd.IAM.Client&version=2.0.2
Rwd.IAM.Client
Small .NET 10 library for backend services: validate IAM access tokens, read realm metadata (JWKS / discovery), and optionally call IAM with client_credentials (e.g. organization path APIs). Full admin REST surface stays for direct HTTP / OpenAPI—not wrapped here except the org helpers below.
What consuming services typically need from IAM
| Need | This package |
|---|---|
JWKS (GET /v1/auth/realms/{realm}/certs) to verify JWT signatures (kid) |
IIamRealmMetadataClient.GetJsonWebKeySetAsync (cached) |
OpenID discovery (GET …/.well-known/openid-configuration) for issuer / jwks_uri / endpoints |
IIamRealmMetadataClient.GetOpenIdConfigurationAsync |
Validate access token (signature, exact trusted iss, lifetime, optional aud) |
IIamAccessTokenValidator.ValidateAsync |
Permission claims (permission = e.g. users:view) |
IamAccessTokenClaims, HasIamPermission / GetIamPermissions extensions |
Organization read APIs (GET …/organizations/{id}, POST …/paths, POST …/existence) with client_credentials |
AddRwdIamOrganizationApiClient → IIamOrganizationsClient |
HTTP errors from metadata endpoints (with IAM error_code, request_id) |
IamApiException and subclasses |
Optional: add Rwd.IAM.Client.AspNetCore for [RequireIamPermission("resource", "scope")] (MVC) and .RequireIamPermission(...) (minimal APIs) — see src/Rwd.IAM.Client.AspNetCore/README.md.
Install
dotnet add package Rwd.IAM.Client
The public packages are available from NuGet.org. GitHub Packages can also be used when the organization feed and permissions are configured.
Outbound: machine client for organization APIs
When your service must call IAM (not only validate incoming JWTs), register AddRwdIamOrganizationApiClient. It acquires an access token with grant_type=client_credentials (cached until near expiry), attaches Bearer to requests, retries once on 401, and exposes IIamOrganizationsClient for:
GetPathAsync→GET /v1/auth/organizations/{id}GetPathsAsync→POST /v1/auth/organizations/paths(body{ "node_ids": [...] })CheckExistenceAsync→POST /v1/auth/organizations/existence
using Microsoft.Extensions.DependencyInjection;
using Rwd.IAM.Client;
builder.Services.AddRwdIamOrganizationApiClient(o =>
{
o.BaseUrl = new Uri(builder.Configuration["Iam:ApiBaseUrl"]!);
o.RealmName = builder.Configuration["Iam:Realm"]!;
o.ClientId = builder.Configuration["Iam:Integration:ClientId"]!;
o.ClientSecret = builder.Configuration["Iam:Integration:ClientSecret"]!;
});
// …
var orgs = app.Services.GetRequiredService<IIamOrganizationsClient>();
var path = await orgs.GetPathAsync(someOrgId);
OrganizationPathDto exposes the Arabic Name, English NameEn, and
Type as { Id, Name } (for example { "id": 1, "name": "general_directorate" }).
Use a confidential IAM client whose token includes whatever IAM needs for those routes (today they only require a valid authenticated JWT; still use a dedicated integration client in production). You can use AddRwdIamAccessTokenValidation and AddRwdIamOrganizationApiClient together (separate options objects: RwdIamJwtValidationOptions vs RwdIamClientCredentialsOptions).
Why two NuGet packages?
| Package | Depends on | Use when |
|---|---|---|
Rwd.IAM.Client |
HTTP + IdentityModel only | Any .NET host: validate JWTs, read permission claims, call discovery/JWKS. No ASP.NET Core required (workers, tests, gRPC hosts, etc.). |
Rwd.IAM.Client.AspNetCore |
Rwd.IAM.Client + Microsoft.AspNetCore.App |
ASP.NET Core only: [RequireIamPermission], minimal API .RequireIamPermission(...). |
Keeping them split avoids forcing a framework reference to ASP.NET Core on services that only need validation in a console or worker. Version the two packages together (same tag publishes both).
End-to-end flow (consumer API)
- SPA talks to IAM directly for login / refresh; the browser sends
Authorization: Bearer <access_token>to your API. - In
Program.cs, callAddRwdIamAccessTokenValidationwithBaseUrl(IAM API URL),IssuerUrl(canonical issuer URL), andRealmName(same realm the token was issued for). - Authenticate each request: either
- use
Rwd.IAM.Client.AspNetCoreUseIamBearerAuthentication()middleware (see AspNetCore README), or - read the bearer token yourself, call
ValidateAsync, and assignHttpContext.User.
- use
- Authorize: IAM permissions are on claims with type
permission(e.g.users:view). Either:- use
User.HasIamPermission(...)/ policies /RequireClaim, or - add
Rwd.IAM.Client.AspNetCoreand use[RequireIamPermission("resource", "scope")]or.RequireIamPermission(...)on endpoints.
- use
- Optional: call
IIamRealmMetadataClient.GetOpenIdConfigurationAsyncat startup or for health checks (not required on every request for validation). - JWKS is fetched by the SDK when validating; results are cached in memory per process (
JwksCacheDuration).
[Browser] --token from IAM--> [Your API]
|
+--> AddRwdIamAccessTokenValidation (DI)
+--> Middleware: Bearer --> ValidateAsync --> HttpContext.User
+--> [Authorize] + [RequireIamPermission] / policies --> action runs
Registration
using Microsoft.Extensions.Hosting;
using Rwd.IAM.Client;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddRwdIamAccessTokenValidation(o =>
{
o.BaseUrl = new Uri(builder.Configuration["Iam:ApiBaseUrl"]!);
o.IssuerUrl = new Uri(builder.Configuration["Iam:IssuerUrl"]!);
o.RealmName = builder.Configuration["Iam:Realm"]!;
// o.JwksCacheDuration = TimeSpan.FromMinutes(5); // default
// o.JwtClockSkew = TimeSpan.FromMinutes(2); // default
});
using var app = builder.Build();
var validator = app.Services.GetRequiredService<IIamAccessTokenValidator>();
Validate a bearer token
using System.Security.Claims;
IIamAccessTokenValidator validator = /* from DI */;
ClaimsPrincipal principal = await validator.ValidateAsync(
accessToken,
audience: "your-api-audience", // or null to skip audience check
cancellationToken: default);
// principal: roles use ClaimTypes.Role; permissions use IamAccessTokenClaims.Permission ("permission")
if (principal.HasIamPermission("users:view")) { … }
Validation compares the token’s iss claim with an exact canonical issuer ({IssuerUrl}/realms/{realm_name}), then loads keys from the IAM API base URL’s realm JWKS endpoint. The JWT header must include kid matching a JWK entry. IAM access tokens contain iam-api and dms-api audiences; user tokens also contain {realm_name}-api, while client-credentials tokens contain audit-log-api.
Multi-realm validation for central services
Central services that accept tokens from more than one IAM realm should configure every trusted realm explicitly. The SDK derives the exact issuer for each configured realm and selects the matching realm JWKS endpoint from the token’s iss claim:
builder.Services.AddRwdIamAccessTokenValidation(o =>
{
o.BaseUrl = new Uri("https://iam.dev.res.moj.iq/");
o.IssuerUrl = new Uri("https://iam.moj.iq/");
o.TrustedRealmNames = ["citizens", "main", "master"];
});
builder.Services.AddIamBearerAuthentication(o =>
{
o.Audience = "dms-api";
});
Do not trust an issuer supplied by the token or accept a URL prefix. Each central service should require its own audience (for example, dms-api).
Permissions (resource:scope strings on the token)
IAM emits each resolved permission as its own JWT claim: type permission, value e.g. users:view. Helpers: IamAccessTokenClaims.Permission, ClaimsPrincipal extensions GetIamPermissions, HasIamPermission, HasAnyIamPermission, HasAllIamPermissions.
Protecting endpoints: combine [Authorize] (authentication) with policies / HasIamPermission, or install Rwd.IAM.Client.AspNetCore and use [RequireIamPermission("districts", "view")] (MVC) or .RequireIamPermission("districts", "view") (minimal APIs). Keep strings aligned with IAM (source of truth). See Rwd.IAM.Client.AspNetCore/README.md.
Discovery only (e.g. issuer pinning or docs)
IIamRealmMetadataClient meta = app.Services.GetRequiredService<IIamRealmMetadataClient>();
var doc = await meta.GetOpenIdConfigurationAsync();
// doc.Issuer, doc.JwksUri, doc.TokenEndpoint, …
Configuration (RwdIamJwtValidationOptions)
| Property | Description |
|---|---|
BaseUrl |
IAM API base URL used for discovery and JWKS routes (e.g. https://iam.dev.res.moj.iq/). |
IssuerUrl |
Canonical issuer base URL used to validate iss (e.g. https://iam.moj.iq/). If omitted, BaseUrl is used. |
RealmName |
Realm segment in /v1/auth/realms/{realm_name}/…. |
TrustedRealmNames |
Exact realm allowlist for multi-realm consumers. If empty, RealmName is trusted. |
JwksCacheDuration |
TTL for cached JWKS (default 5 minutes). Set TimeSpan.Zero to disable caching (always refetch). |
JwtClockSkew |
Passed to token validation (default 2 minutes). |
Publishing
Tag sdk-dotnet-v* → .github/workflows/sdk-publish.yml.
License
Rwd.
| Product | Versions 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. |
-
net10.0
- Microsoft.Extensions.Http (>= 10.0.2)
- Microsoft.Extensions.Http.Resilience (>= 10.2.0)
- Microsoft.Extensions.Options (>= 10.0.2)
- Microsoft.IdentityModel.JsonWebTokens (>= 8.3.1)
- Microsoft.IdentityModel.Tokens (>= 8.3.1)
- System.IdentityModel.Tokens.Jwt (>= 8.3.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Rwd.IAM.Client:
| Package | Downloads |
|---|---|
|
Rwd.IAM.Client.AspNetCore
ASP.NET Core helpers for IAM: bearer JWT middleware, permission filters, minimal API extensions (Rwd.IAM.Client). |
GitHub repositories
This package is not used by any popular GitHub repositories.