10Duke Enterprise C++ SDK
Loading...
Searching...
No Matches
Client Concepts

This article provides a high-level overview of the 10Duke Enterprise C++ SDK and introduces some fundamental concepts.

The client is stateful

Factory functions are used to create the client. The created client, tenduke::ee::TendukeClient, aggregates related services, such as licensing. Since the client is stateful, you must keep the instance alive for the duration of the application. The state currently maintained is the user login session.

For details, see Identity-based licensing.

Save and restore the client state

Since the client is stateful, we recommend that you save the client state to a persistent storage. For example, when the application is about to close, you can request the state to be serialized. You can serialize the state after any license-related API call. This protects the state against any abnormal application termination (for example, a power loss). The state is serialized into a JSON string that you can store, for example, on disk. The JSON format is not documented, and any modification of the JSON outside the client is not supported.

To prevent anyone from tampering the state, we strongly recommend that you encrypt the serialized state before storing it. The client does not support encryption or decryption of the state.

When the application restarts, it reads and decrypts the stored state, and passes the string in the initialStateAsJSON parameter to the factory functions that create the client.

The stored state contains only OIDC session state (for example, an access token, ID token).

For example, to serialize current state of the client, execute the following:

std::shared_ptr<::TendukeClient> tendukeClient = ...;
std::string serializedState = tendukeClient->serializeState();

To restore the client state, pass the serialized state to the factory function when creating the client:

std::string serializedState = ...; // Read the state from somewhere
auto tenduke = ::createClientUsingAutodiscovery(
"stateful-client-demo/0.0.1-alpha-1",
::tenduke::ee::ClientProperties::Builder().hardwareId("simulated-hardware-id").build(),
"https://genco.10duke.net"),
::BrowserAuthenticationConfig("demo", "http://localhost/login", httpMessageAfterLogin),
serializedState // pass the state here
);

Use 10Duke Enterprise REST APIs

If you want to use 10Duke Enterprise REST APIs that don't yet have a C++ implementation, you must authorize the HTTP requests using an OAuth access token.

To get the access token, use the tenduke::oidc::OIDCSession.getAccessToken() method. Authenticate the request by adding an HTTP header named Authorization with the value Bearer accesstoken. Replace accesstoken with the access token.

For example:

std::shared_ptr<::tenduke::se::TendukeClientWithOIDCSession> tendukeClient = ...; // Client created earlier
// Make sure that user has a valid session.
// If the user does not have valid session, this call will either refresh the session or re-login the user
tendukeClient->oidcSession->ensureValidSession();
auto headerValue = "Bearer " + tendukeClient->oidcSession->getAccessToken();

For details, see RFC 6750, 2.1. Authorization Request Header Field.

Errors

Error conditions are reported using C++ exceptions. All exceptions thrown by the client inherit from the tenduke::TendukeException class. As a general rule of thumb, an exception can be thrown if a method or function requires network access. Parsing JSON or JWTs, or doing cryptography operations can also throw exceptions. Most methods try to document thrown exceptions, but this is not totally reliable.

Some network exceptions are handled behind the scenes, but there are still several conditions where the exception is propagated to the caller of the method. Network exceptions are caused either by permanent conditions (for example, an invalid URL has been configured) or by temporary conditions (for example, the network is temporarily down, a server is in maintenance, or a server is out of resources). There is currently no retry logic in the client for temporary network issues.

Note that certain licensing-related error conditions do not throw exceptions. For example, if you try to check out a seat in a license, and there are no seats available, the client does not throw an exception. See for example tenduke::ee::licensing::LicenseCheckoutResponse for more information.

High-level vs low-level

The client is built using layers. Most users can use the high-level client that abstracts away much of the complexities of request authentication. For more control, you can use the low-level client. For example, the high-level tenduke::ee::licensing::impl::StatefulLicensingClient uses a lower level tenduke::ee::licensing::authzapi::DefaultAuthzLicensingClient. The low-level client performs the actual network call, handling request parametrization and response parsing. The high-level client manages the OIDC user session state.

The low-level clients are currently not thoroughly documented. However, we strive to keep their interface stable and ensure it matches the REST API.