TrustBuilder ID SDK (Android)
The SDK is available on demand. Please contact your TrustBuilder's point of contact.
The TrustBuilder ID SDK allows you to develop a mobile app that runs natively on a device. Native mobile applications can use native or browser-based login flows.
In a hosted login flow, the user is shown a web browser and redirected to the TrustBuilder hosted login page for sign up or log in. For example: an iOS application opens a SafariViewController or an Android application opens a Custom Chrome Tab.
With a native login flow, the user signs up or enters their password directly into the app. Note, however, that when using external IDPs, an iOS app may still open a SafariViewController and an Android app may still open a Custom Chrome Tab for the interaction with external IDPs.
Regardless of which option you choose, TrustBuilder supports either.
TrustBuilder ID SDK is a mobile SDK for communicating using OAuth 2.0 and OpenID Connect. It maps the raw protocol flows and adds convenience methods to assist with common tasks like performing an action with fresh tokens and to obtain user profile information.
Best practice
The TrustBuilder ID SDK wraps following functionality:
Secure protocol handling
Secure token lifecycle
Secure user profile access
Persona-driven policies
Handle session obligations
Handle onboarding obligations
Blacklist checking
Phishing/security concerns: an unauthorized party could decompile or intercept traffic to/from your application to get the Client ID and authentication URL. With this information the unauthorized party could create a rogue application, upload it to an application store, and use it to phish for usernames, passwords, and Access Tokens.
An authorization request is dispatched to the TrustBuilder.IO AuthorizationService instance, and the response will be dispatched to the activity of your choice, expressed via an Intent. The TrustBuilder ID SDK supports the PKCE extension to OAuth which was created to secure authorization codes in public clients when custom URI scheme redirects are used. The TrustBuilder ID SDK encapsulates the authorization state of the user and communicates with the TrustBuilder.IO platform.
Token requests, such as obtaining a new access token using a refresh token, follow a similar pattern and are dispatched to TrustBuilder.IO, and a token response instance is returned via a callback. Responses update the authorization state in order to track and persist changes. Once in an authorized state, access tokens can be automatically refreshed as necessary before performing actions that require valid tokens.
The TrustBuilder ID SDK follows best practice set out in RFC 8252 - OAuth 2.0 for Native Apps, authorization requests from native apps should only be made through external user-agents, primarily the user's browser. For this reason, WebView
is explicitly not supported for security reasons.RFC 8252 OAuth 2.0 for Native Apps. Using a web browser for OAuth and OIDC is not only a security imperative but also a user experience advantage. By leveraging trusted browser environments and educating users on the benefits, we can ensure a seamless and secure authentication process.
RFC 8252 Guidelines as defined by IETF
OAuth 2.0 and Native Apps: OAuth 2.0 authorization requests from native apps should only be made through external user-agents, primarily the user's browser. This is a security best practice as outlined in RFC 8252.
Prohibition of Embedded User-Agents: Native apps must not use embedded user-agents for authorization requests. Embedded user-agents can compromise security by allowing access to the user's full authentication credentials.
Google's Stance on WebView
Google has explicitly discouraged the use of WebViews for OAuth 2.0 requests, citing security and usability concerns. This position is detailed in their support article.
System Browser as a Secure Alternative
The use of a system browser is the more secure and trusted method for authorization flows. Platforms like iOS and Android have developed APIs that allow apps to launch a system browser within the app context, maintaining security without compromising the user experience. Google has implemented a secure browser policy to reinforce this practice.
Platform standard implementation
iOS and Android: Both platforms provide specific ways to initiate authorization in a browser (e.g., iOS's SFSafariViewController/SFAuthenticationSession and Android's Custom Tab feature), ensuring a seamless and secure experience.
Google's OAuth Policies: Google's OAuth policies emphasize the use of browsers over embedded webviews, aligning with security best practices. (https://developers.google.com/identity/protocols/oauth2/policies#browsers )
User Experience Considerations
Trust and Familiarity: Users generally trust their browser environment. Features like address verification in browsers enhance trust compared to embedded webviews.
Platform Standards and Security: The embedded browser is a platform standard for both iOS and Android. Prioritizing security, users can benefit from the familiar interface of their system browser.
Educating Users: Instead of compromising security, educating users through an onboarding flow can enhance their understanding and acceptance of browser-based authentication.
Cancellation handling: Because having alternative flows when the user intentionally closes could be desired, we allow checking on that specific flow.
1. Configure TrustBuilder
To use TrustBuilder services, you need to have an application set up in the TrustBuilder Dashboard. The TrustBuilder application is where you will configure authentication in your project.
1.2 Configure your application
Use the Admin Portal to configure a new TrustBuilder application or select an existing application that represents the project you want to integrate with. Every application in TrustBuilder is assigned an alphanumeric, unique client ID that your application code will use to call TrustBuilder APIs through the SDK.
1.3 Configure callback URLs
A callback URL is the application URL that TrustBuilder will direct your users to once they have authenticated. If you do not set this value, TrustBuilder will not return users to your application after they log in.
1.4 Configure logout URLs
A logout URL is the application URL TrustBuilder will redirect your users to once they log out. If you do not set this value, users will not be able to log out from your application and will receive an error.
2. Install the TrustBuilder ID SDK
2.1 Move all files to library folder
Move the following files into the library folder of your Android project. In this guide we use 'libs' folder.
TB.Identity.aar
VDDocumentCapture.aar
VDPhotoSelfieCapture.aar
VDLibraryCommonCore.aar
VDLibraryCommonCoreJvm.jar
VDLibraryCommonImageProcessing.aar
VDLogger.aar
2.2 Gradle dependencies
Add the library files to your dependencies in your Android build.gradle file. This can be done in 2 ways.
Also add extra dependencies, required by us or the Veridas SDK.
dependencies {
// <Your Android project dependencies>
...
// TrustBuilder ID packages
// 1. Add each file individually:
implementation files('libs/TB.Identity.aar')
implementation files('libs/VDDocumentCapture.aar')
implementation files('libs/VDPhotoSelfieCapture.aar')
implementation files('libs/VDLibraryCommonCore.aar')
implementation files('libs/VDLibraryCommonCoreJvm.jar')
implementation files('libs/VDLibraryCommonImageProcessing.aar')
implementation files('libs/VDLogger.aar')
// 2. OR add all .aar and .jar files in your libs folder:
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Extra dependencies required for the TrustBuilder ID SDK
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'net.openid:appauth:0.11.1'
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.auth0.android:jwtdecode:2.0.2'
implementation 'androidx.exifinterface:exifinterface:1.3.7'
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'com.github.bumptech.glide:glide:4.16.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22"
implementation group: 'net.lingala.zip4j', name: 'zip4j', version: '2.9.1'
}
You can change the versions of the dependencies, although we can't guarantee that the SDK will still work if you do.
2.3 AndroidManifest
The following settings are required in your AndroidManifest on your "Application" level.
<application
android:largeHeap="true"
android:allowBackup="false"
tools:replace="android:allowBackup"
...
</application>
To handle the redirect after authorization you need to setup the "appAuthRedirectScheme". You can do this by adding the following in your AndroidManifest.xml file in <application>:
<activity
android:name="net.openid.appauth.RedirectUriReceiverActivity"
tools:node="replace"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="${appAuthRedirectScheme}"/>
</intent-filter>
</activity>
In your build.gradle add the domain for redirects. This should be aligned with the redirectUri used when creating an instance of TBService and your IDHUB settings.
When your redirect Uri is: "com.yourcompany.yourapplication://login-callback" your appAuthRedirectScheme would be "com.yourcompany.yourapplication"
manifestPlaceholders = [
'appAuthRedirectScheme': '<App domain used for redirect>'
]
2.4 Creating the TBLoginService
First, ensure that you have created an instance of the TBLoginService for either the browser flow or the native flow.
For the Browser flow:
CODETBLoginService tbService = TBLoginService.createBrowserService( Uri authorizationEndpoint: <your authorization endpoint>, Uri tokenEndpoint: <your token endpoint>, Uri endSessionEndpoint: <your end session endpoint>, String clientId: <your client id>, Uri redirectUri: <your configured redirect url>, double expirationThreshold: <Threshold to be used for fetching new tokens>, Context context: <Your Android Application context>)
For the native flow:
CODETBLoginService tbService = TBLoginService.createNativeService( Uri idpStepUpEndpoint: <your allowed step-ups endpoint>, Uri authorizationEndpoint: <your authorization endpoint>, Uri tokenEndpoint: <your token endpoint>, Uri endSessionEndpoint: <your end session endpoint>, String clientId: <your client id>, Uri redirectUri: <your configured redirect url>, double expirationThreshold: <Threshold to be used for fetching new tokens>, Context context: <Your Android Application context>)
This instance will allow you to access all of the behavior that is facilitated in this SDK.
Behind the scenes, we will also retrieve a fresh access token automatically when trying to retrieve information from the UserInfo API.
authorizationEndpoint
The endpoint used for the authorization. This is configured in TrustBuilder portal.
An example of a authorization endpoint can beyourcompany.trustbuilder.io/idhub/oidc/v1/authorize
tokenEndpoint
The endpoint used to fetch the tokens. This is configured in TrustBuilder portal.
An example of a token endpoint can beyourcompany.trustbuilder.io/idhub/oidc/v1/token
endSessionEndpoint
The endpoint used to logout the user. This is configured in the TrustBuilder portal.
An example of a end session endpoint can beyourcompany.trustbuilder.io/idhub/oidc/v1/logout
clientId
OAuth 2.0 Client Identifier valid at the Authorization Server.redirectUri
Redirection URI to which the response will be sent. This URI MUST exactly match one of the Redirection URI values for the Client pre-registered at the TrustBuilder portal under the correct Service Provider(simple string comparison)tokenRefreshThreshold
ThetokenRefreshThreshold
will be used during the check whether a token is still valid or not. This way it's possible to already refresh a token a bit before it's actually expired.
This value should be identical with the value configured in TrustBuilder.context
The Android Application context. This is required for the SDK to use secure storage for the authorization tokens.
2.5 Creating the TBOnboardingService
First, ensure that you have created an instance of the TBOnboardingService.
TBOnboardingService tbOnboardingService = TBOnboardingService.createOnboardingService(
Uri tenantUrl: <your tenantUrl>,
Context context: <Your Android Application context>,
List<String> documentIds: <IDs of the documents you allow>,
Map<String, String> documentConfiguration: <The UI configuration of the document scanner>,
Map<String, String> selfieConfiguration: <The UI configuration of the selfie scanner>)
tenantUrl
The uri used for the validation. This is your TrustBuilder domain
An example of a tenantUrl endpoint can beyourcompany.trustbuilder.io
context
The Android Application context. This is required for the SDK for the document and selfie scanner.documentIds
The document ID's to search for. The complete list can be found at: https://docs.veridas.com/document-sdk/android/v4.18/documents/documentConfiguration
Configuration of the UI of the document scanner. A default is available in the demo app.
An overview of the configurable parameters can be found here: https://docs.veridas.com/document-sdk/android/v4.18/configuration/selfieConfiguration
Configuration of the UI of the selfie scanner. A default is available in the demo app.
An overview of the configurable parameters can be found here: https://docs.veridas.com/sap-sdk/android/v3.12/configuration/
3. TBLoginService - Hosted Login
The authentication flow via the browser can be triggered using the authenticateWithBrowser
method on your instance of TBLoginService.
3.1 Sign in
Android will use the on ActivityResult of your Activity to handle the browser result. This result needs to be passed to the SDK.
Then the SDK will fetch the tokens and store these in a secure storage.
You need to include:
Your Android Activity
Your scopes. These are configured in IDHUB and should match.
The instance that implements
ITBServiceCallback
Once that is finished authenticateWithBrowserITBServiceCallback.onTBServiceResult
will be triggered.
This interface (ITBServiceCallback) needs to be implemented in your code.
The following steps are required:
Start the authorize flow
Catch the ActivityResult and pass the result to the SDK (onAuthenticationResult)
ITBServiceCallback will be triggered with success or an error.
Usage
// Your Android Activity that also implements ITBServiceCallback.
// Execute the following to start the authorize flow
public void authorize(Activity activity){
List<String> scopes = Arrays.asList("openid", "users:self");
tbService.authenticateWithBrowser(activity, scopes, this);
}
// Your Android Activity will capture the result. Pass this to the SDK.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
tbLoginService.onAuthenticationResult(requestCode, data, this);
}
// Result of be send via this callback.
// EResultContext indicates if it's concerning Login or Logout flow.
@Override
public void onTBServiceResult(@NonNull Result<EResultContext> result) {
...
}
3.2 Accessing the token
When later in your application you want to access the token to authorize your api calls with, you can simply use getAndRefreshTokenWhenNecessary
on that same TBLoginService instance.
You are technically not required to use that same instance, but you can create a new one with the same configuration.
This method will check whether the token is at least valid for the time in the given threshold when the instance TBLoginService was created.
When that is not the case, the SDK will try to refresh the access token and return the refreshed one.
Usage
public void getToken(Activity activity){
Future<Result<String>> future = tbLoginService.getTokenAndRefreshWhenNeeded(activity);
Result<String> result = future.get();
}
3.3 User canceled flow
When the user canceled the flow the SDK will return an AuthorizationException with the following properties:
Code: 1
errorDescription: "User canceled flow"
detailMessage: "User canceled flow"
4. TBLoginService - Native Login
The native flow will work differently than the Browser flow. First, the different Identity Providers can be retrieved from the TrustBuilder ID SDK. The native flow will start by fetching the allowed IDPs. You can do this by executing getAllowedIDPs.
4.1 GetAllowedIDPs
The getAllowedIDPs method will return a list of TBIdentityProvider. These Identity Providers can be used to authenticate.
This list can be represented visually any way in your application you want.
However, it is important to keep the instance of TBIdentityProvider as we will need it later on to sign the user in.
Usage
// Execute the following to fetch the allowed IDPs
public void getAllowedIDPs(Activity activity){
Future<Result<List<TBStepUp>>> future = tbLoginService.getAllowedIDPs();
Result<List<TBStepUp>> result = future.get();
// Show the list of IDPs
...
}
4.2 Sign in
Once the user of your application has chosen the Identity Provider, that instance can be used to start the sign-in flow.
For this: the authenticateWithIDP
method on the instance of TBService
can be used.
You need to include:
Your Android Activity
The chosen Identity Provider
Your scopes. These are configured in IDHUB and should match.
The instance that implements
ITBServiceCallback
Android will use the on ActivityResult of your Activity to handle the browser result. This result needs to be passed to the SDK.
Then the SDK will fetch the tokens and store these in secure storage.
Once that is finished, authenticateWithBrowser
ITBServiceCallback.onTBServiceResult will be triggered.
This interface (ITBServiceCallback) needs to be implemented in your code.
The following steps are required:
Start the authorize flow with the chosen
TBIdentityProvider
Catch the ActivityResult and pass the result to the SDK using
onAuthenticationResult
ITBServiceCallback
will be triggered with success or an error.
Usage
// Your Android Activity that also implements ITBServiceCallback.
// Execute the following to start the native authorize flow
public void authorize(Activity activity, TBIdentityProvider idp){
List<String> scopes = Arrays.asList("openid", "users:self");
tbLoginService.authenticateWithIDP(activity, idp, scopes, this);
}
// Your Android Activity will capture the result. Pass this to the SDK.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
tbLoginService.onAuthenticationResult(requestCode, data, this);
}
// Result of be send via this callback.
// EResultContext indicates if it's concerning Login or Logout flow.
@Override
public void onTBServiceResult(@NonNull Result<EResultContext> result) {
...
}
4.3 Accessing the token
When later in your application you want to access the token to authorize your api calls with, you can simply use getAndRefreshTokenWhenNecessary
on that same TBLoginService instance.
You are technically not required to use that same instance, but you can create a new one with the same configuration.
This method will check whether the token is at least valid for the time in the given threshold when the instance TBLoginService was created.
When that is not the case, the SDK will try to refresh the access token and return the refreshed one.
Usage
public void getToken(Activity activity){
Future<Result<String>> future = tbLoginService.getTokenAndRefreshWhenNeeded(activity);
Result<String> result = future.get();
}
4.4 User canceled flow
When the user canceled the flow the SDK will return an AuthorizationException with the following properties:
Code: 1
errorDescription: "User canceled flow"
detailMessage: "User canceled flow"
5. TBLoginService - UserInfo
The information that can be retrieved from can also be accessed from the same TBLoginService
instance.
5.1 Get user details
In order to retrieve the details for the currently signed in User, the method getCurrentUser
can be used on the same instance of TBLoginService
.
This method will retrieve the information about the current authorized user and return it in the form of TBUser.
Usage
public void getCurrentUser(Activity activity){
Future<Result<TBUser>> future = tbLoginService.getCurrentUser(activity);
Result<TBUser> user = future.get();
}
5.2 Patch User Details
In order to update some properties of the user, the retrieved TBUser
instance can simply be updated and sent to the SDK with the patchUser
method on the same TBLoginService
instance.
Usage
public void patchUser(Activity activity){
user.familyName = "updated family name"
Future<Result<TBUser>> future = tbLoginService.patchUser(user, activity);
Result<TBUser> result = future.get();
}
6. TBLoginService - Personas
6.1 Get list of personas
In order to retrieve the list of personas for the current signed in user. You can use the getListOfPersonas
method on the instance of TBLoginService.
Behind the scenes, we will automatically use the information of the currently signed in user to retrieve the personas that the user can select.
Usage
public void getListOfPersonas(Activity activity){
Future<Result<List<TBPersona>>> future = tbLoginService.getListOfPersonas(activity);
Result<List<TBPersona>> result = future.get();
}
6.2 Select persona
In order to retrieve a single persona based on a given personaId
you can use the selectPersona
method on the same instance of TBLoginService. Based on the currently authorized user and the given persona
, the detail information of that persona will be retrieved.
Usage
public void selectPersona(TBPersona persona, Activity activity){
Future<Result<TBPersonaInformation>> future = tbLoginService.selectPersona(persona, activity);
Result<TBPersonaInformation> result = future.get();
}
6.3 Patch persona attributes
In order to update the attributes of a specific persona, you can use updatePersonaAttributes.
This method expects the originally retrieved instance of TBPersonaInformation
from selectPersona
with the updated attributes. We need this original instance to correctly update the information. Hence there is also no public constructor available of TBPersonaInformation
.
Usage
public void updatePersonaAttributes(TBPersonaInformation persona, Activity activity) {
for (TBAttribute attribute : persona.attributes.editableAttributes) {
// You can edit the values of an existing attribute
attribute.values = Collections.singletonList("TRUE");
}
// Here we delete every attribute besides the first attribute.
persona.attributes.editableAttributes = Collections.singletonList(persona.attributes.editableAttributes.get(0));
Future<Result<TBPersonaInformation>> future = tbLoginService.updatePersonaAttributes(persona, activity);
Result<TBPersonaInformation> value = future.get();
}
7. TBOnBoardingService
7.1 Start Document Onboarding
This method will execute the following flow:
Start a validation session
Start the document scanner to scan documents and upload said documents
Start the selfie scanner and upload said selfie
Request and return the validation result.
The result will contain a
Validation ID
Indication whether the verification was successful.
Requirements:
In order to start the onboarding flow you need a bearer token of an authenticated user with the correct claims. You can use your instance of TBOnboardingService
to start this flow.
Usage
public void StartOnboarding(){
Future<Result<TBValidationResult>> future = tbOnboardingService.StartOnboarding("BEARER TOKEN");
Result<TBValidationResult> validationResult = future.get();
}
7.2 Session expired
Behind the scenes we will start a validation session that will only be valid for a certain amount of time. If the end-user takes to long to complete the flow, there might be an unsuccessful response with a SessionExpiredException.
8. Response Handling
Most methods returns a Result
object.
This Result
object has the following properties:
Value: The returned value. This can be 'null' if something went wrong.
Exception: An exception in case something went wrong. eg. not signed in, api error,...
isSuccess: Boolean to indicate if the executed method was successful.