Authentication

NetCoreForce supports several Salesforce OAuth 2.0 flows. There are two ways to use them:

  • Call AuthenticationClient directly. It performs the OAuth flow and stores the result in AccessInfo (an AccessTokenResponse). You then build a ForceClient from that access token yourself.
  • Use one of ForceClient's constructors or factory methods that perform the login and initialize the client in a single step.

All AuthenticationClient flow methods throw a ForceAuthException on failure — see Error Handling below.


Client Credentials Flow

Server-to-server authentication with no end user involved, using only the connected app's Consumer Key/Secret.

Via the ForceClient factory method:

ForceClient client = await ForceClient.FromClientCredentialsAsync("your-client-id", "your-client-secret", "https://your-domain.my.salesforce.com/services/oauth2/token");

Or via AuthInfo:

AuthInfo authInfo = new AuthInfo
{
    AuthMethod = AuthInfo.AuthMethodType.ClientCredentials,
    ClientId = "your-client-id",
    ClientSecret = "your-client-secret",
    TokenRequestEndpoint = "https://your-domain.my.salesforce.com/services/oauth2/token"
};

ForceClient client = new ForceClient(authInfo);

Or with AuthenticationClient directly:

AuthenticationClient auth = new AuthenticationClient();
await auth.ClientCredentialsAsync("your-client-id", "your-client-secret", "https://your-domain.my.salesforce.com/services/oauth2/token");
Note

Client Credentials flow may require the org's specific My Domain token endpoint (https://your-domain.my.salesforce.com/services/oauth2/token) rather than the generic https://login.salesforce.com/services/oauth2/token endpoint used by the other flows.


Web Server (Authorization Code) Flow

Used when an end user needs to log in and grant consent interactively via a browser. This is a two-step flow.

Step 1: Redirect the user to a consent URL, built with UriFormatter.WebServerAuthenticationUrl:

Uri consentUrl = UriFormatter.WebServerAuthenticationUrl(
    loginUrl: "https://login.salesforce.com/services/oauth2/authorize",
    clientId: "your-client-id",
    redirectUrl: "https://your-app.example.com/callback");

// redirect the user's browser to consentUrl

Step 2: After the user approves, Salesforce redirects back to redirectUrl with a code query parameter. Exchange it for an access token with AuthenticationClient.WebServerAsync:

AuthenticationClient auth = new AuthenticationClient();
await auth.WebServerAsync("your-client-id", "your-client-secret", "https://your-app.example.com/callback", code);

ForceClient client = new ForceClient(auth.AccessInfo.InstanceUrl, auth.ApiVersion, auth.AccessInfo.AccessToken);

Unlike the Username-Password flow, this flow does return a refresh token, available at auth.AccessInfo.RefreshToken.


Token Introspection

Check whether an access token is still valid with AuthenticationClient.IntrospectTokenAsync:

AuthenticationClient auth = new AuthenticationClient();
IntrospectTokenResponse introspectResponse = await auth.IntrospectTokenAsync(accessToken, "your-client-id", "your-client-secret");

if (introspectResponse.Active)
{
    // token is still valid
}

Returns an IntrospectTokenResponse — see Active for the validity flag, plus Scope, ClientId, Username, and expiry-related fields.


Refreshing an Access Token

If you have a refresh token (obtained via the Web Server Flow), use AuthenticationClient.TokenRefreshAsync to get a new access token without re-prompting the user:

AuthenticationClient auth = new AuthenticationClient();
await auth.TokenRefreshAsync(refreshToken, "your-client-id", "your-client-secret");

ForceClient client = new ForceClient(auth.AccessInfo.InstanceUrl, auth.ApiVersion, auth.AccessInfo.AccessToken);
Note

The Username-Password flow does not return a refresh token, so this only applies to tokens obtained via the Web Server flow.


Using a Pre-Existing Access Token

If authentication was already handled elsewhere (e.g. a token cached from a previous session), initialize ForceClient directly from the instance URL and access token, skipping any login call:

ForceClient client = new ForceClient(instanceUrl, apiVersion, accessToken);

Custom HttpClient / Proxy Support

Both AuthenticationClient and ForceClient accept an optional httpClient parameter for scenarios needing a custom HttpClient, e.g. a proxy. HttpClientFactory.CreateHttpClient can build one configured for a proxy:

HttpClient proxyClient = HttpClientFactory.CreateHttpClient(true, "http://your-proxy:8080");

ForceClient client = new ForceClient("your-client-id", "your-client-secret", "your-username", "your-password", "https://login.salesforce.com/services/oauth2/token", httpClient: proxyClient);

Error Handling

All AuthenticationClient flow methods throw a ForceAuthException if authentication fails, with ErrorCode (e.g. invalid_grant) and HttpStatusCode properties:

try
{
    await auth.UsernamePasswordAsync("your-client-id", "your-client-secret", "your-username", "your-password", "https://login.salesforce.com/services/oauth2/token");
}
catch (ForceAuthException ex)
{
    Console.WriteLine($"{ex.ErrorCode}: {ex.Message}");
}

Username-Password Flow

Warning

The OAuth Username-Password flow is deprecated and Salesforce recommends against using it. It is blocked by default in orgs created in Summer '23 or later, and admins can disable it in any org (Setup > OAuth and OpenID Connect Settings > Allow OAuth Username-Password Flows), so it may not be available in your org. For new integrations, use the Client Credentials Flow for server-to-server access, or the Web Server Flow when a user logs in.

The application holds the user's credentials directly and exchanges them for an access token.

One-step, via the ForceClient(AuthInfo) constructor:

AuthInfo authInfo = new AuthInfo
{
    ClientId = "your-client-id",
    ClientSecret = "your-client-secret",
    Username = "your-username",
    Password = "your-password",
    TokenRequestEndpoint = "https://login.salesforce.com/services/oauth2/token"
};

ForceClient client = new ForceClient(authInfo);

Or without building an AuthInfo object:

ForceClient client = new ForceClient("your-client-id", "your-client-secret", "your-username", "your-password", "https://login.salesforce.com/services/oauth2/token");

If you need the raw token response first (e.g. to inspect or persist it), use AuthenticationClient.UsernamePasswordAsync and build the client from the result:

AuthenticationClient auth = new AuthenticationClient();
await auth.UsernamePasswordAsync("your-client-id", "your-client-secret", "your-username", "your-password", "https://login.salesforce.com/services/oauth2/token");

ForceClient client = new ForceClient(auth.AccessInfo.InstanceUrl, auth.ApiVersion, auth.AccessInfo.AccessToken);

A synchronous UsernamePassword overload is also available if you can't use async/await.

Note

This flow does not return a refresh token — see Refreshing an Access Token.