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

Using PowerAuthSDK 1.9.0+ #65

Merged
merged 8 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ on:
jobs:
build:
name: Build
runs-on: macos-13
runs-on: macos-14
steps:
- name: Checkout the repo
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Set proper xcode version
run: sh ./scripts/xcodeselect.sh
- name: Building
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ on:
jobs:
swift:
name: Swift Lint
runs-on: macos-13
runs-on: macos-14
steps:
- name: Checkout the repo
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Lint
run: swiftlint --strict
run: ./scripts/swiftlint.sh
40 changes: 0 additions & 40 deletions .github/workflows/publish.yml

This file was deleted.

4 changes: 2 additions & 2 deletions Cartfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
binary "https://raw.githubusercontent.com/wultra/powerauth-mobile-sdk-spm/1.8.0/PowerAuth2.json"
binary "https://raw.githubusercontent.com/wultra/powerauth-mobile-sdk-spm/1.8.0/PowerAuthCore.json"
binary "https://raw.githubusercontent.com/wultra/powerauth-mobile-sdk-spm/1.9.0/PowerAuth2.json"
binary "https://raw.githubusercontent.com/wultra/powerauth-mobile-sdk-spm/1.9.0/PowerAuthCore.json"
4 changes: 2 additions & 2 deletions Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
binary "https://raw.githubusercontent.com/wultra/powerauth-mobile-sdk-spm/1.8.0/PowerAuth2.json" "1.8.0"
binary "https://raw.githubusercontent.com/wultra/powerauth-mobile-sdk-spm/1.8.0/PowerAuthCore.json" "1.8.0"
binary "https://raw.githubusercontent.com/wultra/powerauth-mobile-sdk-spm/1.9.0/PowerAuth2.json" "1.9.0"
binary "https://raw.githubusercontent.com/wultra/powerauth-mobile-sdk-spm/1.9.0/PowerAuthCore.json" "1.9.0"
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let package = Package(
targets: ["WultraPowerAuthNetworking"])
],
dependencies: [
.package(url: "https://github.com/wultra/powerauth-mobile-sdk-spm.git", .upToNextMinor(from: "1.8.0"))
.package(url: "https://github.com/wultra/powerauth-mobile-sdk-spm.git", .upToNextMinor(from: "1.9.0"))
],
targets: [
.target(
Expand Down
44 changes: 32 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,12 @@ pod 'WultraPowerAuthNetworking'

### Guaranteed PowerAuth Compatibility

| WPN SDK | PowerAuth SDK |
|---|---|
| `1.0.x` - `1.2.x` | `1.7.x` |
| `1.3.x` | `1.8.x` |
| `1.4.x` | `1.8.x` |
| WPN SDK | PowerAuth SDK |
|-------------------|---------------|
| `1.5.x` | `1.9.x` |
| `1.4.x` | `1.8.x` |
| `1.3.x` | `1.8.x` |
| `1.0.x` - `1.2.x` | `1.7.x` |

### Xcode Compatibility

Expand Down Expand Up @@ -125,6 +126,28 @@ let networking = WPNNetworkingService(

Each endpoint you will target with your project must be defined for the service as a `WPNEndpoint` instance. There are several types of endpoints based on the PowerAuth signature that is required.

### End To End Encryption

If the endpoint is end-to-end encrypted, you need to configure it in the init. Default initializers are set to `e2ee: .notEncrypted`.

Possible values are:

```swift
/// Endpoint configuration for end to end encryption.
public enum WPNE2EEConfiguration {
/// Endpoint is encrypted with the application scope.
case applicationScope
/// Endpoint is encrypted with the activation scope.
case activationScope
/// Endpoint is not encrypted.
case notEncrypted
}
```

<!-- begin box info -->
Whether an endpoint is encrypted or not is based on its backend definition.
<!-- end -->

### Signed endpoint `WPNEndpointSigned`

For endpoints that are __signed__ by PowerAuth signature and can be end-to-end encrypted.
Expand All @@ -133,7 +156,7 @@ Example:

```swift
typealias MySignedEndpointType = WPNEndpointSigned<WPNRequest<MyEndpointDataRequest>, WPNResponse<MyEndpointDataResponse>>
var mySignedEndpoint: MySignedEndpointType { WPNEndpointSigned(endpointURLPath: "/additional/path/to/the/signed/endpoint", uriId: "endpoint/identifier") }
var mySignedEndpoint: MySignedEndpointType { WPNEndpointSigned(endpointURLPath: "/additional/path/to/the/signed/endpoint", uriId: "endpoint/identifier", e2ee: .notEncrypted) }
// uriId is defined by the endpoint issuer - ask your server developer/provider

```
Expand All @@ -148,7 +171,7 @@ Example:

```swift
typealias MyTokenEndpointType = WPNEndpointSignedWithToken<WPNRequest<MyEndpointDataRequest>, WPNResponse<MyEndpointDataResponse>>
var myTokenEndpoint: MyTokenEndpointType { WPNEndpointSignedWithToken(endpointURLPath: "/additional/path/to/the/token/signed/endpoint", tokenName: "MyToken") }
var myTokenEndpoint: MyTokenEndpointType { WPNEndpointSignedWithToken(endpointURLPath: "/additional/path/to/the/token/signed/endpoint", tokenName: "MyToken", e2ee: .notEncrypted) }

// tokenName is the name of the token as stored in the PowerAuthSDK
// more info can be found in the PowerAuthSDK documentation
Expand All @@ -164,7 +187,7 @@ Example:

```swift
typealias MyBasicEndpointType = WPNEndpointBasic<WPNRequest<MyEndpointDataRequest>, WPNResponse<MyEndpointDataResponse>>
var myBasicEndpoint: MyBasicEndpointType { WPNEndpointBasic(endpointURLPath: "/additional/path/to/the/basic/endpoint") }
var myBasicEndpoint: MyBasicEndpointType { WPNEndpointBasic(endpointURLPath: "/additional/path/to/the/basic/endpoint", e2ee: .notEncrypted) }

```

Expand All @@ -177,7 +200,6 @@ To create an HTTP request to your endpoint, you need to call the `WPNNetworkingS
- this parameter is missing for the basic endpoint
- `endpoint` - an endpoint that will be called
- `headers` - custom HTTP headers, `nil` by default
- `encryptor` - End to End encryptor in case that the encryption is required, `nil` by default
- `timeoutInterval` - timeout interval, `nil` by default. When `nil`, the default configured in `WPNConfig` will be used
- `progressCallback` - callback with percentage progress (values between 0 and 1)
- `completionQueue` - queue that the completion will be called on (main queue by default)
Expand Down Expand Up @@ -213,8 +235,6 @@ networking.post(
to: endpoint,
// custom HTTP headers
with: ["MyCustomHeader": "Value"],
// encrypt with the application scope
encryptedWith: powerAuth.eciesEncryptorForApplicationScope(),
// only wait 10 seconds at max
timeoutInterval: 10,
// handle response or error
Expand Down Expand Up @@ -309,7 +329,7 @@ Each `WPNError` has a `reason` property for why the error was created. Such reas
| Option Name | Description |
|---|---|
|`network_unknown`|When unknown (usually logic error) happened during networking.|
|`network_generic`|When generic networking error happened.|
|`network_generic`|Network error that indicates a generic network issue (for example server internal error).|
|`network_errorStatusCode`|HTTP response code was different than 200 (success).|
|`network_invalidResponseObject`|An unexpected response from the server.|
|`network_invalidRequestObject`|Request is not valid. Such an object is not sent to the server.|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ public enum WPNKnownRestApiError: String, Decodable {
/// Returned in case encryption or decryption fails
case encryptionError = "ERR_ENCRYPTION"

/// Temporary key not matched on the server.
case temporaryKeyError = "ERR_TEMPORARY_KEY"

// PUSH ERRORS

/// Failed to register push notifications
Expand Down
27 changes: 27 additions & 0 deletions Sources/WultraPowerauthNetworking/WPNEncryptorScope.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// Copyright 2024 Wultra s.r.o.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions
// and limitations under the License.
//

import Foundation

/// End to end encryption configuration for an endpoint.
public enum WPNE2EEConfiguration {
/// Endpoint is encrypted with the application scope.
case applicationScope
/// Endpoint is encrypted with the activation scope.
case activationScope
/// Endpoint is not encrypted.
case notEncrypted
}
52 changes: 38 additions & 14 deletions Sources/WultraPowerauthNetworking/WPNEndpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,16 @@ public class WPNEndpoint<TRequestData: WPNRequestBase, TResponseData: WPNRespons
/// For example "/my/custom/endpoint"
public let endpointURLPath: String

init(endpointURLPath: String) {
/// End to end encryption configuration
public let e2ee: WPNE2EEConfiguration

/// Class that describes a server endpoint.
/// - Parameters:
/// - endpointURLPath: URL path for the endpoint. For example "/my/custom/endpoint".
/// - e2ee: End to end encryption configuration.
init(endpointURLPath: String, e2ee: WPNE2EEConfiguration) {
self.endpointURLPath = endpointURLPath
self.e2ee = e2ee
}

typealias Request = WPNHttpRequest<TRequestData, TResponseData>
Expand All @@ -37,32 +45,48 @@ public class WPNEndpoint<TRequestData: WPNRequestBase, TResponseData: WPNRespons
public typealias Completion = (TResponseData?, WPNError?) -> Void
}

/// Basic endpoint - not signed.
/// Basic endpoint not signed with PowerAuth.
public class WPNEndpointBasic<RequestData: WPNRequestBase, ResponseData: WPNResponseBase>: WPNEndpoint<RequestData, ResponseData> {
public override init(endpointURLPath: String) {
super.init(endpointURLPath: endpointURLPath)

/// Basic endpoint - not signed with PowerAuth
/// - Parameters:
/// - endpointURLPath: URL path for the endpoint. For example "/my/custom/endpoint".
/// - e2ee: End to end encryption configuration. `.notEncrypted` by default
public override init(endpointURLPath: String, e2ee: WPNE2EEConfiguration = .notEncrypted) {
super.init(endpointURLPath: endpointURLPath, e2ee: e2ee)
}
}

/// Endpoint signed with PowerAuth signature
public class WPNEndpointSigned<RequestData: WPNRequestBase, ResponseData: WPNResponseBase>: WPNEndpoint<RequestData, ResponseData> {

let uriId: String
/// Endpoint ID. Note that this is different from endpoint URL
public let uriId: String

public init(endpointURLPath: String, uriId: String) {
/// Endpoint signed with PowerAuth signature.
/// - Parameters:
/// - endpointURLPath: URL path for the endpoint. For example "/my/custom/endpoint".
/// - uriId: Endpoint ID. Note that this is different from endpoint URL.
/// - e2ee: End to end encryption configuration. `.notEncrypted` by default
public init(endpointURLPath: String, uriId: String, e2ee: WPNE2EEConfiguration = .notEncrypted) {
self.uriId = uriId
super.init(endpointURLPath: endpointURLPath)
super.init(endpointURLPath: endpointURLPath, e2ee: e2ee)
}
}

/// Endpoint signed with PowerAuth Token signature
public class WPNEndpointSignedWithToken<RequestData: WPNRequestBase, ResponseData: WPNResponseBase>: WPNEndpoint<RequestData, ResponseData> {
let tokenName: String

public init(endpointURLPath: String, tokenName: String) {
/// Name of the token used for signature.
public let tokenName: String

/// Endpoint signed with PowerAuth Token signature.
/// - Parameters:
/// - endpointURLPath: URL path for the endpoint. For example "/my/custom/endpoint".
/// - tokenName: Name of the token used for signature.
/// - e2ee: End to end encryption configuration. `.notEncrypted` by default
public init(endpointURLPath: String, tokenName: String, e2ee: WPNE2EEConfiguration = .notEncrypted) {
self.tokenName = tokenName
super.init(endpointURLPath: endpointURLPath)
super.init(endpointURLPath: endpointURLPath, e2ee: e2ee)
}
}

public extension WPNEndpointBasic {

}
10 changes: 4 additions & 6 deletions Sources/WultraPowerauthNetworking/WPNHttpClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,17 @@ class WPNHttpClient: NSObject, URLSessionDelegate {
super.init()
}

func post<Req: WPNRequestBase, Resp: WPNResponseBase>(request: WPNHttpRequest<Req, Resp>, progressCallback: ((Double) -> Void)?, completion: @escaping (Data?, HTTPURLResponse?, Error?) -> Void) {
func post(request: URLRequest, progressCallback: ((Double) -> Void)?, completion: @escaping (Data?, HTTPURLResponse?, Error?) -> Void) {

let urlRequest = request.buildUrlRequest()

if request.url.absoluteString.hasPrefix("http://") {
if request.url?.absoluteString.hasPrefix("http://") == true {
D.warning("Using HTTP for communication may create a serious security issue! Use HTTPS in production.")
}

urlRequest.printToConsole()
request.printToConsole()

var observation: NSKeyValueObservation?

let task = urlSession.dataTask(with: urlRequest) { responseData, response, error in
let task = urlSession.dataTask(with: request) { responseData, response, error in
observation?.invalidate()
observation = nil
assert(Thread.isMainThread) // make sure we're on the right thread
Expand Down
Loading