iOS から iOS への端末移行時、iCloud を用いてセキュアにユーザを紐付けするコード
Last active
February 7, 2016 10:25
-
-
Save kaiinui/30f4a341da5c7249a573 to your computer and use it in GitHub Desktop.
CIDCloudKeyManager
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
@interface CIDCloudKeyManager : NSObject | |
+ (instancetype)sharedManager; | |
- (void)startFetchingWithContainerIdentifier:(NSString *)identifier | |
storingCloudKeyBlock:(void(^)(NSString *cloudKeyID, NSString *cloudKeySecret))storingCloudKeyBlock | |
paringCloudKeyBlock:(void(^)(NSString *cloudKeyID, NSString *cloudKeySecret))paringCloudKeyBlock; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "CIDCloudKeyManager.h" | |
@import CloudKit; | |
static NSString *const kCIDCloudKeyRecordID = @"TheCloudKey"; | |
static NSString *const kCIDCloudKeyRecordType = @"CloudKey"; | |
static NSString *const kCIDCloudKeySecretKey = @"secret"; | |
static NSString *CIDMakeRandomKey(int length) { | |
NSString *alphabet = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY0123456789"; | |
NSMutableString *s = [NSMutableString stringWithCapacity:length]; | |
for (NSUInteger i = 0U; i < length; i++) { | |
u_int32_t r = arc4random() % [alphabet length]; | |
unichar c = [alphabet characterAtIndex:r]; | |
[s appendFormat:@"%C", c]; | |
} | |
return s.copy; | |
}; | |
static void CIDSaveCloudKey(NSString *cloudKeyID, NSString *secret) { | |
NSLog(@"Saving cloud key: %@:%@", cloudKeyID, secret); | |
} | |
static void CIDPairCloudKey(NSString *cloudKeyID, NSString *secret) { | |
NSLog(@"Checking cloud key: %@:%@", cloudKeyID, secret); | |
} | |
static CKRecordID *CIDMakeTheCloudKeyRecordID() { | |
return [[CKRecordID alloc] initWithRecordName:kCIDCloudKeyRecordID]; | |
} | |
static CKRecord *CIDMakeCloudKeyWithRandomSecret() { | |
NSString *secret = CIDMakeRandomKey(32); | |
CKRecord *cloudKey = [[CKRecord alloc] initWithRecordType:kCIDCloudKeyRecordType recordID:CIDMakeTheCloudKeyRecordID()]; | |
[cloudKey setObject:secret forKey:kCIDCloudKeySecretKey]; | |
return cloudKey; | |
} | |
@implementation CIDCloudKeyManager | |
+ (instancetype)sharedManager { | |
static CIDCloudKeyManager *_instance; | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
_instance = [[CIDCloudKeyManager alloc] init]; | |
}); | |
return _instance; | |
} | |
- (void)startFetchingWithContainerIdentifier:(NSString *)identifier storingCloudKeyBlock:(void (^)(NSString *, NSString *))storingCloudKeyBlock paringCloudKeyBlock:(void (^)(NSString *, NSString *))paringCloudKeyBlock { | |
CKContainer *container = [CKContainer defaultContainer]; | |
if (identifier != nil) { | |
container = [CKContainer containerWithIdentifier:identifier]; | |
} | |
[container fetchUserRecordIDWithCompletionHandler:^(CKRecordID *recordID, NSError *error) { | |
if (recordID == nil || error != nil) { | |
NSLog(@"%@", error); | |
return; | |
} | |
NSString *userId = recordID.recordName; | |
NSLog(@"Found record ID! Try to fetch CloudKey."); | |
CKDatabase *db = container.privateCloudDatabase; | |
[db fetchRecordWithID:CIDMakeTheCloudKeyRecordID() completionHandler:^(CKRecord *record, NSError *error) { | |
if (record != nil) { | |
NSLog(@"Found!! Should do paring."); | |
NSString *secret = [record objectForKey:kCIDCloudKeySecretKey]; | |
if (paringCloudKeyBlock != nil) { | |
paringCloudKeyBlock(userId, secret); | |
} | |
return; | |
} | |
if ([error.domain isEqualToString:CKErrorDomain] && error.code == CKErrorUnknownItem) { | |
NSLog(@"Cloud not find CloudKey. Try to create CloudKey."); | |
CKRecord *cloudKey = CIDMakeCloudKeyWithRandomSecret(); | |
[db saveRecord:cloudKey completionHandler:^(CKRecord *record, NSError *error) { | |
if (error != nil) { | |
NSLog(@"Error occured during saving: %@", error); | |
} | |
NSLog(@"Complete everything!"); | |
NSString *secret = [record objectForKey:kCIDCloudKeySecretKey]; | |
CIDSaveCloudKey(userId, secret); | |
if (storingCloudKeyBlock != nil) { | |
storingCloudKeyBlock(userId, secret); | |
} | |
}]; | |
} else { | |
NSLog(@"Unknown error occured. Should retry?"); | |
} | |
}]; | |
}]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment