Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update documentation #618

Merged
merged 8 commits into from
Sep 25, 2024
140 changes: 63 additions & 77 deletions docs/PowerAuth-SDK-for-Android.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,42 @@ PowerAuthAppLifecycleListener.getInstance().registerForActivityLifecycleCallback
```


### Additional configuration methods
### Additional configuration

The `PowerAuthConfiguration.Builder` class provides the following additional methods that can alter the configuration:

- `offlineSignatureComponentLength()` - Alters the default component length for the [offline signature](#symmetric-offline-multi-factor-signature). The values between 4 and 8 are allowed. The default value is 8.
- `externalEncryptionKey()` - See [External Encryption Key](#external-encryption-key) chapter for more details.
- `disableAutomaticProtocolUpgrade()` - Disables the automatic protocol upgrade. This option should be used only for debugging purposes.

### HTTP client configuration

The `PowerAuthClientConfiguration.Builder` class contains configuration for a HTTP client used internally by `PowerAuthSDK` class. It has the following configuration properties:

- `timeouts()` - Function specifies connection and read timeout in milliseconds.
- `allowUnsecuredConnection()` - Enables or disables connection to unsecured servers. Do not use this option in the production build of your application.
- `clientValidationStrategy()` - Specifies TLS client validation strategy. See [Working with Invalid SSL Certificates](#working-with-invalid-ssl-certificates) for more details.
- `requestInterceptor()` - Adds a [request interceptor](#request-interceptors) used by the client before the request is executed.
- `userAgent()` - Specifies value for User-Agent HTTP request header. See [Custom User-Agent](#custom-user-agent) chapter for more details.

### Keychain configuration

The `PowerAuthKeychainConfiguration.builder` class contains configuration for a keychain-based storage used by `PowerAuthSDK` class internally. The configuration contains the following properties:
hvge marked this conversation as resolved.
Show resolved Hide resolved

- `linkBiometricItemsToCurrentSet()` - Function specifies whether the item protected with the biometry is invalidated if fingers are added or removed, or if the user re-enrolls for face. See [Biometry Factor-Related Key Lifetime](#biometry-factor-related-key-lifetime) chapter for more details.
- `confirmBiometricAuthentication()` - Function specifies whether the user's confirmation will be required after the successful biometric authentication. See [Biometric Authentication Confirmation](#biometric-authentication-confirmation) chapter for more details.
- `authenticateOnBiometricKeySetup()` - Function specifies whether biometric key setup always require a biometric authentication. See [Enable Biometric Authentication](#enable-biometric-authentication) chapter for more details.
- `enableFallbackToSharedBiometryKey()` - Function specifies whether `PowerAuthSDK` instance should also do additional lookup for a legacy biometric key, previously shared between multiple PowerAuthSDK object instances. The default value is `true` and the fallback is enabled. If your application is using multiple `PowerAuthSDK` instances, then it's recommended to set this option to `false` to avoid use of the shared key between such instances.
- `minimalRequiredKeychainProtection()` - Function specifies minimal required keychain protection level that must be supported on the current device. See [Activation Data Protection](#activation-data-protection) chapter for more details.

The following properties are also available for configuration but are not recommended to be altered under typical circumstances, as changing them may impact the library’s stability or intended behavior:

- `keychainStatusId()` - Function specifies name of the Keychain file used for storing the status information.
- `keychainBiometryId()` - Function specifies name of the Keychain file used for storing the biometry key information.
- `keychainTokenStoreId()` - Function specifies name of the Keychain file used for storing the access tokens.
- `keychainKeyBiometry()` - Function specifies name of the key to the biometry Keychain to store biometry-factor protection key.


### Activation Data Protection

By default, the PowerAuth Mobile SDK for Android encrypts the local activation data with a symmetric key generated by the Android KeyStore on Android 6 and newer devices. On older devices, or if the device has an unreliable KeyStore implementation, then the fallback to unencrypted storage, based on private [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences) is used. If your application requires a higher level of activation data protection, then you can enforce the level of protection in `PowerAuthKeychainConfiguration`:
Expand Down Expand Up @@ -853,36 +881,25 @@ fun validateTypedCharacters(input: String): String? {

To obtain detailed activation status information, use the following code:

<!-- begin codetabs Kotlin Java -->
```kotlin
// Check if there is some activation on the device
if (powerAuthSDK.hasValidActivation()) {
// If there is an activation on the device, check the status with server
powerAuthSDK.fetchActivationStatusWithCallback(context, object: IActivationStatusListener {
override fun onActivationStatusSucceed(status: ActivationStatus) {
// Activation state: State_Created, State_Pending_Commit, State_Active, State_Blocked, State_Removed, State_Deadlock
// Activation states are explained in detail in "Activation states" chapter below
when (status.state) {
ActivationStatus.State_Pending_Commit ->
// Activation is awaiting commit on the server.
Log.i(TAG, "Waiting for commit")
ActivationStatus.State_Active ->
// Activation is valid and active.
Log.i(TAG, "Activation is active")
ActivationStatus.State_Blocked ->
// Activation is blocked. You can display unblock
// instructions to the user.
Log.i(TAG, "Activation is blocked")
ActivationStatus.State_Removed -> {
// Activation is no longer valid on the server.
// You can inform user about this situation and remove
// activation locally.
Log.i(TAG, "Activation is no longer valid")
powerAuthSDK.removeActivationLocal(context)
}
ActivationStatus.State_Deadlock -> {
// Local activation is technically blocked and no longer
// can be used for the signature calculations. You can inform
// user about this situation and remove activation locally.
Log.i(TAG, "Activation is technically blocked")
powerAuthSDK.removeActivationLocal(context)
}
Expand All @@ -907,75 +924,44 @@ if (powerAuthSDK.hasValidActivation()) {
// No activation present on device
}
```
```java
// Check if there is some activation on the device
if (powerAuthSDK.hasValidActivation()) {
// If there is an activation on the device, check the status with server
powerAuthSDK.fetchActivationStatusWithCallback(context, new IActivationStatusListener() {
@Override
public void onActivationStatusSucceed(ActivationStatus status) {
// Activation state: State_Created, State_Pending_Commit, State_Active, State_Blocked, State_Removed, State_Deadlock
switch (status.state) {
case ActivationStatus.State_Pending_Commit:
// Activation is awaiting commit on the server.
android.util.Log.i(TAG, "Waiting for commit");
break;
case ActivationStatus.State_Active:
// Activation is valid and active.
android.util.Log.i(TAG, "Activation is active");
break;
case ActivationStatus.State_Blocked:
// Activation is blocked. You can display unblock
// instructions to the user.
android.util.Log.i(TAG, "Activation is blocked");
break;
case ActivationStatus.State_Removed:
// Activation is no longer valid on the server.
// You can inform user about this situation and remove
// activation locally.
android.util.Log.i(TAG, "Activation is no longer valid");
powerAuthSDK.removeActivationLocal(context);
break;
case ActivationStatus.State_Deadlock:
// Local activation is technically blocked and no longer
// can be used for the signature calculations. You can inform
// user about this situation and remove activation locally.
android.util.Log.i(TAG, "Activation is technically blocked");
powerAuthSDK.removeActivationLocal(context);
break;
case ActivationStatus.State_Created:
// Activation is just created. This is the internal
// state on the server and therefore can be ignored
// on the mobile application.
default:
android.util.Log.i(TAG, "Unknown state");
break;
}

// Failed login attempts, remaining = max - current
int currentFailCount = status.failCount;
int maxAllowedFailCount = status.maxFailCount;
int remainingFailCount = status.getRemainingAttempts();
Note that the status fetch may fail at an unrecoverable error `PowerAuthErrorCodes.PROTOCOL_UPGRADE`, meaning that it's not possible to upgrade the PowerAuth protocol to a newer version. In this case, it's recommended to [remove the activation locally](#activation-removal).

if (status.getCustomObject() != null) {
// Custom object contains any proprietary server specific data
}
}
### Activation states

@Override
public void onActivationStatusFailed(Throwable t) {
// Network error occurred, report it to the user
}
});
} else {
// No activation present on device
}
```
<!-- end -->
This chapter explains activation states in detail. To get more information about activation lifecycle, check the [Activation States](https://github.com/wultra/powerauth-crypto/blob/develop/docs/Activation.md#activation-states) chapter available in our [powerauth-crypto](https://github.com/wultra/powerauth-crypto) repository.

Note that the status fetch may fail at an unrecoverable error `PowerAuthErrorCodes.PROTOCOL_UPGRADE`, meaning that it's not possible to upgrade the PowerAuth protocol to a newer version. In this case, it's recommended to [remove the activation locally](#activation-removal).
#### `ActivationStatus.State_Created`

The activation record is created using an external channel, such as the Internet banking, but the key exchange between the client and server did not happen yet. This state is never reported to the mobile client.

#### `ActivationStatus.State_Pending_Commit`

The activation record is created and key exchange between the client and server already took place, but the activation record needs additional approval before it can be used.
hvge marked this conversation as resolved.
Show resolved Hide resolved

#### `ActivationStatus.State_Active`

The activation record is created and active. It is ready to be used for typical use-cases, such as generating signatures.

#### `ActivationStatus.State_Blocked`

The activation record is blocked and cannot be used for most of the use-cases, such as generating signatures. It can be unblocked and activated again.
hvge marked this conversation as resolved.
Show resolved Hide resolved

#### `ActivationStatus.State_Removed`

The activation record is removed and permanently blocked. It cannot be used for generating signatures or ever unblocked. You can inform user about this situation and remove the activation locally.

#### `ActivationStatus.State_Deadlock`

The local activation is technically blocked and can no longer be used for signature calculations. You can inform the user about this situation and remove the activation locally.

The reason why the mobile client is no longer capable of calculating valid signatures is that the logical counter is out of sync between the client and the server. This may happen only if the mobile client calculates too many PowerAuth signatures without subsequent validation on the server. For example:

- If your application repeatedly constructs HTTP requests with a PowerAuth signature while the network is unreachable.
- If your application repeatedly creates authentication tokens while the network is unreachable. For example, when trying to register for push notifications in the background, without user interaction.
- If you calculate too many offline signatures without subsequent validation.

To get more information about activation lifecycle, check the [Activation States](https://github.com/wultra/powerauth-crypto/blob/develop/docs/Activation.md#activation-states) chapter available in our [powerauth-crypto](https://github.com/wultra/powerauth-crypto) repository.
In rare situations, this may also happen in development or testing environments, where you’re able to restore the state of the activation on the server from a snapshot.

## Data Signing

Expand Down
21 changes: 14 additions & 7 deletions docs/PowerAuth-SDK-for-iOS-Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<!-- begin remove -->
## Table of Contents

- [Introduction](#introduction)
- [Installation](#installation)
- [CocoaPods Installation](#cocoapods)
- [Manual Installation](#manual)
Expand All @@ -24,6 +25,15 @@ Related documents:
- [PowerAuth SDK for watchOS](./PowerAuth-SDK-for-watchOS.md)
<!-- end -->

## Introduction

The PowerAuth Mobile SDK Extensions library is a lightweight counterpart to the full-featured PowerAuth Mobile SDK, providing limited functionality, such as:

- Retrieving information about activation presence
- Obtaining authentication tokens

If you need to perform more operations in your extension, such as calculating [PowerAuth symmetric signatures](./PowerAuth-SDK-for-iOS.md#symmetric-multi-factor-signature), you can use the full-featured [PowerAuth mobile SDK](./PowerAuth-SDK-for-iOS.md). This can be achieved by configuring [activation data sharing](./PowerAuth-SDK-for-iOS.md#share-activation-data) in both your application and the extension.

## Installation

This chapter describes how to get PowerAuth SDK for iOS and tvOS Extensions up and running in your app. In the current version, you can choose between CocoaPods and manual library integration. Both types of installation will lead to your app extension linked with a dynamic library, provided by the `PowerAuth2ForExtensions.[xc]framework`.
Expand Down Expand Up @@ -146,13 +156,10 @@ class TodayViewController: UIViewController, NCWidgetProviding {
}()

private static func setupPowerAuth() -> PowerAuthExtensionSDK {
let config = PowerAuthConfiguration()
config.instanceId = "your-app-bundle-name";
config.appKey = "sbG8gd...MTIzNA=="
config.appSecret = "aGVsbG...MTIzNA=="
config.masterServerPublicKey = "MTIzNDU2Nz...jc4OTAxMg=="
// URL is optional, the current version of Extensions SDK doesn't perform its own networking.
config.baseEndpointUrl = "https://localhost:8080/demo-server"
let config = PowerAuthConfiguration(
instanceId: Bundle.main.bundleIdentifier!,
baseEndpointUrl: "https://localhost:8080/demo-server",
configuration: "ARDDj6EB6iAUtNm...KKEcBxbnH9bMk8Ju3K1wmjbA==")

let keychainConfig = PowerAuthKeychainConfiguration.sharedInstance()
keychainConfig.keychainAttribute_AccessGroup = "KEYCHAIN_GROUP_IDENTIFIER"
Expand Down
Loading
Loading