diff --git a/docs/Migration-from-1.8-to-1.9.md b/docs/Migration-from-1.8-to-1.9.md index bd082cfe..249cc57c 100644 --- a/docs/Migration-from-1.8-to-1.9.md +++ b/docs/Migration-from-1.8-to-1.9.md @@ -6,6 +6,7 @@ PowerAuth Mobile SDK in version `1.9.0` provides the following improvements: - The PowerAuth protocol is no longer use EC key-pairs for encryption and signature calculation (dual use problem.) - The End-To-End encryption is now using a temporary keys to improve the forward secrecy of our ECIES scheme. - Simplified construction of encrypted request and response. Check updated [Android](PowerAuth-SDK-for-Android.md#end-to-end-encryption) or [iOS](PowerAuth-SDK-for-iOS.md#end-to-end-encryption) documentation for more details. +- Now it's possible to create an activation via OpenID Connect provider. ### Compatibility with PowerAuth Server diff --git a/docs/PowerAuth-SDK-for-Android.md b/docs/PowerAuth-SDK-for-Android.md index 42d283ac..2394e37f 100644 --- a/docs/PowerAuth-SDK-for-Android.md +++ b/docs/PowerAuth-SDK-for-Android.md @@ -7,6 +7,7 @@ - [SDK Configuration](#configuration) - [Device Activation](#activation) - [Activation via Activation Code](#activation-via-activation-code) + - [Activation via OpenID Connect](#activation-via-openid-connect) - [Activation via Custom Credentials](#activation-via-custom-credentials) - [Activation via Recovery Code](#activation-via-recovery-code) - [Customize Activation](#customize-activation) @@ -347,6 +348,45 @@ try { Be aware that OTP can be used only if the activation is configured for ON_KEY_EXCHANGE validation on the PowerAuth server. See our [crypto documentation for details](https://github.com/wultra/powerauth-crypto/blob/develop/docs/Additional-Activation-OTP.md#regular-activation-with-otp). +### Activation via OpenID Connect + +You may also create an activation using OIDC protocol: + +```kotlin +// Create a new activation with a given device name and login credentials +val deviceName = "Juraj's JiaYu S3" +// Get the following information from your OpenID provider +val providerId = "1234567890abcdef" +val code = "1234567890abcdef" +val nonce = "K1mP3rT9bQ8lV6zN7sW2xY4dJ5oU0fA1gH29o" +val codeVerifier = "G3hsI1KZX1o~K0p-5lT3F7yZ4...6yP8rE2wO9n" // code verifier is optional + +// Create an activation object with the given credentials. +val activation: PowerAuthActivation +try { + activation = PowerAuthActivation.Builder.oidcActivation(providerId, code, nonce, codeVerifier) + .setActivationName(deviceName) + .build() +} catch (e: PowerAuthErrorException) { + // Credentials dictionary is empty +} + +// Create a new activation with the given activation object +powerAuthSDK.createActivation(activation, object: ICreateActivationListener { + override fun onActivationCreateSucceed(result: CreateActivationResult) { + val fingerprint = result.activationFingerprint + val activationRecovery = result.recoveryData + // No error occurred, proceed to credentials entry (PIN prompt, Enable "Biometric Authentication" switch, ...) and persist + // The 'fingerprint' value represents the combination of device and server public keys - it may be used as visual confirmation + // If the server supports recovery codes for activation, then `activationRecovery` contains object with information about activation recovery. + } + + override fun onActivationCreateFailed(t: Throwable) { + // Error occurred, report it to the user + } +}) +``` + ### Activation via Custom Credentials You may also create an activation using any custom login data - it can be anything that the server can use to obtain the user ID to associate with a new activation. Since the credentials are custom, the server's implementation must be able to process such a request. Unlike the previous versions of SDK, the custom activation no longer requires a custom activation endpoint. diff --git a/docs/PowerAuth-SDK-for-iOS.md b/docs/PowerAuth-SDK-for-iOS.md index 06df8556..5d6a9c27 100644 --- a/docs/PowerAuth-SDK-for-iOS.md +++ b/docs/PowerAuth-SDK-for-iOS.md @@ -13,6 +13,7 @@ - [SDK Configuration](#configuration) - [Device Activation](#activation) - [Activation via Activation Code](#activation-via-activation-code) + - [Activation via OpenID Connect](#activation-via-openid-connect) - [Activation via Custom Credentials](#activation-via-custom-credentials) - [Activation via Recovery Code](#activation-via-recovery-code) - [Customize Activation](#customize-activation) @@ -234,6 +235,30 @@ guard let activation = try? PowerAuthActivation(activationCode: activationCode, Be aware that OTP can be used only if the activation is configured for ON_KEY_EXCHANGE validation on the PowerAuth server. See our [crypto documentation for details](https://github.com/wultra/powerauth-crypto/blob/develop/docs/Additional-Activation-OTP.md#regular-activation-with-otp). +### Activation via OpenID Connect + +You may also create an activation using OIDC protocol: + +```swift +// Create a new activation with a given device name and custom login credentials +let deviceName = "Petr's iPhone 7" // or UIDevice.current.name (see warning below) +// Get the following information from your OpenID provider +let providerId = "1234567890abcdef" +let code = "1234567890abcdef" +let nonce = "K1mP3rT9bQ8lV6zN7sW2xY4dJ5oU0fA1gH29o" +let codeVerifier = "G3hsI1KZX1o~K0p-5lT3F7yZ4...6yP8rE2wO9n" // code verifier is optional + +// create an activation object with the given OIDC parameters +guard let activation = try? PowerAuthActivation(oidcProviderId: providerId, code: code, nonce: nonce, codeVerifier: codeVerifier) + .with(activationName: deviceName) else { + // Activation parameter contains empty string +} +``` + + +Note that if you use `UIDevice.current.name` for a device’s name, your application must include an [appropriate entitlement](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_device-information_user-assigned-device-name); otherwise, the operating system will provide a generic `iPhone` string. + + ### Activation via Custom Credentials You may also create an activation using any custom login data - it can be anything that the server can use to obtain the user ID to associate with a new activation. Since the credentials are custom, the server's implementation must be able to process such a request. Unlike the previous versions of SDK, the custom activation no longer requires a custom activation endpoint. diff --git a/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/sdk/PowerAuthActivationBuilderTest.java b/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/sdk/PowerAuthActivationBuilderTest.java index c95ad825..b0d33fb7 100644 --- a/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/sdk/PowerAuthActivationBuilderTest.java +++ b/proj-android/PowerAuthLibrary/src/androidTest/java/io/getlime/security/powerauth/sdk/PowerAuthActivationBuilderTest.java @@ -86,7 +86,8 @@ public void createStandardActivationWithExtras() throws Exception { additionalAttributes.put("test", "value"); additionalAttributes.put("zero", 0); - PowerAuthActivation activation = PowerAuthActivation.Builder.activation("W65WE-3T7VI-7FBS2-A4OYA", "Named activation") + PowerAuthActivation activation = PowerAuthActivation.Builder.activation("W65WE-3T7VI-7FBS2-A4OYA") + .setActivationName("Named activation") .setExtras("extras") .setCustomAttributes(additionalAttributes) .build(); @@ -123,15 +124,85 @@ public void createStandardActivationWithOtp() throws Exception { @Test(expected = PowerAuthErrorException.class) public void createStandardActivationWithInvalidCode() throws Exception { - PowerAuthActivation.Builder.activation("W65WE-3T7VI-7FBS2-A4OYB", null) + PowerAuthActivation.Builder.activation("W65WE-3T7VI-7FBS2-A4OYB") .build(); } + // OIDC + + @Test + public void createOidcActivation() throws Exception { + final String providerId = "abc123"; + final String code = "ABCDEFGH"; + final String nonce = "K1mP3rT9bQ8lV6zN7sW2xY4dJ5oU0fA1gH29o"; + final String codeVerifier = "G3hsI1KZX1o~K0p-5lT3F7yZ4bC8dE2jX9aQ6nO2rP3uS7wT5mV8jW1oY6xB3sD09tR4vU3qM1nG7kL6hV5wY2pJ0aF3eK9dQ8xN4mS2zB7oU5tL1cJ3vX6yP8rE2wO9n"; + PowerAuthActivation activation = PowerAuthActivation.Builder.oidcActivation(providerId, code, nonce, null) + .build(); + + assertNotNull(activation); + assertEquals(ActivationType.DIRECT, activation.activationType); + assertNotNull(activation.identityAttributes); + assertEquals("oidc", activation.identityAttributes.get("method")); + assertEquals(providerId, activation.identityAttributes.get("providerId")); + assertEquals(code, activation.identityAttributes.get("code")); + assertEquals(nonce, activation.identityAttributes.get("nonce")); + assertNull(activation.identityAttributes.get("codeVerifier")); + assertNull(activation.activationName); + + activation = PowerAuthActivation.Builder.oidcActivation(providerId, code, nonce, codeVerifier) + .build(); + + assertNotNull(activation); + assertEquals(ActivationType.DIRECT, activation.activationType); + assertNotNull(activation.identityAttributes); + assertEquals("oidc", activation.identityAttributes.get("method")); + assertEquals(providerId, activation.identityAttributes.get("providerId")); + assertEquals(code, activation.identityAttributes.get("code")); + assertEquals(nonce, activation.identityAttributes.get("nonce")); + assertEquals(codeVerifier, activation.identityAttributes.get("codeVerifier")); + assertNull(activation.activationName); + } + + @Test + public void createOidcActivationWithName() throws Exception { + final String providerId = "abc123"; + final String code = "ABCDEFGH"; + final String nonce = "K1mP3rT9bQ8lV6zN7sW2xY4dJ5oU0fA1gH29o"; + final String codeVerifier = "G3hsI1KZX1o~K0p-5lT3F7yZ4bC8dE2jX9aQ6nO2rP3uS7wT5mV8jW1oY6xB3sD09tR4vU3qM1nG7kL6hV5wY2pJ0aF3eK9dQ8xN4mS2zB7oU5tL1cJ3vX6yP8rE2wO9n"; + PowerAuthActivation activation = PowerAuthActivation.Builder.oidcActivation(providerId, code, nonce, null) + .setActivationName("OIDC Activation") + .build(); + + assertNotNull(activation); + assertEquals(ActivationType.DIRECT, activation.activationType); + assertNotNull(activation.identityAttributes); + assertEquals("oidc", activation.identityAttributes.get("method")); + assertEquals(providerId, activation.identityAttributes.get("providerId")); + assertEquals(code, activation.identityAttributes.get("code")); + assertEquals(nonce, activation.identityAttributes.get("nonce")); + assertNull(activation.identityAttributes.get("codeVerifier")); + assertEquals("OIDC Activation", activation.activationName); + + activation = PowerAuthActivation.Builder.oidcActivation(providerId, code, nonce, codeVerifier) + .setActivationName("OIDC Activation") + .build(); + + assertNotNull(activation); + assertEquals(ActivationType.DIRECT, activation.activationType); + assertNotNull(activation.identityAttributes); + assertEquals("oidc", activation.identityAttributes.get("method")); + assertEquals(providerId, activation.identityAttributes.get("providerId")); + assertEquals(code, activation.identityAttributes.get("code")); + assertEquals(nonce, activation.identityAttributes.get("nonce")); + assertEquals(codeVerifier, activation.identityAttributes.get("codeVerifier")); + assertEquals("OIDC Activation", activation.activationName); + } + // Recovery activations @Test public void createRecoveryActivation() throws Exception { - PowerAuthActivation activation = PowerAuthActivation.Builder.recoveryActivation("W65WE-3T7VI-7FBS2-A4OYA", "1234567890", null) + PowerAuthActivation activation = PowerAuthActivation.Builder.recoveryActivation("W65WE-3T7VI-7FBS2-A4OYA", "1234567890") .build(); assertNotNull(activation); @@ -144,7 +215,7 @@ public void createRecoveryActivation() throws Exception { @Test public void createRecoveryActivationFromQrCode() throws Exception { - PowerAuthActivation activation = PowerAuthActivation.Builder.recoveryActivation("R:W65WE-3T7VI-7FBS2-A4OYA", "1234567890", null) + PowerAuthActivation activation = PowerAuthActivation.Builder.recoveryActivation("R:W65WE-3T7VI-7FBS2-A4OYA", "1234567890") .build(); assertNotNull(activation); @@ -157,7 +228,8 @@ public void createRecoveryActivationFromQrCode() throws Exception { @Test public void createRecoveryActivationWithName() throws Exception { - PowerAuthActivation activation = PowerAuthActivation.Builder.recoveryActivation("W65WE-3T7VI-7FBS2-A4OYA", "1234567890", "Recovery") + PowerAuthActivation activation = PowerAuthActivation.Builder.recoveryActivation("W65WE-3T7VI-7FBS2-A4OYA", "1234567890") + .setActivationName("Recovery") .build(); assertNotNull(activation); @@ -193,20 +265,21 @@ public void createRecoveryActivationWithExtras() throws Exception { @Test(expected = PowerAuthErrorException.class) public void createRecoveryActivationWithOtp() throws Exception { - PowerAuthActivation.Builder.recoveryActivation("W65WE-3T7VI-7FBS2-A4OYA", "1234567890", "Recovery") + PowerAuthActivation.Builder.recoveryActivation("W65WE-3T7VI-7FBS2-A4OYA", "1234567890") + .setActivationName("Recovery") .setAdditionalActivationOtp("1234") .build(); } @Test(expected = PowerAuthErrorException.class) public void createRecoveryActivationWithInvalidCode() throws Exception { - PowerAuthActivation.Builder.recoveryActivation("W65WE-3T7VI-7FBS2-A4OYB", "1234567890", null) + PowerAuthActivation.Builder.recoveryActivation("W65WE-3T7VI-7FBS2-A4OYB", "1234567890") .build(); } @Test(expected = PowerAuthErrorException.class) public void createRecoveryActivationWithInvalidPuk() throws Exception { - PowerAuthActivation.Builder.recoveryActivation("W65WE-3T7VI-7FBS2-A4OYA", "123456789", null) + PowerAuthActivation.Builder.recoveryActivation("W65WE-3T7VI-7FBS2-A4OYA", "123456789") .build(); } @@ -218,7 +291,7 @@ public void createCustomActivation() throws Exception { identityAttributes.put("login", "juraj"); identityAttributes.put("password", "nbusr123"); - PowerAuthActivation activation = PowerAuthActivation.Builder.customActivation(identityAttributes, null) + PowerAuthActivation activation = PowerAuthActivation.Builder.customActivation(identityAttributes) .build(); assertNotNull(activation); @@ -236,7 +309,8 @@ public void createCustomActivationWithName() throws Exception { identityAttributes.put("login", "juraj"); identityAttributes.put("password", "nbusr123"); - PowerAuthActivation activation = PowerAuthActivation.Builder.customActivation(identityAttributes, "CustomActivation") + PowerAuthActivation activation = PowerAuthActivation.Builder.customActivation(identityAttributes) + .setActivationName("CustomActivation") .build(); assertNotNull(activation); diff --git a/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/networking/model/entity/ActivationType.java b/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/networking/model/entity/ActivationType.java index 008faca9..2db45861 100644 --- a/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/networking/model/entity/ActivationType.java +++ b/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/networking/model/entity/ActivationType.java @@ -22,6 +22,7 @@ */ public enum ActivationType { CODE, + DIRECT, CUSTOM, RECOVERY } diff --git a/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/sdk/PowerAuthActivation.java b/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/sdk/PowerAuthActivation.java index b541770b..1180398d 100644 --- a/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/sdk/PowerAuthActivation.java +++ b/proj-android/PowerAuthLibrary/src/main/java/io/getlime/security/powerauth/sdk/PowerAuthActivation.java @@ -16,6 +16,7 @@ package io.getlime.security.powerauth.sdk; +import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -76,9 +77,9 @@ public static class Builder { private final @NonNull ActivationType activationType; private final @NonNull Map identityAttributes; - private final @Nullable String activationName; private final @Nullable ActivationCode activationCode; + private @Nullable String activationName; private @Nullable String extras; private @Nullable Map customAttributes; private @Nullable String additionalActivationOtp; @@ -106,6 +107,69 @@ private Builder(@NonNull ActivationType activationType, * The activation code may contain an optional signature part, in case that it is scanned * from QR code. * + * @param activationCode Activation code, obtained either via QR code scanning or by manual entry. + * @return {@link Builder} instance. + * @throws PowerAuthErrorException In case that activation code is invalid. + */ + public static @NonNull Builder activation(@NonNull String activationCode) throws PowerAuthErrorException { + return activation(activationCode, null); + } + + /** + * Construct a {@link Builder} object for an activation via OpenID connect provider. + * + * @param providerId OAuth 2.0 provider identification. + * @param code OAuth 2.0 authorization code. + * @param nonce Nonce used in the OAuth 2.0 flow. + * @param codeVerifier Optional code verifier, in case that PKCE extension is used for an activation. + * @return {@link Builder} instance. + * @throws PowerAuthErrorException In case that some parameter contains an empty string. + */ + public static @NonNull Builder oidcActivation(@NonNull String providerId, @NonNull String code, @NonNull String nonce, @Nullable String codeVerifier) throws PowerAuthErrorException { + if (TextUtils.isEmpty(providerId) || TextUtils.isEmpty(code) || TextUtils.isEmpty(nonce) || (codeVerifier != null && TextUtils.isEmpty(codeVerifier))) { + throw new PowerAuthErrorException(PowerAuthErrorCodes.INVALID_ACTIVATION_DATA, "Empty parameter provided"); + } + final Map identityAttributes = new HashMap<>(5); + identityAttributes.put("method", "oidc"); + identityAttributes.put("providerId", providerId); + identityAttributes.put("code", code); + identityAttributes.put("nonce", nonce); + if (codeVerifier != null) { + identityAttributes.put("codeVerifier", codeVerifier); + } + return new Builder(ActivationType.DIRECT, identityAttributes, null, null); + } + + /** + * Construct a {@link Builder} object with an identity attributes for the custom activation purposes. + * + * @param identityAttributes Custom activation parameters that are used to prove identity of a user. + * @return {@link Builder} instance. + * @throws PowerAuthErrorException In case that identity attributes map is empty. + */ + public static @NonNull Builder customActivation(@NonNull Map identityAttributes) throws PowerAuthErrorException { + return customActivation(identityAttributes, null); + } + + /** + * Construct a {@link Builder} object with recovery activation code and PUK. + * + * @param recoveryCode Recovery code, obtained either via QR code scanning or by manual entry. + * @param puk PUK obtained by manual entry. + * @return {@link Builder} instance. + * @throws PowerAuthErrorException In case that recovery code or PUK is invalid. + */ + public static @NonNull Builder recoveryActivation(@NonNull String recoveryCode, @NonNull String puk) throws PowerAuthErrorException { + return recoveryActivation(recoveryCode, puk, null); + } + + // Obsolete methods (will be deprecated in some future version) + + /** + * Construct a {@link Builder} object for a regular activation with activation code. + * The activation code may contain an optional signature part, in case that it is scanned + * from QR code. + *

* The activation's name parameter is optional, but recommended to set. You can use the value obtained from * {@code Settings.System.getString(getContentResolver(), "device_name")} or let the user set the name. * The name of activation will be associated with an activation record on PowerAuth Server. @@ -127,7 +191,7 @@ private Builder(@NonNull ActivationType activationType, /** * Construct a {@link Builder} object with an identity attributes for the custom activation purposes. - * + *

* The activation's name parameter is optional, but recommended to set. You can use the value obtained from * {@code Settings.System.getString(getContentResolver(), "device_name")} or let the user set the name. * The name of activation will be associated with an activation record on PowerAuth Server. @@ -146,7 +210,7 @@ private Builder(@NonNull ActivationType activationType, /** * Construct a {@link Builder} object with recovery activation code and PUK. - * + *

* The activation's name parameter is optional, but recommended to set. You can use the value obtained from * {@code Settings.System.getString(getContentResolver(), "device_name")} or let the user set the name. * The name of activation will be associated with an activation record on PowerAuth Server. @@ -171,9 +235,24 @@ private Builder(@NonNull ActivationType activationType, return new Builder(ActivationType.RECOVERY, identityAttributes, activationName, null); } + // Activation object customization + + /** + * Set activation's name. The activation's name parameter is optional, but recommended to set. You can use the + * value obtained from {@code Settings.System.getString(getContentResolver(), "device_name")} or let the user + * set the name. The name of activation will be associated with an activation record on PowerAuth Server. + * + * @param activationName Name of the activation. + * @return This value will never be {@code null}. + */ + public @NonNull Builder setActivationName(@NonNull String activationName) { + this.activationName = activationName; + return this; + } + /** * Set extra attributes of the activation, used for application specific purposes (for example, info about the client - * device or system). This extras string will be associated with the activation record on PowerAuth Server. + * device or system). The extras string will be associated with the activation record on PowerAuth Server. * * @param extras String with extra attributes * @return This value will never be {@code null}. diff --git a/proj-xcode/PowerAuth2/PowerAuthActivation.h b/proj-xcode/PowerAuth2/PowerAuthActivation.h index 8f946a42..2b402aa3 100644 --- a/proj-xcode/PowerAuth2/PowerAuthActivation.h +++ b/proj-xcode/PowerAuth2/PowerAuthActivation.h @@ -30,36 +30,54 @@ /** Create an instance of `PowerAuthActivation` configured with the activation code. The activation code may contain an optional signature part, in case that it is scanned from QR code. - - The activation's `name` parameter is optional, but recommended to set. You can use the value obtained from - `UIDevice.current.name` or let the user set the name. The name of activation will be associated with - an activation record on PowerAuth Server. - + @param activationCode Activation code, obtained either via QR code scanning or by manual entry. - @param name Activation name to be used for the activation. @param error Error reference in case some error occurs. @return New instance of `PowerAuthActivation` or `nil` in case that activation code is invalid. */ + (nullable instancetype) activationWithActivationCode:(nonnull NSString*)activationCode - name:(nullable NSString*)name error:(NSError * _Nullable * _Nullable)error; /** Creates an instance of `PowerAuthActivation` with an identity attributes for the custom activation purposes. - - The activation's `name` parameter is optional, but recommended to set. You can use the value obtained from - `UIDevice.current.name` or let the user set the name. The name of activation will be associated with - an activation record on PowerAuth Server. - + @param identityAttributes Custom activation parameters that are used to prove identity of a user. - @param name Activation name to be used for the activation. @param error Error reference in case some error occurs. @return New instance of `PowerAuthActivation` or `nil` in case that identity attributes are empty. */ + (nullable instancetype) activationWithIdentityAttributes:(nonnull NSDictionary*)identityAttributes - name:(nullable NSString*)name error:(NSError * _Nullable * _Nullable)error; +/** + Creates an instance of `PowerAuthActivation` with a recovery activation code and PUK. + + @param recoveryCode Recovery code, obtained either via QR code scanning or by manual entry. + @param recoveryPuk PUK obtained by manual entry. + @param error Error reference in case some error occurs. + @return New instance of `PowerAuthActivation` or `nil` in case that recovery code, or recovery PUK is invalid. + */ ++ (nullable instancetype) activationWithRecoveryCode:(nonnull NSString*)recoveryCode + recoveryPuk:(nonnull NSString*)recoveryPuk + error:(NSError * _Nullable * _Nullable)error; + +/** + Creates an instance of `PowerAuthActivation` with OpenID connect credentials. + + @param providerId OAuth 2.0 provider identification. + @param code OAuth 2.0 authorization code. + @param nonce Nonce used in the OAuth 2.0 flow. + @param codeVerifier Optional code verifier, in case that PKCE extension is used for an activation. + @param error Error reference in case some error occurs. + @return New instance of `PowerAuthActivation` or `nil` in case that some parameter contains empty string. + */ ++ (nullable instancetype) activationWithOidcProviderId:(nonnull NSString*)providerId + code:(nonnull NSString*)code + nonce:(nonnull NSString*)nonce + codeVerifier:(nullable NSString*)codeVerifier + error:(NSError * _Nullable * _Nullable)error; + +#pragma mark - Obsolete methods (will be deprecated in future version) + /** Creates an instance of `PowerAuthActivation` with a recovery activation code and PUK. @@ -77,10 +95,53 @@ recoveryPuk:(nonnull NSString*)recoveryPuk name:(nullable NSString*)name error:(NSError * _Nullable * _Nullable)error; +/** + Create an instance of `PowerAuthActivation` configured with the activation code. The activation code may contain + an optional signature part, in case that it is scanned from QR code. + + The activation's `name` parameter is optional, but recommended to set. You can use the value obtained from + `UIDevice.current.name` or let the user set the name. The name of activation will be associated with + an activation record on PowerAuth Server. + + @param activationCode Activation code, obtained either via QR code scanning or by manual entry. + @param name Activation name to be used for the activation. + @param error Error reference in case some error occurs. + @return New instance of `PowerAuthActivation` or `nil` in case that activation code is invalid. + */ ++ (nullable instancetype) activationWithActivationCode:(nonnull NSString*)activationCode + name:(nullable NSString*)name + error:(NSError * _Nullable * _Nullable)error; + +/** + Creates an instance of `PowerAuthActivation` with an identity attributes for the custom activation purposes. + + The activation's `name` parameter is optional, but recommended to set. You can use the value obtained from + `UIDevice.current.name` or let the user set the name. The name of activation will be associated with + an activation record on PowerAuth Server. + + @param identityAttributes Custom activation parameters that are used to prove identity of a user. + @param name Activation name to be used for the activation. + @param error Error reference in case some error occurs. + @return New instance of `PowerAuthActivation` or `nil` in case that identity attributes are empty. + */ ++ (nullable instancetype) activationWithIdentityAttributes:(nonnull NSDictionary*)identityAttributes + name:(nullable NSString*)name + error:(NSError * _Nullable * _Nullable)error; #pragma mark - Activation customization +/** + Sets activation name. The activation's name parameter is optional, but recommended to set. You can use the value obtained from + `UIDevice.current.name` or let the user set the name. The name of activation will be associated with + an activation record on PowerAuth Server. + + @param activationName Name of activation. + @return The same object instance. + */ +- (nonnull instancetype) withActivationName:(nonnull NSString*)activationName + NS_SWIFT_NAME(with(activationName:)); + /** Sets extra attributes of the activation, used for application specific purposes (for example, info about the client device or system). This extras string will be associated with the activation record on PowerAuth Server. diff --git a/proj-xcode/PowerAuth2/PowerAuthActivation.m b/proj-xcode/PowerAuth2/PowerAuthActivation.m index df1c678a..8fd49158 100644 --- a/proj-xcode/PowerAuth2/PowerAuthActivation.m +++ b/proj-xcode/PowerAuth2/PowerAuthActivation.m @@ -60,6 +60,12 @@ - (id) copyWithZone:(NSZone *)zone #pragma mark - Static initializers ++ (instancetype) activationWithActivationCode:(NSString*)activationCode + error:(NSError**)error +{ + return [self activationWithActivationCode:activationCode name:nil error:error]; +} + + (instancetype) activationWithActivationCode:(NSString*)activationCode name:(NSString*)name error:(NSError**)error @@ -78,6 +84,12 @@ + (instancetype) activationWithActivationCode:(NSString*)activationCode name:name]; } ++ (instancetype) activationWithIdentityAttributes:(NSDictionary*)identityAttributes + error:(NSError**)error +{ + return [self activationWithIdentityAttributes:identityAttributes name:nil error:error]; +} + + (instancetype) activationWithIdentityAttributes:(NSDictionary*)identityAttributes name:(NSString*)name error:(NSError**)error @@ -94,6 +106,13 @@ + (instancetype) activationWithIdentityAttributes:(NSDictionary