Configuration
Add the Android SDK to your project
If you are using Gradle, you can add the library with the following dependency:
Gradle dependency
compile 'com.onegini.mobile.sdk.android:onegini-sdk:VERSION@aar' {
transitive = true
}
Instantiating the Android SDK
All functions of the Android SDK are available from a single facade, the OneginiClient
. The OneginiClient
is a singleton that has to be set up once with the OneginiClientBuilder
class. It can can be fetched via a OneginiClient.getInstance()
method afterwards.
Note
The Application (not Activity) context must be used to instantiate the OneginiClient
.
Client instantiation
public class OneginiSDK {
public static OneginiClient getOneginiClient(final Context context) {
OneginiClient oneginiClient = OneginiClient.getInstance();
if (oneginiClient == null) {
oneginiClient = buildSDK(context);
}
return oneginiClient;
}
private static OneginiClient buildSDK(final Context context) {
final Context applicationContext = context.getApplicationContext();
final RegistrationRequestHandler registrationRequestHandler = new RegistrationRequestHandler(applicationContext);
final CreatePinRequestHandler createPinRequestHandler = new CreatePinRequestHandler(applicationContext);
final PinAuthenticationRequestHandler pinAuthenticationRequestHandler = new PinAuthenticationRequestHandler(applicationContext);
// throws the OneginiConfigNotFoundException if the OneginiConfigModel class can't be found
return new OneginiClientBuilder(applicationContext, createPinRequestHandler, pinAuthenticationRequestHandler)
.setBrowserRegistrationRequestHandler(registrationRequestHandler)
.build();
}
}
The first method that must be called on OneginiClient
after application startup is OneginiClient#start()
. This method is responsible for asynchronous initialization of the Android SDK. During this process, the Android SDK can return errors, for example if the device is using a deprecated Android version or when the app version is outdated. The method expects a OneginiInitializationHandler
to return initialization results.
Client initialization
// method called during app's startup
private void setupOneginiSDK() {
final OneginiClient oneginiClient = OneginiSDK.getOneginiClient(this);
oneginiClient.start(new OneginiInitializationHandler() {
@Override
public void onSuccess(final Set<UserProfile> removedUserProfiles) {
// remove UserProfiles that were removed on the server side and proceed with you application flow
}
@Override
public void onError(final OneginiInitializationError error) {
// handle different error types
}
});
}
Configuration model
Configuration properties should be provided to the Android SDK via an implementation of the OneginiClientConfigModel
interface. The implementation can be provided in two ways:
-
If the Mobile SDK Configurator script was used to apply configuration and certificate pinning to your app project, the
OneginiClientConfigModel
implementation is added to the app's main directory. In such case, the Android SDK uses reflection and theContext#getPackageName()
method to search for a class called{your.application.package}.OneginiConfigModel
that implements theOneginiClientConfigModel
interface. If the proper class can't be found, the Android SDK throws aOneginiConfigNotFoundException
exception. -
To create the implementation manually, or to move the generated implementation to a different (sub)package, then you can explicitly provide the config using the
OneginiClientBuilder#setConfigModel()
method.
Code example OneginiClientConfigModel implementation
// ...
final OneginiClientConfigModel configModel = new OneginiClientConfigModel() {
/**
* Application identifier, as configured in the IDAAS-core.
* Please note that once set, the ID should not change. Otherwise the SDK will not be able to resolve internally stored data.
*/
@Override
public String getAppIdentifier() {
return "myAppId";
}
/**
* Application platform, as set within application version in the IDAAS-core.
* Please note that once set, the platform should not change. Otherwise the SDK will not be able to resolve internally stored data.
*/
@Override
public String getAppPlatform() {
return "android";
}
/**
* Redirect uri used in the callback from the authentication process to the client
* @return the redirect uri used in the callback
*/
@Override
public String getRedirectUri() {
return "oneginisdk://loginsuccess";
}
/**
* Application version, as set within application version in the IDAAS-core.
*/
@Override
public String getAppVersion() {
return "1.0";
}
/**
* IDAAS-core's base url.
*/
@Override
public String getBaseUrl() {
return "https://acme.token-server.com";
}
/**
* Resource server base url.
*/
@Override
public String getResourceBaseUrl() {
return "https://acme.resource-gateway.com";
}
/**
* Resource containing certificate-to-pin identifier, by default it's `keystore.bks` located in `res/raw`.
*/
@Override
public int getCertificatePinningKeyStore() {
return R.raw.keystore;
}
/**
* Certificate-to-pin (`keystore.bks`) hash.
*/
@Override
public String getKeyStoreHash() {
return "52b7a8bb2a72356d271a6df6bdfc88f4d78e46913adca54da77a70f260e12af3";
}
/**
* Device name. Will be used during client registration process, allows user to distinguish his devices more precisely.
* Please note that once set, the device name should not change. Otherwise the SDK will not be able to resolve internally stored data.
*/
@Override
public String getDeviceName() {
return android.os.Build.MODEL;
}
/**
* The hexadecimal server public key used to perform a Payload Encryption handshake. Can be null if Payload Encryption is not used.
*/
public String getServerPublicKey() {
return "355C555820D47CB2010F601D96CB134A3026BFEC7F23732E0890CD5E62AB2D24";
}
}
final OneginiClient oneginiClient = new OneginiClientBuilder(applicationContext, createPinRequestHandler, pinAuthenticationRequestHandler)
.setConfigModel(configModel)
.build();
// ...
Certificate pinning
The Android SDK provides functionality to pin your servers certificate. If you pin the servers certificate itself, you will need to deploy a new version of the application when you change the servers certificate. We recommend using the intermediate certificate of the Certificate Authority used to get the server certificate (the second level in the certificate chain). This gives you the option to renew the server certificate without having to deploy a new version of the application.
Export the certificate
You can use Firefox to export the certificate. Click on the lock of the SSL website. Choose: more information. In the security tab, press View certificate, then go to the details tab. And there you can choose which certificate in the chain you wish to export.
Creating a keystore
In order to create a keystore you need a Java JDK installed to get a keytool. And for Android you need Bouncy Castle 1.46 (newer versions of Bouncy Castle create a keystore with a different header, which is not accepted by Android).
http://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on/1.46
Create keystore
keytool -import -alias MYALIAS -file /PATH/TO/CERTIFICATE/FROM/EXPORT -keystore /PATH/TO/keystore.bks -storepass PASSWORD -providerpath /PATH/TO/BOUNCYCASTLE/1.46/bcprov-ext-jdk15on-1.46.jar -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
Add the keystore to the project
The keystore has to be added to the raw directory of your Android project. And your configuration needs to provide the keystore within the configuration. For example:
Keystore configuration
@Override
public int getCertificatePinningKeyStore() {
return R.raw.keystore;
}
Keystore tampering protection
As the keystore is stored on the file system of the device, theoretically it is possible to tamper it. This is possible if the device is rooted and some malicious application is installed. To prevent a tampered keystore, an SHA 256 hash of the keystore has to be provided by the application. It is recommended to have the hash hardcoded and not in a separate property file or any other file on the file system.
Calculating the keystore hash
shasum -a 256 keystore.bks
Example code of hash in config model
@Override
public String getKeyStoreHash() {
return "7A8E3D2333A1324229712B288950E317CE5BE5F956C196CEF33B46993D371575";
}
Providing your own authentication request handlers and callbacks
When the IDAAS-core returns oAuth 2.0 refresh tokens, the user needs to provide a PIN or a fingerprint to store those credentials. For this, you need to provide your own authentication request handlers using OneginiClientBuilder
methods. The OneginiCreatePinRequestHandler
and OneginiPinAuthenticationRequestHandler
are required to perform basic registration and authentication with PIN. Other handlers are optional and should be provided only when the app uses functionalities like fingerprint or mobile authentication. See Registration/Authentication request handlers for more information.
Other OneginiClient settings
OneginiClientBuilder
exposes additional methods to customize OneginiClient
behavior:
shouldStoreCookies(final boolean shouldStoreCookies)
method can be used to specify if the HTTP client should store cookies between requests. The default value is TRUE.setHttpConnectTimeout(final int timeout)
method can be used to specify the HTTP client's connection timeout (in milliseconds). Default value is60000
(60s).setHttpReadTimeout(final int timeout)
method can be used to specify the HTTP client's read timeout (in milliseconds). Default value is60000
(60s).setDeviceConfigCacheDurationSeconds(final long cacheDurationSeconds)
method can be used to specify device configuration cache duration (in seconds). Default value is300
(5 minutes). Passing0
will disable the cache.
Sample initialization call
public static OneginiClient getOneginiClient(final Context context) {
OneginiClient oneginiClient = OneginiClient.getInstance();
if (oneginiClient == null) {
final Context applicationContext = context.getApplicationContext();
final RegistrationRequestHandler registrationRequestHandler = new RegistrationRequestHandler(applicationContext);
final OneginiCreatePinRequestHandler createPinRequestHandler = new CreatePinRequestHandler();
final OneginiPinAuthenticationRequestHandler pinAuthenticationRequestHandler = new PinAuthenticationRequestHandler();
final OneginiFingerprintAuthenticationRequestHandler fingerprintAuthenticationRequestHandler = new FingerprintAuthenticationRequesthandler();
// will throw OneginiConfigNotFoundException if OneginiConfigModel class can't be found
oneginiClient = new OneginiClientBuilder(applicationContext, createPinRequestHandler, pinAuthenticationRequestHandler)
.setBrowserRegistrationRequestHandler(registrationRequestHandler)
// optional settings
.setFingerprintAuthenticationRequestHandler(fingerprintAuthenticationRequestHandler)
.setConfigModel(new OneginiConfigModel())
.setHttpReadTimeout(30000)
.setDeviceConfigCacheDurationSeconds(600)
.build();
}
return oneginiClient;
}
``