Authorization
Full authorization reference for the Android SDK
The SDK exchanges data with the Engagement APIs through authorized HTTP/HTTPS communication. The SDK supports two authorization modes: the default token authorization for public API access and the more secure customer token authorization for private API access. Developers can choose the appropriate authorization mode for the required level of security.
Token authorization
The default token authorization mode provides public API access using an API key as a token.
Token authorization is used for the following API endpoints by default:
POST /track/v2/projects/<projectToken>/customers
for tracking of customer dataPOST /track/v2/projects/<projectToken>/customers/events
for tracking of event dataPOST /track/v2/projects/<projectToken>/campaigns/clicks
for tracking campaign eventsPOST /data/v2/projects/<projectToken>/customers/attributes
for fetching customer attributesPOST /data/v2/projects/<projectToken>/consent/categories
for fetching consentsPOST /webxp/s/<projectToken>/inappmessages?v=1
for fetching InApp messagesPOST /webxp/projects/<projectToken>/appinbox/fetch
for fetching of AppInbox dataPOST /webxp/projects/<projectToken>/appinbox/markasread
for marking of AppInbox message as readPOST /campaigns/send-self-check-notification?project_id=<projectToken>
for part of self-check push notification flow
Developers must set the token using the authorization
configuration parameter when initializing the SDK:
class App : Application() {
override fun onCreate() {
super.onCreate()
val configuration = ExponeaConfiguration()
configuration.authorization = "Token YOUR_API_KEY"
configuration.projectToken = "YOUR_PROJECT_TOKEN"
configuration.baseURL = "https://api.exponea.com"
Exponea.init(App.instance, configuration)
}
}
Customer token authorization
Customer token authorization is optional and provides private API access to select Engagement API endpoints. The customer token contains encoded customer IDs and a signature. When the Bloomreach Engagement API receives a customer token, it first verifies the signature and only processes the request if the signature is valid.
The customer token is encoded using JSON Web Token (JWT), an open industry standard RFC 7519 that defines a compact and self-contained way for securely transmitting information between parties.
The SDK sends the customer token in Bearer <value>
format. Currently, the SDK supports customer token authorization for the following Engagement API endpoints:
POST /webxp/projects/<projectToken>/appinbox/fetch
for fetching of AppInbox dataPOST /webxp/projects/<projectToken>/appinbox/markasread
for marking of AppInbox message as read
Developers can enable customer token authorization by setting the advancedAuthEnabled
configuration parameter to true
when initializing the SDK:
class App : Application() {
override fun onCreate() {
super.onCreate()
val configuration = ExponeaConfiguration()
configuration.projectToken = "YOUR_PROJECT_TOKEN"
configuration.baseURL = "https://api.exponea.com"
configuration.authorization = "Token YOUR_API_KEY" // !!! basic authorization is required
configuration.advancedAuthEnabled = true
Exponea.init(App.instance, configuration)
}
}
Additionally, developers must implement the com.exponea.sdk.services.AuthorizationProvider
interface, ensuring that the getAuthorizationToken
method returns a valid JWT token that encodes the relevant customer ID(s) and private API key ID:
class ExampleAuthProvider : AuthorizationProvider {
override fun getAuthorizationToken(): String? {
return "YOUR JWT TOKEN"
}
}
You must register your AuthorizationProvider
in your app's AndroidManifest.xml
file as:
<application
...
<meta-data
android:name="ExponeaAuthProvider"
android:value="com.your.app.security.ExampleAuthProvider"
/>
</application>
Customer tokens must be generated by a party that can securely verify the customer's identity. Usually, this means that customer tokens should be generated during the application backend login procedure. When the customer identity is verified (using password, 3rd party authentication, Single Sign-On, etc.), the application backend should generate the customer token and send it to the device running the SDK.
Refer to Generating customer token in the customer token documentation for step-by-step instructions to generate a JWT customer token.
Troubleshooting
If you implement AuthorizationProvider
but it is not working as expected, check the logs for the following:
- If you enable customer token authorization by setting the configuration flag
advancedAuthEnabled
totrue
but the SDK can't find a provider implementation, it will log the following message:
Advanced auth has been enabled but provider has not been found
- If you register an
ExponeaAuthProvider
class inAndroidManifest.xml
but the SDK cannot find it, it will log the following message:
Registered <your class> class has not been found with detailed info
- If you register an
ExponeaAuthProvider
class inAndroidManifest.xml
that doesn't implement theAuthorizationProvider
interface, it will log the following message:
Registered <your class> class has to implement com.exponea.sdk.services.AuthorizationProvider
Asynchronous implementation of AuthorizationProvider
The customer token value is requested for every HTTP call at runtime. The method getAuthorizationToken()
is written for synchronous usage but is invoked in a background thread. Therefore, you are able to block any asynchronous token retrieval (i.e. other HTTP call) and wait for the result by blocking this thread. If the token retrieval fails, you may return a NULL value but the request will automatically fail.
class ExampleAuthProvider : AuthorizationProvider {
override fun getAuthorizationToken(): String? = runBlocking {
return@runBlocking suspendCoroutine { done ->
retrieveTokenAsync(
success = {token -> done.resume(token)},
error = {error -> done.resume(null)}
)
}
}
}
Different network libraries support different approaches but the principle stays same - feel free to block the invocation of the
getAuthorizationToken
method.
Customer token retrieval policy
The customer token value is requested for every HTTP call that requires it.
Typically, JWT tokens have their own expiration lifetime and can be used multiple times. The SDK does not store the token in any cache. Developers may implement their own token cache as they see fit. For example:
class ExampleAuthProvider : AuthorizationProvider {
private var tokenCache: String? = null
override fun getAuthorizationToken(): String? = runBlocking {
if (tokenCache.isNullOrEmpty()) {
tokenCache = suspendCoroutine { done ->
retrieveTokenAsync(
success = {token -> done.resume(token)},
error = {error -> done.resume(null)}
)
}
}
return@runBlocking tokenCache
}
}
Please consider to store your cached token more securely. Android offers multiple options such as KeyStore or Encrypted Shared Preferences.
A customer token is valid until its expiration and is assigned to the current customer IDs. Bear in mind that if customer IDs change (due to invoking the
identifyCustomer
oranonymize
methods), the customer token may become invalid for future HTTP requests invoked for new customer IDs.
Updated about 1 month ago