Authentication to your systems
The webhook's library provides three helpers, in the SESARWebHook.Core.Auth namespace, so that your handler can authenticate with the system that receives the data. Create them in Initialize, once, and reuse them.
OAuth2, client credentials
OAuth2ClientCredentialsHelper, for Microsoft Entra ID, SharePoint and Dynamics 365.
var dynamics = OAuth2ClientCredentialsHelper.ForDynamics365(tenantId, clientId, clientSecret, "https://<organization>.crm3.dynamics.com");
var graph = OAuth2ClientCredentialsHelper.ForSharePoint(tenantId, clientId, clientSecret, sharePointUrl);
var other = OAuth2ClientCredentialsHelper.ForAzureAD(tenantId, clientId, clientSecret, "api://my-api/.default");
string token = await dynamics.GetAccessTokenAsync();
| Factory | Requested scope |
|---|---|
ForDynamics365 |
{dynamicsUrl}/.default |
ForSharePoint |
https://graph.microsoft.com/.default, whatever SharePoint address you pass |
ForAzureAD |
The scope you pass |
The token endpoint is the one of Microsoft's public cloud: https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token.
OAuth2, refresh token
OAuth2RefreshTokenHelper, for services that issue a long-lived refresh token.
| Factory | Token endpoint |
|---|---|
ForZoho(clientId, clientSecret, refreshToken, accountsDomain) |
{accountsDomain}/oauth/v2/token, by default https://accounts.zoho.com |
ForGoogle(clientId, clientSecret, refreshToken) |
https://oauth2.googleapis.com/token |
ForSalesforce(clientId, clientSecret, refreshToken, isSandbox) |
https://login.salesforce.com or, with isSandbox, https://test.salesforce.com |
ForHubSpot(clientId, clientSecret, refreshToken) |
https://api.hubapi.com/oauth/v1/token |
If the provider returns a new refresh token, the helper ignores it and keeps the old one. For a provider that rotates its refresh tokens, manage them yourself.
Shared behavior of the OAuth2 helpers
- The access token is kept in memory and renewed on demand, 60 seconds before it expires. Obtaining it is protected against simultaneous calls.
- A client credentials helper does not keep in memory a token without a lifetime (
expires_in): each call requests a new one. - A refusal from the provider throws an OAuth2Exception, whose
RawResponsecontains the raw response. Do not log it as is: it can contain details about your tenant. - If your system answers 401, call
InvalidateToken(), then retry once: the helpers do not do it on their own. TestConnectionAsync()obtains a token and returnsfalseon failure, without throwing an exception.
API key
ApiKeyHelper adds an API key to your requests.
var auth = ApiKeyHelper.InHeader("X-API-Key", apiKey);
auth.ApplyTo(request); // request: HttpRequestMessage
| Factory | Effect |
|---|---|
InHeader(headerName, apiKey) |
Header of your choice |
AsBearer(apiKey) |
Authorization: Bearer <key> |
AsBasicAuth(username, apiKey) |
Authorization: Basic, key as password |
AsBasicAuthUsername(apiKey) |
Authorization: Basic, key as user name, empty password |
InQueryString(paramName, apiKey) |
Address parameter |
- Prefer
ApplyTo(HttpRequestMessage), request by request.ApplyTo(HttpClient)modifies a client that may be shared: withInHeader, each call adds the value once more, and withInQueryString, it throws an exception. - Avoid
InQueryString: the key, placed in the address, ends up in server and proxy logs. - Basic mode encodes in ASCII: a non-ASCII character in the name or the key is altered.
Secrets
The credentials for your systems come from the secrets file, Handlers.{id}.Secrets section, and are read with GetRequiredSetting. Never write them in appsettings.json or in the code.