PowerAuth Networking SDK for Android
Wultra PowerAuth Networking (WPN) is a high-level SDK built on top of our PowerAuth SDK that enables request signing and encryption.
You can imagine the purpose of this SDK as an HTTP layer (client) that enables request signing and encryption via PowerAuth SDK based on its recommended implementation.
We use this SDK in our other open-source projects that you can take inspiration for example in:
SDK Integration
Requirements
- Android 5.0+ (API level 21+)
- PowerAuth Mobile SDK needs to be implemented in your project
Gradle
To use the SDK in your Android application include the following dependency to your gradle file.
repositories {
mavenCentral() // if not defined elsewhere...
}
implementation "com.wultra.android.powerauth:powerauth-networking:1.x.y"
Open Source Code
The code of the library is open source and you can freely browse it in our GitHub at https://github.com/wultra/networking-android
Creating a Service API Class
Everything you need is packed inside the single com.wultra.android.powerauth.networking.Api
abstract class that provides all the necessary APIs for your networking.
This class takes several parameters:
baseUrl
- Base URL for endpoints. For examplehttps://myservice.com/my-controller/
okHttpClient
- okhttp3 client that will be used for the networking. You can leverage all utilities that are provided by this client like timeout configuration, listeners, etc…powerAuthSDK
-PowerAuthSDK
instance that will sign requestsgsonBuilder
- GsonBuilder for (de)serializationappContext
- Application ContexttokenProvider
- Optional Token Provider in case you have several services and want to share the token logic.userAgent
- Custom user-agent that will be added as an HTTP header to each request.
It is expected that you inherit this class and create your own APIs based on our needs.
Example MyServiceApi that will call 2 sample endpoints (one signed and one signed with token):
class MyServiceApi(
okHttpClient: OkHttpClient,
baseUrl: String,
powerAuthSDK: PowerAuthSDK,
appContext: Context
) : Api(baseUrl, okHttpClient, powerAuthSDK, GsonBuilder(), appContext) {
class SampleRequestData(@SerializedName("uid") val userID: String)
class SampleResponseData(@SerializedName("name") val username: String)
class SampleRequest(requestObject: SampleRequestData): ObjectRequest<SampleRequestData>(requestObject)
class SampleResponse(responseObject: SampleResponseData, status: Status): ObjectResponse<SampleResponseData>(responseObject, status)
companion object {
// This endpoint points to https://my.serviceurl.com/api/auth/token/app/user/sample
private val sampleEndpoint1 = EndpointSigned<SampleRequest, SampleResponse>("api/my/endpoint/user/sample", "/user/get")
// This endpoint points to https://my.serviceurl.com/api/auth/token/app/user/sample2
private val sampleEndpoint2 = EndpointSignedWithToken<SampleRequest, SampleResponse>("api/my/endpoint/user/sample2", "possession_universal")
}
/** Get the username with a token-signed request. */
fun sample1(userID: String, listener: IApiCallResponseListener<SampleResponse>) {
post(SampleRequest(SampleRequestData(userID)), sampleEndpoint1, null, null, null, listener)
}
/** Get the username with a user-signed request. */
fun sample2(userID: String, authentication: PowerAuthAuthentication, listener: IApiCallResponseListener<SampleResponse>) {
post(SampleRequest(SampleRequestData(userID)), sampleEndpoint2, authentication, null, null, null, listener)
}
}
Endpoint Definition
Each endpoint you will target with your project must be defined for the service as an Endpoint
instance. There are several types of endpoints based on the PowerAuth signature that is required.
Signed endpoint EndpointSigned
For endpoints that are signed by PowerAuth signature and can be end-to-end encrypted.
Example:
val mySignedEndpoint = EndpointSigned<MyRequest, MyResponse>("api/my/endpoint/path", "/endpoint/uriId")
// uriId is defined by the endpoint issuer - ask your server developer/provider
Signed endpoint with Token EndpointSignedWithToken
For endpoints that are signed by token by PowerAuth signature and can be end-to-end encrypted.
More info for token-based authentication can be found here
Example:
val myTokenEndpoint = EndpointSignedWithToken<MyRequest, MyResponse>("api/my/endpoint/path", "possession_universal")
// token name (`possession_universal` in this case) is the name of the token as stored in the PowerAuthSDK
// more info can be found in the PowerAuthSDK documentation
// https://github.com/wultra/powerauth-mobile-sdk/blob/develop/docs/PowerAuth-SDK-for-Android.md#token-based-authentication
Basic endpoint (not signed) EndpointBasic
For endpoints that are not signed by PowerAuth signature but can be end-to-end encrypted.
Example:
val myBasicEndpoint = EndpointBasic<MyRequest, MyResponse>("api/my/endpoint/path")
Creating an HTTP request
To create an HTTP request to your endpoint, you need to call the Api.post
method with the following parameters:
data
- with the payload of your requestendpoint
- an endpoint that will be calledauth
-PowerAuthAuthentication
instance that will sign the request- this parameter is missing for the basic and token endpoints
headers
- custom HTTP headers,null
by defaultencryptor
- End to End encryptor in case that the encryption is required,null
by defaultokHttpInterceptor
- OkHttp interceptor to intercept requests eg. for logging purposes,null
by defaultlistener
- result listener
Example:
// Sample Data that will be sent and received from the server
class SampleRequestData(@SerializedName("uid") val userID: String)
class SampleResponseData(@SerializedName("name") val username: String)
// Request objects
class SampleRequest(requestObject: SampleRequestData): ObjectRequest<SampleRequestData>(requestObject)
class SampleResponse(responseObject: SampleResponseData, status: Status): ObjectResponse<SampleResponseData>(responseObject, status)
// endpoint configuration
val myEndpoint = EndpointSigned<SampleRequest, SampleResponse>("api/my/endpoint/path", "/my/endoint/uriId")
// Authentication, for example purposes, expect user PIN 1111
val auth = PowerAuthAuthentication.possessionWithPassword("1111")
// Api.post call
post(
// create request data
SampleRequest(SampleResponseData("12345")),
// specify endpoint
myEndpoint,
// Authenticated with
auth,
// custom HTTP headers
hashMapOf(Pair("MyCustomHeader","Value"))
// encrypt with the application scope. null if not encrypted (usual case)
powerAuthSDK.eciesEncryptorForApplicationScope,
// no HTTP interceptor
null,
// handle response or error
object : IApiCallResponseListener<SampleResponse> {
override fun onFailure(error: ApiError) {
// handle error
}
override fun onSuccess(result: SampleResponse) {
// handle success
}
}
)
Error Handling
Every error produced by this library is of a ApiError
type. This error contains the following information:
error
- A specific reason, why the error happened. For more information see ApiErrorCode chapter.e
- Original exception/error that caused this error. In case of PowerAuth-related errors, it will be by the type ofApiHttpException
orErrorResponseApiException
ApiErrorCode
Each ApiError
has an optional error
property for why the error was created. Such reason can be useful when you’re creating for example a general error handling or reporting, or when you’re debugging the code.
Known common API errors
Option Name | Description |
---|---|
ERROR_GENERIC |
When unexpected error happened |
POWERAUTH_AUTH_FAIL |
General authentication failure (wrong password, wrong activation state, etc…) |
INVALID_REQUEST |
Invalid request sent - missing request object in the request |
INVALID_ACTIVATION |
Activation is not valid (it is different from configured activation) |
INVALID_APPLICATION |
Invalid application identifier is attempted for operation manipulation. |
INVALID_OPERATION |
Invalid operation identifier is attempted for operation manipulation. |
ERR_ACTIVATION |
Error during activation |
ERR_AUTHENTICATION |
Error in case that PowerAuth authentication fails |
ERR_SECURE_VAULT |
Error during secure vault unlocking |
ERR_ENCRYPTION |
Returned in case encryption or decryption fails |
TOO_MANY_REQUESTS |
Too many same requests |
REMOTE_COMMUNICATION_ERROR |
Communication with remote system failed |
Known specific API errors
There are many Wultra-specific codes available, each starting with a service prefix:
OPERATION_
- likeOPERATION_EXPIRED
, when operation approval fails because it expired.PUSH_
- likePUSH_REGISTRATION_FAILED
when push registering fails.ACTIVATION_CODE_
- likeACTIVATION_CODE_FAILED
when failing to retrieve the activation code for the ActivationSpawn library.ONBOARDING_
- for onboarding-related errors.IDENTITY_
for identity-related errors.
Language Configuration
Before using any methods from this SDK that call the backend, a proper language should be set. A properly translated content is served based on this configuration. The property that stores language settings does not persist. You need to set acceptLanguage
every time that the application boots.
Note: Content language capabilities are limited by the implementation of the server - it must support the provided language.
Format
The default value is always en
. With other languages, we use values compliant with standard RFC Accept-Language.
Logging
For logging purposes com.wultra.android.powerauth.networking.Logger
that prints to the console is used.
Verbosity Level
You can limit the amount of logged information via verboseLevel
property.
Level | Description |
---|---|
OFF |
Silences all messages. |
ERROR |
Only errors will be printed into the log. |
WARNING (default) |
Errors and warnings will be printed into the log. |
DEBUG |
All messages will be printed into the log. |