Ark.oAuth.Client
2.0.1
See the version list below for details.
dotnet add package Ark.oAuth.Client --version 2.0.1
NuGet\Install-Package Ark.oAuth.Client -Version 2.0.1
<PackageReference Include="Ark.oAuth.Client" Version="2.0.1" />
<PackageVersion Include="Ark.oAuth.Client" Version="2.0.1" />
<PackageReference Include="Ark.oAuth.Client" />
paket add Ark.oAuth.Client --version 2.0.1
#r "nuget: Ark.oAuth.Client, 2.0.1"
#:package Ark.oAuth.Client@2.0.1
#addin nuget:?package=Ark.oAuth.Client&version=2.0.1
#tool nuget:?package=Ark.oAuth.Client&version=2.0.1
Ark.oAuth.Client
The OAuth 2.1 / OpenID Connect client for ASP.NET Core applications. One call in Program.cs,
two required settings, and [Authorize] works.
It configures ASP.NET Core's own OpenID Connect and cookie handlers rather than hand-rolling the
protocol, so PKCE, state, nonce, JWKS rollover and token refresh all come from the framework.
Built for Ark.oAuth.Oidc, but because it is the
stock handler underneath, changing Authority and ClientId is enough to point the same
application at Entra ID, Okta, Auth0 or Keycloak.
Install
dotnet add package Ark.oAuth.Client
Program.cs
using Ark.oAuth;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddArkOidcClient(builder.Configuration);
builder.Services.AddControllersWithViews();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting(); // MUST precede the next two
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
appsettings.json
Authority and ClientId are the only required keys — every endpoint is read from the provider's
discovery document.
{
"ark_oauth_client": {
"Authority": "https://idp.example.com/my_idp", // the issuer
"ClientId": "my-app",
"ClientSecret": null, // null = public client + PKCE
"Scopes": [ "openid", "profile", "email", "offline_access" ],
"CallbackPath": "/signin-oidc",
"SignedOutCallbackPath": "/signout-callback-oidc",
"SignedOutRedirectUri": "/",
"AuthErrorPath": "/", // failed callbacks land here with ?auth_error=...
"RequireHttpsMetadata": true,
"CookieName": "my_app_auth",
"RoleClaimType": "role", // ark_claims from the access token map onto this
"ExpireMins": 480
}
}
Using the result
[Authorize]
public IActionResult Secure() => View();
// Ark authorization claims (ark_claims) are projected as roles, so policies work directly
[Authorize(Roles = "billing.admin")]
public IActionResult Billing() => View();
Reading the access token — always per call, never cached; the cookie handler refreshes it underneath you:
var accessToken = await HttpContext.GetArkAccessTokenAsync();
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com/things");
await request.WithArkTokenAsync(HttpContext);
Protecting an API
builder.Services
.AddAuthentication()
.AddArkOidcApi(arkConfig);
The flows outside interactive sign-in
AddArkOidcClient also registers three services. All three work off the provider's discovery
document, so they need the issuer and nothing else.
| Service | For |
|---|---|
ArkSetupProbe |
Pairs local configuration against the provider's live metadata and returns ArkSetupModel — issuer mismatch, unregistered scopes, the exact redirect URI this app will send. Render it and a registration mistake reads as a sentence instead of invalid_client. |
ArkClientCredentials |
The client credentials grant. GetTokenAsync caches until shortly before expiry; RequestTokenAsync forces a live exchange. |
ArkRegistration |
Dynamic client registration (RFC 7591) and management (RFC 7592). |
var model = await setup.ProbeAsync(HttpContext);
var token = await credentials.GetTokenAsync(clientId, secret, new[] { "reports.read" });
var client = await registration.RegisterAsync(metadata, token.AccessToken);
Registering the application
Three things have to line up on the provider, not one:
- Create the client.
- Register both redirect URIs —
{host}/signin-oidcand{host}/signout-callback-oidc— matched byte for byte. No wildcards, no prefix matching. - Grant each user access to that client. Without the mapping, sign-in fails with a message that looks like a wrong password.
Scopes on a client record are a whitelist: an unregistered scope is rejected, not dropped.
offline_access is what produces a refresh token. Never add a controller action at CallbackPath —
it shadows the handler. Sign out of both ArkOidcClient.CookieScheme and ArkOidcClient.OidcScheme,
or the provider session survives and the next sign-in is silent.
Legacy flow
ark_oauth_client:UseLegacyFlow keeps the original cookie/bearer middleware for deployments
migrating off the v1 endpoints. It does not validate state or nonce — treat it as a migration
aid, not a supported configuration.
Documentation
A complete, runnable client application and the full walkthrough are in the repository: https://github.com/ir-dev/ark-oauth-oidc
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
-
net9.0
- ark.net.util (>= 1.0.4.14)
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 8.0.15)
- Microsoft.AspNetCore.Authentication.OpenIdConnect (>= 8.0.15)
- Microsoft.IdentityModel.JsonWebTokens (>= 8.8.0)
- Microsoft.IdentityModel.Protocols.OpenIdConnect (>= 8.8.0)
- System.IdentityModel.Tokens.Jwt (>= 8.8.0)
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 |
|---|---|---|
| 2.0.10 | 151 | 9/12/2026 |
| 2.0.9 | 167 | 9/3/2026 |
| 2.0.8 | 133 | 9/2/2026 |
| 2.0.7 | 115 | 9/1/2026 |
| 2.0.6 | 116 | 9/1/2026 |
| 2.0.5 | 144 | 8/30/2026 |
| 2.0.4 | 129 | 8/29/2026 |
| 2.0.3 | 121 | 8/29/2026 |
| 2.0.2 | 143 | 8/19/2026 |
| 2.0.1 | 141 | 8/18/2026 |
| 2.0.0 | 124 | 8/17/2026 |
| 1.0.5.45 | 202 | 3/22/2026 |
| 1.0.5.44 | 189 | 3/20/2026 |
| 1.0.5.43 | 331 | 10/12/2025 |
| 1.0.5.42 | 345 | 7/9/2025 |
| 1.0.5.41 | 326 | 7/3/2025 |
| 1.0.5.40 | 328 | 7/3/2025 |
| 1.0.5.39 | 315 | 7/2/2025 |
| 1.0.5.38 | 313 | 7/2/2025 |
| 1.0.5.37 | 322 | 7/2/2025 |
2.0.1 — maintenance release.
No API change over 2.0.0. Rebuilt and republished alongside Ark.oAuth.Oidc 2.0.1 to keep the two
halves on the same version, and to carry the packaging fixes below. Consumers on 2.0.0 can upgrade
with no code change; the 2.0.0 notes apply unchanged and are kept below.
Packaging: the package icon (ark_logo.png) and the readme are packed at the root of the .nupkg, so
nuget.org and the Visual Studio package manager show both. The icon is referenced through
PackageIcon rather than the deprecated PackageIconUrl, and is included with an empty PackagePath so
it lands at the package root on a non-Windows build too.
2.0.0 — the standards release.
* AddArkOidcClient now configures ASP.NET Core's OpenID Connect and cookie handlers against the
provider's discovery document. Real PKCE, state and nonce validation, JWKS rollover and silent
refresh all come from the framework instead of being hand-rolled.
* Authority and ClientId are the only required settings — no pasted rsaPublic, no issuer/audience
to mirror, no per-tenant key table to keep in step with rotation.
* AddArkOidcApi for protecting an API with bearer tokens from the same provider.
* Ark authorization claims (ark_claims) are projected onto the principal as role claims, so
[Authorize(Roles = "...")] and policies work directly.
* GetArkAccessTokenAsync / WithArkTokenAsync read the current token per call, so a token refreshed
by the cookie handler is picked up automatically.
* New services for the non-interactive flows: ArkSetupProbe (configuration vs. live metadata),
ArkClientCredentials (client credentials grant with caching) and ArkRegistration (RFC 7591/7592).
Breaking / migration: the standard flow is now the default. Set ark_oauth_client:UseLegacyFlow to
true to keep the original cookie/bearer middleware while migrating — it does not validate state or
nonce and should be treated as a migration aid, not a supported configuration.
Packaging: the package no longer ships a sample appsettings file into consuming projects, and now
carries a readme, an SPDX license expression and a symbol package.