MaksIT.IdentityHub.Client
3.1.2
See the version list below for details.
dotnet add package MaksIT.IdentityHub.Client --version 3.1.2
NuGet\Install-Package MaksIT.IdentityHub.Client -Version 3.1.2
<PackageReference Include="MaksIT.IdentityHub.Client" Version="3.1.2" />
<PackageVersion Include="MaksIT.IdentityHub.Client" Version="3.1.2" />
<PackageReference Include="MaksIT.IdentityHub.Client" />
paket add MaksIT.IdentityHub.Client --version 3.1.2
#r "nuget: MaksIT.IdentityHub.Client, 3.1.2"
#:package MaksIT.IdentityHub.Client@3.1.2
#addin nuget:?package=MaksIT.IdentityHub.Client&version=3.1.2
#tool nuget:?package=MaksIT.IdentityHub.Client&version=3.1.2
MaksIT.IdentityHub.Client
NuGet client for MAKS-IT Identity Hub.
Hub controllers use result.ToActionResult(); this client maps HTTP with Result.FromHttpResponseAsync / Result{T}.FromHttpResponseAsync.
Surfaces
| Interface | Use when | Auth |
|---|---|---|
IIdentityHubIdpClient |
Covered apps, Google/Microsoft challenge/redeem, mailbox | Anonymous + external Hub JWT for mailbox only |
IIdentityHubAdminClient |
Admin login, users, audit, debug/sidecar | AdminAccessToken (global admin for most) |
IIdentityHubClient |
Both | Combines the two |
SignalR /hubs/sidecar-status is WebUI-only (not wrapped).
Token names (do not mix)
| Name | What it is | Where |
|---|---|---|
AdminAccessToken |
Hub JWT for admin | Default Bearer for admin APIs; set by LoginAsync / RefreshTokenAsync |
ExternalLoginAccessToken |
Hub JWT for external from IdP redeem | Mailbox Bearer only; set by RedeemLoginExternalAsync |
MailboxAccessTokenResponse.IdpAccessToken |
IdP mailbox access token | Response body — not a Hub JWT |
IdP challenge/redeem never set AdminAccessToken.
Install
dotnet add package MaksIT.IdentityHub.Client
DI
IdP-only (PostClient mailbox or Google/Microsoft product login — no Hub admin login):
services.AddIdentityHubIdpClient("https://identity.maks-it.com");
// inject IIdentityHubIdpClient
Full API (admin + IdP):
services.AddIdentityHubClient(opts => {
opts.BaseAddress = "https://identity.maks-it.com";
});
// inject IIdentityHubClient, or IIdentityHubIdpClient / IIdentityHubAdminClient
Examples (IdP only — no Hub admin login)
Register once with AddIdentityHubIdpClient, inject IIdentityHubIdpClient. Generate a PKCE code_verifier / S256 code_challenge in the app. postLogin must be an HTTPS host listed in Hub AllowedPostLoginHosts.
Sign-in with Google or Microsoft
Use when the app only needs a Hub session for an external user (no mailbox / IMAP). Omit mailboxPurpose (default false) so Hub requests only openid email profile.
// 1) Start IdP authorize (follow 302 Location, or open it in a browser / system web view)
var challenge = await idp.GetLoginExternalChallengeAsync(
provider: "Google", // or "Microsoft"
postLogin: "https://app.maks-it.com/desktop-callback",
codeChallenge: codeChallenge);
if (!challenge.IsSuccess)
throw new InvalidOperationException(string.Join("; ", challenge.Messages));
var authorizeUrl = challenge.Value; // IdP authorize URL
// 2) After IdP redirects to Hub callback, Hub redirects to postLogin?code=<otc>
// 3) Redeem OTC + PKCE verifier → Hub JWT for the external principal
var redeem = await idp.RedeemLoginExternalAsync(otcCode, codeVerifier);
if (!redeem.IsSuccess)
throw new InvalidOperationException(string.Join("; ", redeem.Messages));
var hubJwt = redeem.Value!.ExternalLoginAccessToken;
// Use hubJwt as Bearer against your own APIs / covered product — not for Hub admin APIs.
// Do not call LoginAsync; AdminAccessToken stays unset.
PostClient — mailbox access (XOAUTH2)
Use when PostClient needs a Google/Microsoft mailbox access token via Hub. Pass mailboxPurpose: true so Hub requests configured mailbox scopes and can vault a refresh token.
// 1) Challenge with purpose=mailbox (consent + offline access for Google)
var challenge = await idp.GetLoginExternalChallengeAsync(
provider: "Google", // or "Microsoft"
postLogin: "https://postclient.maks-it.com/desktop-callback",
codeChallenge: codeChallenge,
mailboxPurpose: true);
if (!challenge.IsSuccess)
throw new InvalidOperationException(string.Join("; ", challenge.Messages));
// 2) User completes IdP; Hub OTC arrives on postLogin
var redeem = await idp.RedeemLoginExternalAsync(otcCode, codeVerifier);
if (!redeem.IsSuccess)
throw new InvalidOperationException(string.Join("; ", redeem.Messages));
// idp.ExternalLoginAccessToken is set from redeem
// 3) Exchange external Hub JWT for IdP mailbox token (IMAP/POP/SMTP XOAUTH2)
var mailbox = await idp.GetMailboxAccessTokenAsync();
if (!mailbox.IsSuccess)
throw new InvalidOperationException(string.Join("; ", mailbox.Messages));
var idpMailboxToken = mailbox.Value!.IdpAccessToken;
// Use idpMailboxToken with the IdP mail server — never treat it as a Hub JWT.
Later mailbox renewal (Hub stays transparent — IdP refresh is vaulted on Hub):
// If the Hub external session expired, renew it (anonymous IdP surface — not admin refresh)
var session = await idp.RefreshLoginExternalAsync(storedHubRefreshToken);
if (!session.IsSuccess)
throw new InvalidOperationException(string.Join("; ", session.Messages));
// session.Value.ExternalLoginAccessToken is set on idp as well
var mailbox = await idp.GetMailboxAccessTokenAsync();
// or: GetMailboxAccessTokenAsync(externalLoginAccessToken: session.Value!.ExternalLoginAccessToken);
While the Hub external session is still valid, call GetMailboxAccessTokenAsync alone — Hub refreshes the IdP mailbox token from its vault.
Admin (optional)
Only when the app manages Hub users / audit (WebUI-style). Not needed for PostClient or Google/Microsoft product login.
services.AddIdentityHubClient("https://identity.maks-it.com");
IIdentityHubAdminClient admin = ...;
var login = await admin.LoginAsync(new LoginRequest { Username = "admin", Password = "..." });
var users = await admin.SearchUsersAsync(new SearchUserRequest { PageNumber = 1, PageSize = 25 });
await admin.LogoutAsync(new LogoutRequest());
PowerShell
See MaksIT.IdentityHub.Client.PowerShell. Connect-IdentityHub -BaseAddress <url> without -AdminAccessToken for IdP-only; optional -ExternalLoginAccessToken for mailbox.
E2E (manual)
PowerShell scenarios against a running Hub (Compose from maksit-identity-hub): src/e2e-tests/README.md. Not run in CI.
pwsh -File .\src\e2e-tests\Test-IdentityHubE2E.ps1
Contributing
See CONTRIBUTING.md and homelab works/repostories-maintenance/nuget-trusted-publishing.md.
| 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
- MaksIT.Core (>= 1.6.14)
- MaksIT.Results (>= 2.1.0)
- Microsoft.Extensions.Http (>= 10.0.14)
- Microsoft.Extensions.Options (>= 10.0.14)
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 |
|---|---|---|
| 4.0.0 | 96 | 11/3/2026 |
| 3.1.3 | 106 | 10/28/2026 |
| 3.1.2 | 96 | 10/28/2026 |
| 3.1.1 | 100 | 10/28/2026 |
| 3.0.0 | 105 | 10/27/2026 |
| 2.2.0 | 108 | 9/24/2026 |
| 2.1.2 | 117 | 9/20/2026 |
| 2.1.1 | 113 | 9/19/2026 |
| 2.1.0 | 130 | 9/18/2026 |
| 2.0.1 | 145 | 9/17/2026 |
| 2.0.0 | 112 | 9/17/2026 |
| 1.6.0 | 118 | 9/16/2026 |
| 1.5.1 | 141 | 8/21/2026 |
| 1.5.0 | 172 | 8/18/2026 |
| 1.4.3 | 133 | 8/16/2026 |
| 1.4.1 | 133 | 8/12/2026 |
| 1.4.0 | 137 | 8/1/2026 |
| 1.3.0 | 130 | 7/30/2026 |
| 1.1.0 | 140 | 7/27/2026 |