Authentication
Calls to the Messaging and LIFF APIs are authorized with a channel access token carried as
a Bearer token. This library models token acquisition behind Kiota's
IAccessTokenProvider, so you can choose between a static token and a runtime-refreshing one
without changing call sites.
Token strategies at a glance
| Strategy | Type | When to use |
|---|---|---|
| Static (long-lived) | StaticChannelAccessTokenProvider | You already hold a long-lived token. |
| Short-lived (v2.1 JWT) | JwtAssertionTokenSource | Issue a token via JWT assertion (/oauth2/v2.1/token). |
| Stateless (v3) | StatelessJwtAssertionTokenSource | Issue a 15-minute stateless token (/oauth2/v3/token). |
| Auto-refresh wrapper | RefreshingChannelAccessTokenProvider | Cache a short-lived/stateless token and re-issue near expiry. |
Static token
The simplest case: hold a token and return it. This provider lives in Line.OpenApi.Core and only
attaches the token to allowed hosts (see Security).
using Line.OpenApi.Core.Authentication;
using Microsoft.Kiota.Abstractions.Authentication;
var provider = new StaticChannelAccessTokenProvider("CHANNEL_ACCESS_TOKEN");
var auth = new BaseBearerTokenAuthenticationProvider(provider);
Both MessagingClient and LiffClient expose a CreateWithStaticToken(...) shortcut that
wires this up for you.
Short-lived tokens (JWT assertion)
Use JwtAssertionTokenSource to issue a short-lived token from a signed JWT assertion. Signing with your channel's private key is application-specific, so you supply the assertion through a factory — this library never handles signing keys.
using Line.OpenApi.ChannelAccessToken;
using Line.OpenApi.ChannelAccessToken.Generated;
var tokenClient = new ChannelAccessTokenClient(requestAdapter); // Kiota-generated client
var source = new JwtAssertionTokenSource(
tokenClient,
async ct => await BuildSignedJwtAssertionAsync(ct)); // your signing logic
IssuedToken token = await source.IssueAsync();
Stateless tokens (v3)
StatelessJwtAssertionTokenSource issues a stateless token from
/oauth2/v3/token. Stateless tokens have no limit on the number of concurrently active tokens,
but they live for only 15 minutes and cannot be revoked before expiry — so pair them with the
refreshing provider and issue on demand.
Why a dedicated helper? The
/oauth2/v3/tokenbody is a discriminator-lessoneOf. The generated code represents it as a composed wrapper that serializes its inner model as a nested object, which the form-urlencoded serializer cannot express (it fails with "Form serialization does not support nested objects."). This helper sidesteps the wrapper by sending a flat request model, so you get the same issuance seam as the v2.1 source.
Auto-refreshing provider
RefreshingChannelAccessTokenProvider wraps any
IChannelAccessTokenSource, caches the issued token, and re-issues it once the refresh margin
before expiry is reached. It prevents duplicate issuance under concurrent refresh, and it is
IDisposable.
using Line.OpenApi.ChannelAccessToken;
using var provider = new RefreshingChannelAccessTokenProvider(
source, // e.g. JwtAssertionTokenSource / StatelessJwtAssertionTokenSource
refreshMargin: TimeSpan.FromMinutes(5));
var auth = new BaseBearerTokenAuthenticationProvider(provider);
var messaging = new MessagingClient(auth);
To use a refreshing provider with DI, inject it through the auth-provider overload of
AddLineMessaging / AddLineLiff — see Dependency Injection & Hosting.
This keeps Line.OpenApi.Messaging / Line.OpenApi.Liff free of a dependency on Line.OpenApi.ChannelAccessToken.