Android SDK
How to install, configure and use the Castle Android SDK to perform device fingerprinting and monitor user activity.
👩💻 Looking for the source code?
The Castle Android SDK is available on GitHub.
Introduction
The Android SDK is a central component of the Castle integration, and provides device fingerprinting, behavioral analysis, and client-side event monitoring.
All the client-side SDKs, have two main purposes:
- Create request tokens. Generate a unique token to be passed to your server and used when calling Castle's Risk and Filter APIs.
- Tracking client-side events. Track important in-app events directly from the client to the Castle API.
Configuration
Once installed, the SDK needs to be configured using your Publishable Key, which can be found in the Dashboard for users with administrator access.
import io.castle.android.Castle
// Place the below in your Application class onCreate method
Castle.configure(application, "{Publishable-API-Key}")
import io.castle.android.Castle;
// Place the below in your Application class onCreate method
Castle.configure(application, "{Publishable-API-Key}");
The Castle Android SDK collects fingerprint information from the device and sends this information directly to Castle. These requests are batched to optimize device performance. See the last section, Configuration Notes, to make changes to the way Castle collects and batch-processes this fingerprint information.
Creating request tokens
The SDK generates a request_token
, which is a required field in the Risk and Filter APIs.
It's recommended that you forward the request token as a request header to every request to your API, since then you won't need to update the app whenever you're adding new server-side calls to Castle. The default value of the header is X-Castle-Request-Token
, but you can specify the header name in the SDK configuration.
Request tokens don't live forever
A new request token value should to be generated for each request to your backend. A request token will expire after 120 seconds and should only be used during a single request to your backend. It's recommended that you implement the token generation as a client-side middleware which generates a new request token with each request to your backend.
Examples on how to pass the request token to your server
// OkHttp
requestBuilder.header(
Castle.requestTokenHeaderName,
Castle.createRequestToken()
);
// HttpURLConnection
httpUrlConnection.setRequestProperty(
Castle.requestTokenHeaderName,
Castle.createRequestToken()
);
// Volley
headers.put(
Castle.requestTokenHeaderName,
Castle.createRequestToken()
);
// OkHttp
requestBuilder.header(
Castle.requestTokenHeaderName,
Castle.createRequestToken()
)
// HttpURLConnection
httpUrlConnection.setRequestProperty(
Castle.requestTokenHeaderName,
Castle.createRequestToken()
)
// Volley
headers.put(
Castle.requestTokenHeaderName,
Castle.createRequestToken()
)
The createRequestToken
method doesn't accept any options, and it generates tokens immediately in a non-blocking way.
Tracking client-side events
Step 1. Exposing the user object from your backend
The SDK offer two methods of sending data: screen
and custom
(described below) depending on which type of action the user performs. Common for these calls is that a user
object needs to be provided. The contents of the user
object are the same as for the the Risk and Filter APIs.
def castle_user
return {
id: 'ca1242f498', # required
email: '[email protected]', # required
phone: '+1415232183', # required if email is not present
name: 'Michael Brown',
registered_at: '2012-12-02T00:30:08.276Z',
traits: {
plan: 'premium'
}
}
end
In order to prevent user information from being spoofed by a bad actor, it is required that you encode the user information as a signed JWT on your backend.
From your backend code, you encode the user as a JWT and sign it using your Castle API Secret. Later, when Castle receives the JWT, the integrity of the user data will be verified to ensure that the data isn't being tampered with.
Below is an example of how to generate a JWT using the Ruby language, and exposing it as an endpoint called from your mobile app:
# Put behind authorization to have access to the logged in user
post '/castle_user_jwt' do
JWT.encode(castle_user, ENV.fetch('CASTLE_API_SECRET'), 'HS256')
end
Step 2. Setting the user in your app
Now that your server API exposes the /castle_user_jwt
endpoint, you'll request it from your mobile app and put it into the userJwt
method. This method caches the user object for subsequent requests to screen
and custom
.
// IMPLEMENT: fetch the user_jwt from your /castle_user_jwt endpoint
Castle.userJwt("{user_jwt}");
// IMPLEMENT: fetch the user_jwt from your /castle_user_jwt endpoint
Castle.userJwt("{user_jwt}")
Step 3. Sending screen views from your app
Passing the title of each screen view to Castle offers your analysts detailed insights into user patterns that will help uncover complex fraud patterns. It's recommended that you centralize this logic so that you won't have to explicitly call screen
for each new screen view. At the very least, it's recommended that you call screen
for each step in the user onboarding flow, as well as any critical views such as transactions or user settings.
Castle.screen("Onboarding – Verify documents");
Castle.screen("Onboarding – Verify documents")
Step 4. Sending custom events from your app
Any user action that isn't covered by screen views can be tracked by calling the custom
function. This also allows you to send custom properties related to the user action.
Castle.custom("Added to Cart", Map.of(
"product", "iPhone 13 Pro",
"price", 1099.99
));
Castle.custom("Added to Cart", mapOf(
"product" to "iPhone 13 Pro",
"price" to 1099.99
))
Additional configuration
The SDK allows for additional configuration options. Please refer to the documentation packaged with the SDK code for full details.
ArrayList<String> baseURLAllowList = new ArrayList<>();
baseURLAllowList.add("https://m.castle.io/");
CastleConfiguration configuration = new CastleConfiguration.Builder()
.publishableKey("{Publishable-API-Key}")
.debugLoggingEnabled(true) // Default false
.flushLimit(10) // Default 20
.baseURLAllowList(baseURLAllowList)
.maxQueueLimit(100) // Default 1000
.build();
// Setup Castle SDK with provided configuration
Castle.configure(application, configuration);
val configuration = CastleConfiguration.Builder()
.publishableKey("{Publishable-API-Key}")
.debugLoggingEnabled(true) // Default false
.flushLimit(10) // Default 20
.baseURLAllowList(listOf("https://m.castle.io/"))
.maxQueueLimit(100) // Default 1000
.build()
// Setup Castle SDK with provided configuration
Castle.configure(application, configuration)
Queue flushing
The SDK queues API calls to save battery life, and it only flushes queued events to the Castle API whenever the app is installed, updated, opened or closed, or when the queue reaches 20 events.
Updated 5 months ago