Why do it?

LuciadCPillar allows you to connect to several web services. In practice, such web services are often access-restricted: they require authentication through a username and a password before they grant access.

How to do it?

By configuring a custom ICredentialsProviderICredentialsProviderICredentialsProvider in the LuciadCPillar EnvironmentEnvironmentEnvironment class, you can provide credentials. You must create the EnvironmentEnvironmentEnvironment class when you start using the LuciadCPillar library. For more information about using the environment, see the first map application sample.

Implementation notes

Implementations of ICredentialsProviderICredentialsProviderICredentialsProvider must be thread-safe.

The interface offers several methods that allow you to implement caching of user credentials supplied through a login panel. When registering an ICredentialsProviderICredentialsProviderICredentialsProvider on the EnvironmentEnvironmentEnvironment, you can indicate if you want to make use of an internal credentials caching implementation in LuciadCPillar, or if you want to perform the caching yourself.

The internal loader within LuciadCPillar supports these authentication schemes:

  • Basic

  • Digest

Integration in UI frameworks

The samples offer a ICredentialsProviderICredentialsProviderICredentialsProvider implementation that opens a credentials dialog. The ICredentialsProviderICredentialsProviderICredentialsProvider sends back as the result the credentials entered in the dialog form.

Program: An ICredentialsProvider implementation
/**
 * This implementation of `ICredentialsProvider` relies on the _internal_ caching functionality offered
 * within LuciadCPillar (see Environment#withCredentialsProvider). Therefore, only the `getCredentials`
 * method is implemented and it always presents a user dialog to get the user information.
 */
class QtSampleCredentialsProvider final : public luciad::ICredentialsProvider {
public:
  explicit QtSampleCredentialsProvider() : _parent(nullptr) {
  }

  void setParent(QObject* parent) {
    _parent = parent;
  }

  std::shared_ptr<luciad::Credentials> getCredentials(const luciad::AuthenticationScope& authenticationScope) override {
    return _parent ? QtCredentialsDialog::getCredentials(_parent, authenticationScope) : nullptr;
  }

  void confirmCredentials(const luciad::AuthenticationScope& authenticationScope, const std::shared_ptr<luciad::Credentials>& credentials) override {
  }

  void removeCredentials(const luciad::AuthenticationScope& authenticationScope, const std::shared_ptr<luciad::Credentials>& credentials) override {
  }

private:
  QObject* _parent;
};
/**
 * This implementation of `ICredentialsProvider` relies on the _internal_ caching functionality offered
 * within LuciadCPillar (see Environment#WithCredentialsProvider). Therefore, only the `getCredentials`
 * method is implemented and it always presents a user dialog to get the user information.
 */
public class WpfSampleCredentialsProvider : ICredentialsProvider
{
    public Window Parent { get; set; }

    public Credentials GetCredentials(AuthenticationScope authenticationScope)
    {
        // Create a credentials view model with a description for the credentials that are required
        var description = GetDescription(authenticationScope);
        var viewModel = new CredentialsDialogViewModel()
        {
            Description = description
        };

        // Create and open a modal (blocking) dialog that allows the user to set the credentials
        bool? accepted = false;
        Application.Current.Dispatcher.Invoke(delegate
        {
            var credentialsDialog = CreateCredentialsDialog(viewModel);
            accepted = credentialsDialog.ShowDialog();
        });

        // Return the supplied credentials
        var userName = viewModel.UserName;
        var password = new System.Net.NetworkCredential(string.Empty, viewModel.Password).Password;
        return accepted == true ? new UsernamePasswordCredentials(userName, password) : null;
    }

    public void ConfirmCredentials(AuthenticationScope authenticationScope, Credentials credentials)
    {
    }

    public void RemoveCredentials(AuthenticationScope authenticationScope, Credentials credentials)
    {
    }

}
/**
 * This implementation of `ICredentialsProvider` relies on the _internal_ caching functionality offered
 * within LuciadCPillar (see Environment#withCredentialsProvider). Therefore, only the `getCredentials`
 * method is implemented.
 */
class AndroidCredentialProvider : ICredentialsProvider {

    override fun getCredentials(authenticationScope: AuthenticationScope): Credentials {
        return UsernamePasswordCredentials(USER, PASSWORD)
    }

    override fun confirmCredentials(
        authenticationScope: AuthenticationScope,
        credentials: Credentials
    ) {
    }

    override fun removeCredentials(
        authenticationScope: AuthenticationScope,
        credentials: Credentials
    ) {
    }
}

This code snippet shows how to configure the ICredentialsProviderICredentialsProviderICredentialsProvider on the EnvironmentEnvironmentEnvironment. In this configuration, LuciadCPillar caches the credentials itself.

Program: Configuring the ICredentialsProvider
std::shared_ptr<Environment> environment = Environment::createInitializer()
                                               .withLicenseText(licenseText)
                                               .withLoggingBackend(std::make_shared<SpdlogLoggingBackend>("sample_dataformats.log"))
                                               .withCredentialsProvider(credentialsProvider, true)
                                               .initialize();
_credentialsProvider = new WpfSampleCredentialsProvider();
_environment = Environment.CreateInitializer()
    .WithLicenseText(licenseText)
    .WithCredentialsProvider(_credentialsProvider, true)
    .WithLoggingBackend(new NLogLoggingBackend("sample_dataformats.log"))
    .Initialize();
val credentialProvider = AndroidCredentialProvider()
val environment = Environment.createInitializer()
    .withLicenseText(licenseText)
    .withResourcePath(getPath(application).resolve("resources").toString())
    .withCredentialsProvider(credentialProvider)
    .initialize()