Table of Contents

Authentication

Every route except the OAuth ones needs a bearer access token. The login methods in OpenBiApiClientAuthExtensions get one from the server's oauth/token endpoint and attach it to the client, so every later call on that client carries it. They also return the OAuthAccessToken, for its expiry, its scopes and its refresh token.

A client holds one token at a time. To act as two identities at once, use two clients.

As a user

var token = await client.LoginAsync("username", "password", cancellationToken);

The OAuth2 password grant.

As an API key

var token = await client.CreateAccessTokenAsync(apiKeyId, apiKeySecret, cancellationToken: cancellationToken);

The OAuth2 client_credentials grant, for services and scripts. An API key is created in the configurator or with OpenBiApiClientApiKeyExtensions; its id and secret are the client id and secret. A scope narrows the token to some of what the key may do.

Windows single sign-on

using var client = new OpenBiApiClient(
    new Uri("https://myserver/openbi/api/"),
    new HttpClientHandler { UseDefaultCredentials = true });

var token = await client.NegotiateAsync(cancellationToken);

The negotiate grant signs on with Kerberos or NTLM. The message handler answers the server's challenge, so it has to be allowed to send the current user's credentials. In a browser, the browser does that. The server has to be configured for single sign-on.

In an app, for its users

An application registered as an OAuth app (BiExcellence.OpenBi.Api.OAuthApps) can use the authorization code flow with PKCE: the user signs in on the open bi server and allows the app, and the app never sees the password.

var pkce = OAuthPkce.Create();
var state = Guid.NewGuid().ToString("N");

// 1. send the user's browser here
var authorizeUri = client.GetAuthorizationUri(appId, redirectUri, pkce, state);

// 2. the browser comes back to redirectUri with ?code=...&state=... - check the state, then
var token = await client.CreateAccessTokenFromAuthorizationCodeAsync(
    appId, appSecret, code, redirectUri, pkce.Verifier, cancellationToken);

The secret is null for a public client such as a single page or desktop app. Asking for the openid scope also returns an OpenID Connect ID token.

Refreshing and signing out

An access token is short-lived (ExpiresIn, in seconds). The password, negotiate and authorization code grants also return a refresh token, which gets the next access token without signing in again:

token = await client.RefreshAccessTokenAsync(token.RefreshToken!, cancellationToken: cancellationToken);

Every refresh returns a new refresh token. Keep it and drop the old one - using an old one again revokes the whole grant. An API key has no refresh token; it simply asks again.

RevokeTokenAsync ends one grant, SignOutEverywhereAsync every grant of the current user.

Without the login methods

A token obtained some other way is attached with SetAccessToken(string?).