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

This documentation gives high level overview of the client and introduces some fundamental concepts.

The client is stateful

Factory-functions are used to create the client. The created client is tenduke::ee::TendukeClient, which aggregates related services, like licensing. The client is stateful, and 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.

Saving and restoring the client state

Since the client is stateful, it is recommended that you save the client state to 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, if you like: This would protect the state against any abnormal ending of the application (e.g. power loss). The state is serialized into a string, which contains JSON-representation of the state. You then store the string to e.g. disk. The JSON format is not documented and any modification of the JSON outside the client is unsupported.

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

When the application re-starts, it reads the stored state, decrypts it and passes the string in parameter named initialStateAsJSON to the factory functions which create the client.

The stored state currently only OIDC session state (e.g. access token, id-token).

For example, to serialize current state of the client, execute 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
);

Using 10Duke Enterprise REST APIs

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

To get the access-token, use method tenduke::oidc::OIDCSession.getAccessToken(). Then authenticate the request by adding HTTP header with name Authorization and value Bearer accesstoken, where accesstoken is replaced by 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 class tenduke::TendukeException. As a general rule of thumb, if method or function does network access, an exception might be thrown. Parsing JSON or JWTs or doing cryptography operations might 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 (e.g. invalid URL has been configured) or by temporary conditions (network temporarily down, server in maintenance, server out of resources). There is currently no re-try 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 checkout a seat of a license, and there are no seats available, the client does not throw exception. See for example tenduke::ee::licensing::LicenseCheckoutResponse for more information.

High-level vs low-level

The client is built as layers. Most users can use the high-level client, which abstracts away much of the complexities of request authentication. For more control, you may want to use the low-level client. For example, the high level tenduke::ee::licensing::impl::StatefulLicensingClient uses 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 for example manages the OIDC user session state.

The low-level clients are currently not thoroughly documented, but we try to keep the interface stable and matching the REST-API.