You can access resources secured with user authentication, app authentication, or network authentication using the available credential types.
- ArcGIS credentials are used to access resources secured by ArcGIS authentication methods, such as OAuth, Identity-Aware Proxy (IAP), and ArcGIS token. For more information, see ArcGIS credentials.
- Network credentials are used to access resources secured by network authentication methods, such as Integrated Windows Authentication (IWA) and Client Certificate (PKI). For more information, see Network credentials.
ArcGIS credentials
You can access secure resources with user authentication or app authentication using any of the following credential types:
- OAuthUserCredential - A credential object used to access OAuth token-secured ArcGIS resources with a specific
OAuthUserConfiguration. - IapCredential - A credential object used to access ArcGIS Enterprise resources that are secured behind an Identity-Aware Proxy (IAP). You can create the credential using an
IapConfiguration. - OAuthApplicationCredential - A credential object used to access OAuth token-secured ArcGIS resources using the application's credentials.
- TokenCredential - A credential object used to access token-secured ArcGIS resources.
- PregeneratedTokenCredential - A credential object used to access token-secured ArcGIS resources using a token that is generated outside of your application.
If you know the service's domain/server context, you can create an ArcGIS credential independent of loading the specific resource and store it in the ArcGISCredentialStore.
OAuthUserCredential
To create an OAuthUserCredential, provide an OAuthUserConfiguration with a valid portal URL, client ID, and redirect URL. You must present a prompt, in a browser supported by the device, for the user to enter their username and password. The response from the browser should be handled within your activity or the fragment that launched the browser prompt. Once the OAuthUserCredential is created, you will be able to access the token information from the asynchronous token method.
void SecurityAndAuthentication::oauthUserCredentials(const QUrl& portalUrl, const QString& clientId,
const QString& redirectUri)
{
// Create a new OAuth user configuration using the supplied: portalUrl, clientId, redirectUri,
// and parent object.
OAuthUserConfiguration* oauthUserConfiguration = new OAuthUserConfiguration(
portalUrl, clientId, redirectUri, this);
// Get the OAuth user credential object from the static OAuth credential's create async method
// (uses QFuture).
OAuthUserCredential::createAsync(oauthUserConfiguration, this).then(
this, [this](OAuthUserCredential* oauthUserCredential)
{
// Get the OAuth user token info object from the OAuth credential's token info async method
// (uses QFuture).
oauthUserCredential->tokenInfoAsync(this).then(
this, [](Authentication::OAuthUserTokenInfo* oauthUserTokenInfo)
{
// Access the authentication OAuth user token info details here...
qDebug() << oauthUserTokenInfo->expirationDate();
});
});
}
IapCredential
The IapCredential supports access to an ArcGIS Enterprise portal and its services that are protected behind an Identity-Aware Proxy (IAP). ArcGIS Maps SDK for Qt currently supports the Microsort Entra Application Proxy via the Microsoft Identity Platform. To initiate an IAP authorization workflow, create an IapConfiguration to store your application's registration details and use it to create an IapCredential.
Use the following steps to create an IapCredential:
To establish trust between your application and the IAP, your administrator registers your application with the Microsoft Identity Platform. Following this, you can review the client ID, tenant ID, redirect url, and so on.
Create an IapConfiguration using these application registration details. Depending on your workflow, you can initialize an IapConfiguration by either providing the details in a JSON file or supplying them directly in the application's code.
To initialize the IapConfiguration with a JSON file, create a Microsort Entra Application Proxy JSON file containing the following key/value pairs:
{
"authorize_url" : "https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/authorize",
"token_url" : "https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/token",
"logout_url" : "https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/logout",
"client_id" : "<client_id>",
"redirect_url" : "<redirect_url>",
"scope" : [
"<client_id>/.default",
"offline_access",
"openid",
"profile"
],
"hosts_behind_proxy" : ["*.domain.com"],
"authorization_prompt_type" : "<empty string, none, login, consent, or select_account>"
}The keys are defined as follows:
- authorize_url - The authorization endpoint of the Identity-Aware Proxy (IAP) portal.
- token_url - The token endpoint of the Identity-Aware Proxy (IAP) portal.
- logout_url - The logout endpoint of the Identity-Aware Proxy (IAP) portal.
- client_id - A unique identifier associated with an application which is registered with the Identity-Aware Proxy (IAP) portal.
- redirect_url - The URL that the Identity-Aware Proxy (IAP) login and logout pages will redirect to when authentication completes. The scheme of this URL must be registered as a custom URL scheme in the application.
- scope - The scope of user's account.
- hosts_behind_proxy - The hosts to be accessed behind the Identity-Aware Proxy (IAP).
- authorization_prompt_type - The type of user interaction required for authentication and consent while signing in to the Identity-Aware Proxy (IAP).
Create the IapConfiguration using the IapConfiguration::createAsync() initializer.
// Create an IapConfiguration object using the static createAsync method by passing in the
// path to the JSON file on the device.
IapConfiguration::createAsync(path, this).then(this, [](IapConfiguration* iapConfiguration){
// Use the iapConfiguration object here...
qDebug() << iapConfiguration->clientId();
});
If the JSON file is missing any required properties, this IapConfiguration initializer will fail.
Alternatively, create the IapConfiguration by specifying each parameter in the IapConfiguration::create() initializer.
// Create an IapConfiguration object using the static create method by passing in all of
// the needed parameters listed.
IapConfiguration* iapConfiguration = IapConfiguration::create(
QUrl("https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/authorize"), // authorizeUrl
QUrl("https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/token"), // tokenUrl
QUrl("https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/logout"), // logoutUrl
QString("<client_id>"), // clientId
QString("<client_secret"), // clientSecret
QUrl("<redirect_url>"), // redirectUrl
QString("<iap_client>"), // iapClientId
QStringList({"<client_id>/.default", "offline_access", "openid", "profile"}), // scopes
QStringList({"*.domain.com"}), // hostsBehindProxy
IapAuthorizationPromptType::Login // authorizationPromptType
);
Best Practice: To avoid storing secure information in you application's code, the recommended approach is to use the IapConfiguration::createAsync() initializer with a JSON file on disk to create a IapConfiguration.
To ensure that the IapConfiguration can be used when an authentication challenge is issued for IAP credential, call apConfiguration::canBeUsedForUrl() using a URL specified in the configuration’s hosts behind proxy.
// Determine if the IapConfiguration object can be used for the supplied QUrl.
if(iapConfiguration->canBeUsedForUrl(
QUrl("<ArcGIS Enterprise resource URL of host specified in hostsBehindProxy>")))
{
qDebug() << "The IAP configuration supports access to the Identity-Aware Proxy.";
}
else
{
qDebug() << "The IAP configuration can not be used for the given url. Review the configuration parameters.";
}
Create the IapCredential using the IapConfiguration. This will present the Microsoft sign-in page for the user to enter their username and password. Once the IapCredential is created, it is added to the ArcGISCredentialStore and you can access its token property.
// Create an IapCredential object using the static createAsync method by passing in an
// IapConfiguration object.
IapCredential::createAsync(iapConfiguration).then(this,[this](IapCredential* iapCredential){
// Obtain the IapTokenInfo object from the IapCredential object using the tokenInfoAsync method.
iapCredential->tokenInfoAsync(this).then(this,[](IapTokenInfo* iapTokeninfo){
// Access the iapTokeninfo here...
qDebug() << iapTokeninfo->idToken();
});
});
During application sign-out, you must invalidate the credential by calling IapCredential::invalidateAsync(). This will present a Microsoft page that allows the user to sign-out. Note that after a successful sign-out, the browser will not redirect back to the application. The user must manually switch back to the application after sign-out.
// Get a bool using the invalidateAsync method on the IapCredential object to determine if
// if logout request was successful.
iapcredential->invalidateAsync().then(this,[](bool isInvalidated){
if(isInvalidated)
{
qDebug() << "The IAP Credential is invalidated";
}
else {
qDebug() << "The IAP Credential was not invalidated";
}
});
TokenCredential
To create a TokenCredential, provide a secured service URL, valid username, and password. Optionally, you can specify token expiration minutes. Once a TokenCredential is created, you will be able to access token information from the asynchronous token property.
void SecurityAndAuthentication::tokenCredentials(const QUrl& url, const QString& username,
const QString& password,
std::optional<int> tokenExpirationInterval)
{
// Get the token credential object from the static token credential's create async method
// (uses QFuture).
TokenCredential::createAsync(url, username, password,tokenExpirationInterval, this).then(
this, [this](TokenCredential* tokenCredential)
{
// Get the token info object from the token credential's token info async method (uses
// QFuture).
tokenCredential->tokenInfoAsync(this).then(
this, [](Authentication::TokenInfo* tokenInfo)
{
// Access the authentication token info info details here...
qDebug() << tokenInfo->expirationDate();
});
});
}
PregeneratedTokenCredential
To create a PregeneratedTokenCredential, provide a previously generated short or long-lived access token. Use this when the access token is created using the generateToken REST endpoint directly. You must provide the referer if one was used while generating the token.
// Create a new token info using the supplied: accessToken, expirationDate, isSslRequired,
// and parent object.
TokenInfo* tokenInfo = new TokenInfo(accessToken, expirationDate, isSslRequired, this);
// Create a new pregenerated token credential using the supplied: url, token info, referer,
// and parent object.
PregeneratedTokenCredential* pregeneratedTokenCredential = new PregeneratedTokenCredential(
url, tokenInfo, referer, this);
OAuthApplicationCredential
To create an OAuthApplicationCredential, provide a valid portal URL, a client ID, and a client secret. Optionally, you can specify the token expiration in minutes. Once the OAuthApplicationCredential is created, you will be able to access the token information from the asynchronous token property.
void SecurityAndAuthentication::oauthApplicationCredentials(const QUrl& portalUrl,
const QString& clientId,
const QString& clientSecret,
std::optional<int> tokenExpirationInterval)
{
// Get the OAuth application credential object from the static OAuth application credential's
// create async method (uses QFuture).
OAuthApplicationCredential::createAsync(portalUrl, clientId, clientSecret, tokenExpirationInterval,
this).then(this, [this](OAuthApplicationCredential* oauthApplicationCredential)
{
// Get the OAuth application token info object from the OAuth application
// credential's token info async method (uses QFuture).
oauthApplicationCredential->tokenInfoAsync(this).then(
this, [](OAuthApplicationTokenInfo* oauthApplicationTokenInfo)
{
// Access the OAuth application token token info info details here...
qDebug() << oauthApplicationTokenInfo->expirationDate();
});
});
}
Network credentials
You can access resources secured by network authentication using the following credential types:
- PasswordCredential - A credential object that is used to authenticate HTTP Basic or Integrated Windows Authentication (IWA) secured resources.
- CertificateCredential - A credential object that is used to authenticate Public Key Infrastructure (PKI) secured resources.
- ServerTrust - A network credential that specifies that a server should be trusted.
PasswordCredential
The PasswordCredential is used to authenticate HTTP Basic/Digest or Integrated Windows Authentication (IWA) secured resources.
// Get a password credential from the network credential password method.
PasswordCredential* passwordCredential =NetworkCredential::password(username, password, this);
CertificateCredential
CertificateCredential represents a digital client certificate used to access certificate secured resources. All digital certificates must be pre-installed in the device keychain. The CertificateCredential can be created using the alias of the chosen certificate.
// Get a certificate credential from the network credential certificate method.
CertificateCredential* certificateCredential = NetworkCredential::certificate(path, password, this);
ServerTrust
To trust a development server that uses a self-signed certificate (untrusted host), create a NetworkCredential and specify that the server should be trusted.
The following pseudo-code shows the generic steps to override the Network:
// Helpful reference docs:
// https://developers.arcgis.com/qt/cpp/api-reference/esri-arcgisruntime-authentication-networkauthenticationchallengehandler.html#dtor.NetworkAuthenticationChallengeHandler
// https://developers.arcgis.com/qt/cpp/api-reference/esri-arcgisruntime-authentication-networkauthenticationchallenge.html#networkChallengeType
// https://developers.arcgis.com/qt/cpp/api-reference/esri-arcgisruntime-authentication-servertrustcredential.html
class ServerTrustChallengeHandler : public NetworkAuthenticationChallengeHandler
{
public:
ServerTrustChallengeHandler(QObject* parent) :
NetworkAuthenticationChallengeHandler(parent)
{}
~ServerTrustChallengeHandler() override = default;
private:
void handleNetworkAuthenticationChallenge(NetworkAuthenticationChallenge* challenge) override
{
// Check if this is a ServerTrust challenge.
if (challenge->networkChallengeType() == NetworkChallengeType::ServerTrust)
{
ServerTrustCredential* credential = ServerTrustCredential::createWithChallenge(challenge, this);
challenge->continueWithCredential(credential);
challenge->deleteLater();
return;
}
}
};