# User Based Licensing

User-based licensing is a contemporary approach to software or service provisioning, wherein access and usage rights are granted on a per-user basis.

Unlike traditional licensing models that focus on the number of devices or installations, user-based licensing centers around the actual individuals who will be utilizing the product or service.

This model has gained popularity due to its flexibility and scalability, providing businesses and organizations with a more efficient and cost-effective way to manage their software resources.

By the end of this tutorial, you should understand how to create a login feature by activating a license, how to create a logout feature by deactivating a license, and how to routinely perform online checks on your user-based license from your program.

{% hint style="info" %}
When [**activating**](broken://pages/f528c0e4e486edc850ab3b495bd3659519ed8f70) a **user-based license**, the `license_id` parameter is optional but highly recommended in certain cases:

* If `license_id` is **not provided**, the system will activate the **most recently created license** associated with the specified user.
* If a user is assigned to **multiple licenses**, omitting `license_id` may lead to unintended behavior, as the latest license will be selected automatically.
  {% endhint %}

### Adding a User to a License on the Platform

Email and password of users can be found on the licenses page. Utilizing a user-based license requires users to be created and assigned to the license.

This is done by entering the user-based license, switching to the users tab, and clicking “assign license user”.

![](/files/08c4cd929c5428571e6a21650988d4a4b8ae1e81)

### Configuration

Configuration is a set of parameters or settings that are specific to a SDK and can include elements such as API keys, shared keys or product codes.

### Local License

The local license is a copy of the license information that is saved on the end user's local computer. Users who have not activated the license on their end before will not have a local license. By default, the local license is stored: %USERPROFILE%\AppData\Local\LicenseSpring"Product Code"\License.key.

You can read more about the local license file [**here**](https://docs.licensespring.com/sdks/tutorials/best-practices/local-license-file).

The process of activating a license refers to binding a device to a license. On the LicenseSpring platform, activating the license increments the total activations counter within the license.

If a device already has a license, and you try to activate another license on that device, for the same product, that newly activated license will override the existing license, deleting it from the device. This will be on the developer to make sure that they check if a license exists on the device before a new activation:

{% tabs %}
{% tab title="C++" %}

```cpp
auto license = licenseManager->getCurrentLicense();
if (license == nullptr)
    // activate a new license
```

{% endtab %}

{% tab title="C#" %}

```csharp
var license = licenseManager.CurrentLicense();
if ( license == null )
   //activate a new license
```

{% endtab %}

{% tab title="Java" %}

```java
License license = licenseManager.getCurrent();
if ( license == null )
  //activate a new license
```

{% endtab %}

{% tab title="Swift" %}

```swift
if manager.currentLicense == nil {
    // activate new license.
}
```

{% endtab %}

{% tab title="Python" %}

```python
## need to implement getCurrentLicense in python
```

{% endtab %}

{% tab title="Go" %}

```go
// Go SDK v2
ld, err = license_handler.GetCurrentLicense()
```

{% endtab %}
{% endtabs %}

### Activation

#### Logging In

Creating a login system with the user-based license is straightforward. You can ask the user to input their email and password combination. Once we have the user's credentials, we can then take that email/password combination and use it to activate our user-based license. How the user inputs their credentials is up to you.

{% tabs %}
{% tab title="C++" %}

```cpp
std::string email = "UserEmail@example.com";
std::string password = "UserPassword";
auto licenseId = LicenseID::fromUser(email, password);
auto license = licenseManager->activateLicense(licenseId);
```

{% endtab %}

{% tab title="C#" %}

```csharp
string email = "UserEmail@example.com";
string password = "UserPassword";
var licenseId = LicenseID.FromUser( email, password );
var license = licenseManager.ActivateLicense( licenseId );
```

{% endtab %}

{% tab title="Java" %}

```java
String email = "UserEmail@example.com";
String password = "UserPassword";
ActivationLicense licenseId = ActivationLicense.fromUsername( email, password );
License license = licenseManager.activateLicense( licenseId );
```

{% endtab %}

{% tab title="Swift" %}

```swift
let license = try manager.activateLicense(
    user: "UserEmail@example.com",
    password: "UserPassword"
)
```

{% endtab %}

{% tab title="Python" %}

```python
from licensespring.licensefile.license_manager import LicenseID
from licensespring.licensefile.license_manager import LicenseManager

license_id = LicenseID.from_user(username="email@email.com",password="password")
license = manager.activate_license(license_id) 
```

{% endtab %}
{% endtabs %}

#### Checking a License

It is recommended to perform a local license check at application open to confirm that the local license file belongs to the current device and has not been transferred. It is also useful to check whether the local license file has been tampered with and whether the local license is still valid. For more information on performing local license checks, see the [**Getting Started Tutorial**](https://app.archbee.com/docs/FbT_Z5Cu33D-LVZx1fRkU/f9WUVI_a_a3MHSrCREa4h).

{% tabs %}
{% tab title="C++" %}

```cpp
license->localCheck(); // Perform a local (offline) check
license->check(); // Perform an online check
```

{% endtab %}

{% tab title="C#" %}

```csharp
license.LocalCheck(); //Perform a local (offline) check
license.Check(); //Perform an online check
```

{% endtab %}

{% tab title="Java" %}

```java
license.localCheck(); //Perform a local (offline) check
license = licenseManager.checkLicense( license ); //Perform an online check
```

{% endtab %}

{% tab title="Swift" %}

```swift
try license.localCheck()
try license.fullCheck()
```

{% endtab %}

{% tab title="Python" %}

```python
license.local_check()
license.check()
```

{% endtab %}
{% endtabs %}

### Retrieving Details of License User

User data such as email address, first name, last name, license ID, order ID, and order store ID can all be retrieved through the SDK. Initial passwords are also available on your local license file, but once the password has been changed, you will no longer be able to access that data using the LicenseSpring SDK. All this user data is stored and encrypted on your local license file. The SDK allows you to retrieve the data and decrypt it. For more on license encryption/decryption see our tutorial on [**Safety/Security Considerations**](https://docs.licensespring.com/sdks/tutorials/advanced-usage/security).

Here is how to retrieve a "User Data" object that contains such information

{% tabs %}
{% tab title="C++" %}

```cpp
license->licenseUser();
```

{% endtab %}

{% tab title="C#" %}

```csharp
license.LicenseUser();
```

{% endtab %}

{% tab title="Java" %}

```java
license.getData();
```

{% endtab %}

{% tab title="Swift" %}

```swift
let user = try license.user // User?.
```

{% endtab %}

{% tab title="Python" %}

```python
user_info = license.license_user()
print(user_info)
```

{% endtab %}
{% endtabs %}

### Modifying User Password

We can allow users to change their password. This can be done by the License Manager through the platform, but we can also allow end-users to change their password using our SDK. To change the password, we will require the original/old password and a new, replacement password. If the old password is correct, and the new password is valid, then the user's password will be changed. Note: this method requires internet connection.

{% tabs %}
{% tab title="C++" %}

```cpp
license->changePassword("old_password", "new_password");
```

{% endtab %}

{% tab title="C#" %}

```csharp
license.ChangePassword( "old password", "new password" );
```

{% endtab %}

{% tab title="Java" %}

```java
license.getData();//Java requires the Management SDK to be able to change passwords.
LicenseService licenseService = new LicenseService( configuration );
int userId = 123456789;
licenseService.setUserPassword( userId, "new password" );
```

{% endtab %}

{% tab title="Swift" %}

```swift
try license.changePassword(password: "old_pwd", newPassword: "new_pwd")
```

{% endtab %}

{% tab title="Python" %}

```python
manager = LicenseManager(conf)

license_id = LicenseID.from_user(username="python@gmail.com",password="7t_x3!o9")

license = manager.activate_license(license_id)

license.change_password("7t_x3!o9","12345678")
```

{% endtab %}
{% endtabs %}

#### Initiating Password Reset for First-Time Login

New accounts are created with a temporary, initial password. We can check if a license user is still using an initial password and prompt them to change their password using the following code:

{% tabs %}
{% tab title="C++" %}

```cpp
auto user = license->licenseUser();
if (user->isInitialPassword())
{
    // Prompt user to change password, use the change password method from the previous code block.
}
```

{% endtab %}

{% tab title="C#" %}

```csharp
var user = license.LicenseUser();
if ( user.IsInitialPassword)
{
    //Prompt user to change password, use the change password method from the previous code block.
}        
```

{% endtab %}

{% tab title="Java" %}

```java
//Java currently does not have an initialPassword feature.
```

{% endtab %}

{% tab title="Swift" %}

```swift
if license.user?.isInitialPassword == true {
    // Prompt user to change password.
    // Use the change password method from the previous example.
}
```

{% endtab %}

{% tab title="Python" %}

```python
user_data = license.license_user()

if user_data["is_initial_password"]:
     pass #ask user to change password
```

{% endtab %}
{% endtabs %}

### Retrieving All Customer-Associated License Users

To return the list of all the license users on every order by some customer use GetCustomerLicenseUsers method of the SDK. This method returns a list of LicenseUser objects that represents all license users associated with the customer.

{% tabs %}
{% tab title="C++" %}

```cpp
auto users = licenseManager->getLicenseUsers( "CustomerEmail@example.com" ); //get users by customer email

// or get them for the owner of current license
// auto customer = license->owner();
// auto users = licenseManager->getLicenseUsers( customer );
```

{% endtab %}

{% tab title="C#" %}

```csharp
var customer = new Customer( "CustomerEmail@example.com" ); //create Customer object using the email
//var customer = license.Owner();// or get the owner of current license
var users = licenseManager.GetCustomerLicenseUsers( customer );
```

{% endtab %}

{% tab title="Swift" %}

```swift
let users: manager.requestLicenseUsers(for: "customer@example.com") // [User].
```

{% endtab %}

{% tab title="Python" %}

```python
manager = LicenseManager(conf)

response = manager.get_user_licenses(license_id)
```

{% endtab %}
{% endtabs %}

### Retrieving multiple licenses of the same product assigned to a single user

It's possible for a single user to have multiple licenses of the same product assigned to them. In that case, we need to use another identifier to differentiate between different licenses.

The license API does that by assigning a 64-bit `license_id` to each license. To avoid collision with the `LicenseID` structure in the SDKs, we also call them server-side license identifiers, or shorter `serverId`.

To retrieve the license identifiers along with the license and user information, use the `GetUserLicenses` method, which returns a list of all license-user pairs assigned to the relevant user.

{% tabs %}
{% tab title="C++" %}

```cpp
std::string username = "sampleUser";
std::string password = "samplePassword";
userLicensesDataVec = licenseManager->getUserLicenses(username, password);
for (const auto& userLicensesData : userLicensesDataVec)
{ 
    // you can use the vector to create a license picker.
    // the UserLicense class contains license info.
    // the LicenseUser class contains user info.
    std::cout << userLicensesData->userLicense()->serverId() << std::endl; 
    auto user = userLicensesData->licenseUser();
}

std::string serverId = 123456; // pick a server-side license id
auto licenseId = LicenseID::fromUser(username, serverId, password);
auto license = licenseManager::activateLicense(licenseId);
```

{% endtab %}

{% tab title="C#" %}

```csharp
string username = "sampleUser";
string password = "samplePassword";
UserLicensesData[] userLicensesDataList = _licenseManager.GetUserLicenses(username, password);

foreach (UserLicensesData userLicensesData in userLicensesDataList)
{
    // You can use the list to create a license picker.
    // The License property contains license info.
    // The User property contains user info.
    Console.WriteLine(userLicensesData.License.Id);
    var user = userLicensesData.User;
}

long serverId = userLicensesDataList.First().License.Id; // Pick a server-side license id
LicenseID licenseId = LicenseID.FromUser(username, serverId, password);
ILicense license = _licenseManager.ActivateLicense(licenseId);
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
If you want to allow users to change licenses dynamically, make sure to set a different file name for the license file for different licenses.
{% endhint %}

### Common Errors

#### C++

| Exception                              | Error code                     | Definition                                                                                                |
| -------------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------- |
| ConfigurationException                 | eInitializationError           | Throws in case of something wrong with Configuration. E.g. wrong API or Shared key                        |
| InvalidCredentialException             | eInvalidCredential             | This exception means that user or password is wrong                                                       |
| LicenseActivationException             | eActivationFailed              | Rare exception, can arise if activation is limited to some device count or license transfer is prohibited |
| LicenseNoAvailableActivationsException | eLicenseNoAvailableActivations | Throws when license has already been activated maximum number of times                                    |
| PasswordChangeNotAllowedException      | ePasswordChangeNotAllowed      | This exception can arise if password change is restricted by company policy                               |

#### .Net

| Exception                         | Definition                                                                  |
| --------------------------------- | --------------------------------------------------------------------------- |
| InvalidCredentialException        | This exception means that user or password is wrong                         |
| CustomerNotFoundException         | In case customer does not exist                                             |
| InvalidAuthMethodException        | Thrown when GetCustomerLicenseUsers method is called for key-based product  |
| PasswordChangeNotAllowedException | This exception can arise if password change is restricted by company policy |
| MissingParametersException        | If empty string is passed to ChangePassword method                          |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.licensespring.com/sdks/tutorials/licensing-scenarios/user-based-licensing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
