Skip to content

Commit

Permalink
DIGI-17598 Ongoing Postbox support (#202)
Browse files Browse the repository at this point in the history
* DIGI-20955 Ongoing Postbox support (#199)

* Fix some flow errors

* WIP

* Split common ongoing OAuth flow into separate class: DMEOAuthService

* Move some more functions to OAuthService

* Ensure that all pull and push client callbacks occur on main thread.

* OAuthToken and OngoingPostbox now conform to NSSecureCoding.

* Split action for opening digi.me app into host and path where necessary.

* Bump cyclic endpoints to v1.4

* Add workspace checks

* Update new SDK functions to complete on main thread

* Return an SDK error if try to use ongoing postbox with one-off contract

* Update Swift demo to include ongoing postbox example

* Update tests

* Oops. Wasn't actually pushing data using oauth token!!

* DIGI-21401 Update examples app to include contacts and private keys (#201)

* Add example contracts for private sharing

* Add example contracts and p12s

* Fix error when decoding ongoing postbox

* Store ongoing postboxes in example.

* Add instruction for user to try relaunching app after first ongoing postbox push

* Update ongoing private sharing contract.

Added info about each contract in the code.

* Fix broken CA pull examples.

* DIGI-21393 Ongoing Postbox documentation (#200)

* Add Ongoing Postbox documentation

* Add migration tips for breaking code

* Update Postbox docs with breaking changes and reference ongoing gpostbox

* Fix scope documentation to refer to DMESessionOptions

* Fix spelling

* Fix broken link in getting started

* Remove unnecessary docsets

* Ignore docsets in future and any intermediary files for documentation generation

* Split sources & scripts for documentation generation into seperate folder

* Add documentation for Swift files

* Update readmes
  • Loading branch information
michaeleustace authored Mar 5, 2021
1 parent 994fc22 commit 646c7f6
Show file tree
Hide file tree
Showing 196 changed files with 9,990 additions and 27,444 deletions.
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ Carthage
#
Pods/
Podfile.lock
docs/docsets/

# jazzy & sourcekitten document generation
docs/docsets/
docsets/
Documentation/objcDoc.json
Documentation/swiftDoc.json
3 changes: 2 additions & 1 deletion DigiMeSDK.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "DigiMeSDK"
s.version = "3.3.0"
s.version = "4.0.0"
s.summary = "digi.me iOS Consent Access SDK"
s.homepage = "https://github.com/digime/digime-sdk-ios"
s.license = { :type => "MIT", :file => "LICENSE" }
Expand All @@ -26,6 +26,7 @@ Pod::Spec.new do |s|
'DigiMeSDK/Core/Classes/Network/DMERequestFactory.h',
'DigiMeSDK/Core/Classes/Security/DMECrypto.h',
'DigiMeSDK/Core/Classes/Security/DMEDataDecryptor.h',
'DigiMeSDK/Core/Classes/Security/DMEOAuthService.h',
'DigiMeSDK/Core/Classes/Utility/DMECompressor.h',
'DigiMeSDK/Core/Classes/Utility/DMEDataRequestSerializer.h',
'DigiMeSDK/Core/Classes/Utility/DMEFileListDeserializer.h',
Expand Down
9 changes: 9 additions & 0 deletions DigiMeSDK/Core/Classes/Callbacks/DMEClientCallbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
@class DMEAccounts;
@class DMEFile;
@class DMEPostbox;
@class DMEOngoingPostbox;
@class DMESession;
@class DMEFileList;
@class DMEOAuthToken;
Expand Down Expand Up @@ -56,6 +57,14 @@ typedef void (^DMEPostboxCreationCompletion) (DMEPostbox * _Nullable postbox, NS
*/
typedef void (^DMEPostboxDataPushCompletion) (NSError * _Nullable error);

/**
DMEOngoingPostboxCompletion - executed when an ongoing Postbox is created/updated or when data is pushed to ongoing Postbox.
@param postbox The ongoing Postbox if creation is successful, nil if not
@param error nil if ongoing Postbox creation is successful, otherwise an error specifying what went wrong
*/
typedef void (^DMEOngoingPostboxCompletion) (DMEOngoingPostbox * _Nullable postbox, NSError * _Nullable error);

/**
DMEFileContentCompletion - executed when a file has been retrieved.
Expand Down
9 changes: 8 additions & 1 deletion DigiMeSDK/Core/Classes/DMEAppCommunicator.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ - (BOOL)canOpenDMEApp

- (void)openDigiMeAppWithAction:(DMEOpenAction *)action parameters:(NSDictionary *)parameters
{
NSArray *actionComponents = [action componentsSeparatedByString:@"/"];
NSAssert(actionComponents.count < 3, @"Invalid action. Should contain at most one '/'");
self.sentAction = action;
self.sentParameters = parameters;
dispatch_async(dispatch_get_main_queue(), ^{
Expand All @@ -77,7 +79,12 @@ - (void)openDigiMeAppWithAction:(DMEOpenAction *)action parameters:(NSDictionary
}

NSURLComponents *components = [NSURLComponents componentsWithURL:[self digiMeBaseURL] resolvingAgainstBaseURL:NO];
components.host = action;
components.host = actionComponents[0];

if (actionComponents.count == 2)
{
components.path = [NSString stringWithFormat:@"/%@", actionComponents[1]];
}

NSMutableArray *newQueryItems = [NSMutableArray arrayWithArray:components.queryItems] ?: [NSMutableArray array];
[newQueryItems addObject:[NSURLQueryItem queryItemWithName:kDMESdkVersion value:[[NSBundle bundleForClass:[self class]] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]]];
Expand Down
27 changes: 26 additions & 1 deletion DigiMeSDK/Core/Classes/DMEBaseConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,39 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, copy) NSString *contractId;

/**
Your rsa private key hex. This property MUST be set before you can call authorize.
*/
@property (nonatomic, copy) NSString *privateKeyHex;

/**
Determines whether the user is automatically forwarded
to digi.me app when the `DMEOAuthToken` could not be refreshed by the SDK.
Default to YES.
Setting this to NO will instead return a `AuthErrorOAuthTokenExpired` error.
*/
@property (nonatomic) BOOL autoRecoverExpiredCredentials;

/**
Designated Initializer
@param appId application identifier
@param contractId contract identifier
@param privateKeyHex RSA private key string in HEX format
@return instancetype
*/
- (instancetype)initWithAppId:(NSString *)appId contractId:(NSString *)contractId NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithAppId:(NSString *)appId contractId:(NSString *)contractId privateKeyHex:(NSString *)privateKeyHex NS_DESIGNATED_INITIALIZER;

/**
Convinience Initializer
@param appId application identifier
@param contractId contract identifier
@param p12FileName RSA private key file name from your application bundle
@param p12Password p12 file password
@return instancetype or nil if failed to extract private key from p12
*/
- (nullable instancetype)initWithAppId:(NSString *)appId contractId:(NSString *)contractId p12FileName:(NSString *)p12FileName p12Password:(NSString *)p12Password;

- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
Expand Down
21 changes: 17 additions & 4 deletions DigiMeSDK/Core/Classes/DMEBaseConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
//

#import "DMEBaseConfiguration.h"

NSString * const kDMEConfigFileName = @"DMEConfig";
#import "DMECryptoUtilities.h"

@interface DMEBaseConfiguration()

Expand All @@ -18,7 +17,7 @@ @implementation DMEBaseConfiguration

#pragma mark - Initialization

- (instancetype)initWithAppId:(NSString *)appId contractId:(NSString *)contractId
- (instancetype)initWithAppId:(NSString *)appId contractId:(NSString *)contractId privateKeyHex:(NSString *)privateKeyHex
{
self = [super init];
if (self)
Expand All @@ -33,9 +32,23 @@ - (instancetype)initWithAppId:(NSString *)appId contractId:(NSString *)contractI
_maxConcurrentRequests = 5;
_debugLogEnabled = NO;
_baseUrl = @"https://api.digi.me/";
_autoRecoverExpiredCredentials = YES;
_privateKeyHex = privateKeyHex;
}

return self;
}

- (nullable instancetype)initWithAppId:(NSString *)appId contractId:(NSString *)contractId p12FileName:(NSString *)p12FileName p12Password:(NSString *)p12Password
{
NSString *privateKeyHex = [DMECryptoUtilities privateKeyHexFromP12File: p12FileName password: p12Password];

if (!privateKeyHex)
{
return nil;
}

return [self initWithAppId:appId contractId:contractId privateKeyHex:privateKeyHex];
}

@end
5 changes: 5 additions & 0 deletions DigiMeSDK/Core/Classes/DMEClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ - (nullable NSError *)validateClient
return [NSError sdkError:SDKErrorInvalidContract];
}

if (!self.configuration.privateKeyHex)
{
return [NSError sdkError:SDKErrorNoPrivateKeyHex];
}

return nil;
}

Expand Down
13 changes: 13 additions & 0 deletions DigiMeSDK/Core/Classes/DMEClientConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,19 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, copy) NSString *contractId;

/**
Your rsa private key hex. This property MUST be set before you can call authorize.
*/
@property (nonatomic, copy) NSString *privateKeyHex;

/**
Determines whether the user is automatically forwarded
to digi.me app when the `DMEOAuthToken` could not be refreshed by the SDK.
Default to YES.
Setting this to NO will instead return a `AuthErrorOAuthTokenExpired` error.
*/
@property (nonatomic) BOOL autoRecoverExpiredCredentials;

@end

NS_ASSUME_NONNULL_END
14 changes: 5 additions & 9 deletions DigiMeSDK/Core/Classes/DMENativeConsentManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ - (void)handleAction:(DMEOpenAction *)action withParameters:(NSDictionary<NSStri

NSError *error;

if(![self.sessionManager isSessionKeyValid:sessionKey])
if (![self.sessionManager isSessionKeyValid:sessionKey])
{
error = [NSError authError:AuthErrorInvalidSessionKey];
}
Expand All @@ -73,19 +73,15 @@ - (void)handleAction:(DMEOpenAction *)action withParameters:(NSDictionary<NSStri
{
// Need to know if we succeeded.
DMESession *session = error == nil ? self.session : nil;
dispatch_async(dispatch_get_main_queue(), ^{
self.authCompletionBlock(session, error);
self.authCompletionBlock = nil;
});
self.authCompletionBlock(session, error);
self.authCompletionBlock = nil;
}
else if (self.ongoingAccessExchangeCompletionBlock)
{
// Need to know if we succeeded.
DMESession *session = error == nil ? self.session : nil;
dispatch_async(dispatch_get_main_queue(), ^{
self.ongoingAccessExchangeCompletionBlock(session, authorizationCode, error);
self.ongoingAccessExchangeCompletionBlock = nil;
});
self.ongoingAccessExchangeCompletionBlock(session, authorizationCode, error);
self.ongoingAccessExchangeCompletionBlock = nil;
}

[self.appCommunicator removeCallbackHandler:self];
Expand Down
28 changes: 14 additions & 14 deletions DigiMeSDK/Core/Classes/DMEPullClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
Either redirect to the digi.me application (if installed) or present options for user to choose a one-time share or download the digi.me app.
- Guest is not enabled:
Redirect to the digi.me application (if installed).
@param completion Block called when authorization has completed
@param completion Block called on main thread when authorization has completed
*/
- (void)authorizeWithCompletion:(DMEAuthorizationCompletion)completion;

Expand All @@ -48,15 +48,15 @@ NS_ASSUME_NONNULL_BEGIN
Redirect to the digi.me application (if installed).
@param scope Custom scope that will be applied to available data.
@param completion Block called when authorization has completed
@param completion Block called on main thread when authorization has completed
*/
- (void)authorizeWithScope:(nullable id<DMEDataRequest>)scope completion:(DMEAuthorizationCompletion)completion __attribute((deprecated("Use authorizeWithOptions:completion: instead."))) NS_SWIFT_NAME(authorize(scope:completion:));

/**
Initializes ongoing contract authentication. Once user has given consent in digi.me app all subsequent data retrieval calls will be done without digi.me client app involvement.
This authorization flow enables 3rd parties to access protected resources, without requiring users to disclose their digi.me credentials to the consumers.
@param completion Block called when authorization has completed
@param completion Block called on main thread when authorization has completed
*/
- (void)authorizeOngoingAccessWithСompletion:(DMEOngoingAccessAuthorizationCompletion)completion NS_SWIFT_NAME(authorizeOngoingAccess(completion:));

Expand All @@ -66,7 +66,7 @@ NS_ASSUME_NONNULL_BEGIN
@param scope Custom scope that will be applied to available data.
@param oAuthToken valid OAuth token
@param completion Block called when authorization has completed
@param completion Block called on main thread when authorization has completed
*/
- (void)authorizeOngoingAccessWithScope:(nullable id<DMEDataRequest>)scope oAuthToken:(DMEOAuthToken * _Nullable)oAuthToken completion:(DMEOngoingAccessAuthorizationCompletion)completion __attribute((deprecated("Use authorizeOngoingAccessWithOptions:oAuthToken:completion: instead."))) NS_SWIFT_NAME(authorizeOngoingAccess(scope:oAuthToken:completion:));

Expand All @@ -81,19 +81,19 @@ NS_ASSUME_NONNULL_BEGIN
Redirect to the digi.me application (if installed).
@param options additional session configuration options
@param completion Block called when authorization has completed
@param completion Block called on main thread when authorization has completed
*/
- (void)authorizeWithOptions:(DMESessionOptions * _Nullable)options completion:(DMEAuthorizationCompletion)completion NS_SWIFT_NAME(authorize(options:completion:));
- (void)authorizeWithOptions:(nullable DMESessionOptions *)options completion:(DMEAuthorizationCompletion)completion NS_SWIFT_NAME(authorize(options:completion:));

/**
Initializes ongoing contract authentication with custom session configuration. Once user has given consent in digi.me app all subsequent data retrieval calls will be done without digi.me client app involvement.
This authorization flow enables 3rd parties to access protected resources, without requiring users to disclose their digi.me credentials to the consumers
@param options additional session configuration options
@param oAuthToken valid OAuth token
@param completion Block called when authorization has completed
@param completion Block called on main thread when authorization has completed
*/
- (void)authorizeOngoingAccessWithOptions:(DMESessionOptions * _Nullable)options oAuthToken:(DMEOAuthToken * _Nullable)oAuthToken completion:(DMEOngoingAccessAuthorizationCompletion)completion NS_SWIFT_NAME(authorizeOngoingAccess(options:oAuthToken:completion:));
- (void)authorizeOngoingAccessWithOptions:(nullable DMESessionOptions *)options oAuthToken:(DMEOAuthToken * _Nullable)oAuthToken completion:(DMEOngoingAccessAuthorizationCompletion)completion NS_SWIFT_NAME(authorizeOngoingAccess(options:oAuthToken:completion:));

/**
Fetches content for all the requested files.
Expand All @@ -104,23 +104,23 @@ NS_ASSUME_NONNULL_BEGIN
N.B. A session must already have been authorized
@param fileContentHandler Handler called after every file fetch attempt finishes. Either contains the file or an error if fetch failed
@param completion Contains final snapshot of DMEFileList. Error object will be set if an error occurred, nil otherwise
@param completion Block called on main thread when fetch completed. Contains final snapshot of DMEFileList. Error object will be set if an error occurred, nil otherwise
*/
- (void)getSessionDataWithDownloadHandler:(DMEFileContentCompletion)fileContentHandler completion:(DMESessionDataCompletion)completion NS_SWIFT_NAME(getSessionData(downloadHandler:completion:));

/**
Fetches file content for fileId. The fileId may be retrieved from the download handler in getSessionDataWithDownloadHandler:completion:.
@param fileId NSString id if the file to fetch.
@param completion Reports result of fetch. Either contains the file or an error if fetch failed
@param completion Block called on main thread when fetch completed. Either contains the file or an error if fetch failed
*/
- (void)getSessionDataForFileWithId:(NSString *)fileId completion:(DMEFileContentCompletion)completion __attribute((deprecated("Use getSessionDataWithFileId:completion: instead."))) NS_SWIFT_UNAVAILABLE("Swift name now associated with getSessionDataWithFileId:completion:");

/**
Fetches file content for fileId. The fileId may be retrieved from the download handler in getSessionDataWithDownloadHandler:completion:.
@param fileId NSString id if the file to fetch.
@param completion Reports result of fetch. Either contains the file or an error if fetch failed
@param completion Block called on main thread when fetch completed. Either contains the file or an error if fetch failed
*/
- (void)getSessionDataWithFileId:(NSString *)fileId completion:(DMEFileContentCompletion)completion NS_SWIFT_NAME(getSessionData(fileId:completion:));

Expand All @@ -133,22 +133,22 @@ NS_ASSUME_NONNULL_BEGIN
together with an array of fileIds that have been added or updated since last snapshot.
Only notified when a change has occurred. See `DMESessionFileListCompletion` for details.
@param completion executed when file list has finished updating, and no more changes will come.
@param completion Block called on main thread when file list has finished updating, and no more changes will come.
Error object will be set if an error occurred, nil otherwise.
*/
- (void)getSessionFileListWithUpdateHandler:(DMESessionFileListCompletion)updateHandler completion:(void (^)(NSError * _Nullable error))completion NS_SWIFT_NAME(getSessionFileList(updateHandler:completion:));

/**
Fetches file list which contains current snapshot of the sync progress, and a list of files that are available for download.
@param completion Completion block executed once request has completed successfully.
@param completion Completion block executed on main thread once request has completed successfully.
*/
- (void)getFileListWithCompletion:(void (^)(DMEFileList * _Nullable fileList, NSError * _Nullable error))completion;

/**
Fetches the accounts available for the authorized contract.
@param completion Reports result of fetch. Either contains the accounts or an error if fetch failed
@param completion Block called on main thread when fetch completed. Either contains the accounts or an error if fetch failed
*/
- (void)getSessionAccountsWithCompletion:(DMEAccountsCompletion)completion NS_SWIFT_NAME(getSessionAccounts(completion:));

Expand Down
Loading

0 comments on commit 646c7f6

Please sign in to comment.