Skip to content

Commit 62a6b15

Browse files
committed
Merge branch 'task/post_request_for_auth' into develop
2 parents 50eea1d + a3bad0f commit 62a6b15

File tree

6 files changed

+125
-66
lines changed

6 files changed

+125
-66
lines changed

Classes/Core/JSRESTBase+JSRESTSession.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@
4747
4848
@since 1.9
4949
*/
50-
51-
- (BOOL)isSessionAuthorized;
52-
50+
- (BOOL)isSessionAuthorized __attribute__((deprecated));
51+
- (void)verifyIsSessionAuthorizedWithCompletion:(void (^)(BOOL isSessionAuthorized))completion;
5352

5453
@end

Classes/Core/JSRESTBase+JSRESTSession.m

Lines changed: 92 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,25 @@
4141
NSString * const kJSAuthenticationTimezoneKey = @"userTimezone";
4242

4343
@implementation JSRESTBase(JSRESTSession)
44+
45+
#pragma mark - Public API
4446
- (BOOL)isSessionAuthorized {
47+
return self.cookies.count > 0;
48+
}
49+
50+
- (void)verifyIsSessionAuthorizedWithCompletion:(void (^)(BOOL isSessionAuthorized))completion
51+
{
4552
if ([self.cookies count]) {
46-
return YES;
53+
if (completion) {
54+
completion(YES);
55+
}
4756
} else {
48-
return [self authenticationToken];
57+
[self authenticateWithCompletion:completion];
4958
}
5059
}
5160

52-
- (BOOL)authenticationToken
61+
#pragma mark - Private API
62+
- (void)fetchEncryptionKeyWithCompletion:(void(^)(NSString *modulus, NSString *exponent, NSError *error))completion
5363
{
5464
NSString *URI = @"GetEncryptionKey";
5565
JSRequest *request = [[JSRequest alloc] initWithUri:URI];
@@ -58,72 +68,83 @@ - (BOOL)authenticationToken
5868
request.method = RKRequestMethodGET;
5969
request.responseAsObjects = NO;
6070
request.redirectAllowed = NO;
61-
request.asynchronous = NO;
71+
request.asynchronous = YES;
6272

63-
__block BOOL authenticationSuccess = NO;
6473
[request setCompletionBlock:@weakself(^(JSOperationResult *result)) {
65-
NSString *password = self.serverProfile.password;
66-
67-
NSError *jsonError;
68-
NSData *jsonData = result.body;
69-
if (jsonData) {
70-
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData
71-
options:NSJSONReadingMutableContainers
72-
error:&jsonError];
73-
if (json) {
74-
NSString *modulus = json[@"n"];
75-
NSString *exponent = json[@"e"];
76-
77-
if (modulus && exponent) {
78-
JSEncryptionManager *encryptionManager = [JSEncryptionManager managerWithModulus:modulus
79-
exponent:exponent];
80-
password = [encryptionManager encryptText:password];
74+
if (completion) {
75+
if (result.error) {
76+
completion(nil, nil, result.error);
77+
} else {
78+
NSData *jsonData = result.body;
79+
NSError *error = nil;
80+
if (jsonData) {
81+
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData
82+
options:NSJSONReadingMutableContainers
83+
error:&error];
84+
if (json) {
85+
NSString *modulus = json[@"n"];
86+
NSString *exponent = json[@"e"];
87+
if (modulus && exponent) {
88+
completion(modulus, exponent, nil);
89+
} else {
90+
NSDictionary *userInfo = @{NSLocalizedDescriptionKey : @"Encription Key doesn't valid. Modulus or exponent is absent."};
91+
error = [NSError errorWithDomain:NSURLErrorDomain code:JSClientErrorCode userInfo:userInfo];
92+
completion(nil, nil, error);
93+
}
94+
} else {
95+
completion(nil, nil, error);
96+
}
97+
} else {
98+
NSDictionary *userInfo = @{NSLocalizedDescriptionKey : @"Encription Key data is empty."};
99+
error = [NSError errorWithDomain:NSURLErrorDomain code:JSClientErrorCode userInfo:userInfo];
100+
completion(nil, nil, error);
101+
}
81102
}
82103
}
83-
}
84-
authenticationSuccess = [self authenticationTokenWithUsername:self.serverProfile.username
85-
password:password
86-
organization:self.serverProfile.organization];
87-
88-
} @weakselfend];
104+
}@weakselfend];
89105

90106
[self sendRequest:request];
91-
return authenticationSuccess;
92107
}
93108

94-
- (BOOL)authenticationTokenWithUsername:(nonnull NSString *)username
95-
password:(nonnull NSString *)password
96-
organization:(nullable NSString *)organization
109+
- (void)fetchAuthenticationTokenWithUsername:(NSString *)username
110+
password:(NSString *)password
111+
organization:(NSString *)organization
112+
method:(RKRequestMethod)requestMethod
113+
completion:(void(^)(BOOL isTokenFetchedSuccessful))completion
97114
{
98115
JSRequest *request = [[JSRequest alloc] initWithUri:[JSConstants sharedInstance].REST_AUTHENTICATION_URI];
99116
request.restVersion = JSRESTVersion_None;
100-
request.method = RKRequestMethodGET;
117+
request.method = requestMethod;
101118
request.responseAsObjects = NO;
102119
request.redirectAllowed = NO;
103-
request.asynchronous = NO;
120+
request.asynchronous = YES;
104121

105122
[self resetReachabilityStatus];
106123

107-
[request addParameter:kJSAuthenticationUsernameKey withStringValue:username];
108-
[request addParameter:kJSAuthenticationPasswordKey withStringValue:password];
109-
[request addParameter:kJSAuthenticationOrganizationKey withStringValue:organization];
110-
[request addParameter:kJSAuthenticationTimezoneKey withStringValue:[[NSTimeZone localTimeZone] name]];
111-
112124
// Add locale to session
113125
NSString *currentLanguage = [[NSLocale preferredLanguages] objectAtIndex:0];
114126
NSInteger dividerPosition = [currentLanguage rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"_-"]].location;
115127
if (dividerPosition != NSNotFound) {
116128
currentLanguage = [currentLanguage substringToIndex:dividerPosition];
117129
}
118130
NSString *currentLocale = [[JSConstants sharedInstance].REST_JRS_LOCALE_SUPPORTED objectForKey:currentLanguage];
131+
132+
[request addParameter:kJSAuthenticationUsernameKey withStringValue:username];
133+
[request addParameter:kJSAuthenticationPasswordKey withStringValue:password];
134+
[request addParameter:kJSAuthenticationOrganizationKey withStringValue:organization];
135+
[request addParameter:kJSAuthenticationTimezoneKey withStringValue:[[NSTimeZone localTimeZone] name]];
119136
[request addParameter:kJSAuthenticationLocaleKey withStringValue:currentLocale];
120137

121-
__block BOOL authenticationSuccess = NO;
138+
if (requestMethod == RKRequestMethodPOST) {
139+
self.restKitObjectManager.requestSerializationMIMEType = RKMIMETypeFormURLEncoded;
140+
}
141+
122142
[request setCompletionBlock:@weakself(^(JSOperationResult *result)) {
143+
BOOL isTokenFetchedSuccessful = NO;
123144
switch (result.statusCode) {
124145
case 401: // Unauthorized
125146
case 403: { // Forbidden
126-
authenticationSuccess = NO;
147+
isTokenFetchedSuccessful = NO;
127148
break;
128149
}
129150
case 302: { // redirect
@@ -134,17 +155,45 @@ - (BOOL)authenticationTokenWithUsername:(nonnull NSString *)username
134155
NSRange errorStringRange = [location rangeOfString:@"error"];
135156
isErrorRedirect = errorStringRange.length > 0;
136157
}
137-
authenticationSuccess = !result.error && !isErrorRedirect;
158+
isTokenFetchedSuccessful = !result.error && !isErrorRedirect;
138159
break;
139160
}
140161
default: {
141-
authenticationSuccess = (!result.error);
162+
isTokenFetchedSuccessful = (!result.error);
142163
}
143164
}
165+
if (completion) {
166+
completion(isTokenFetchedSuccessful);
167+
}
144168
} @weakselfend];
145169
[self sendRequest:request];
170+
}
171+
172+
- (void)authenticateWithCompletion:(void(^)(BOOL isSuccess))completion
173+
{
174+
NSString *username = self.serverProfile.username;
175+
NSString *password = self.serverProfile.password;
176+
NSString *organization = self.serverProfile.organization;
177+
178+
[self fetchEncryptionKeyWithCompletion:@weakself(^(NSString *modulus, NSString *exponent, NSError *error)) {
179+
NSString *encPassword = password;
180+
if (modulus && exponent) {
181+
JSEncryptionManager *encryptionManager = [JSEncryptionManager managerWithModulus:modulus
182+
exponent:exponent];
183+
encPassword = [encryptionManager encryptText:password];
184+
}
146185

147-
return authenticationSuccess;
186+
[self fetchAuthenticationTokenWithUsername:username
187+
password:encPassword
188+
organization:organization
189+
method:RKRequestMethodPOST // TODO: make select method
190+
completion:@weakself(^(BOOL isTokenFetchedSuccessful)) {
191+
self.restKitObjectManager.requestSerializationMIMEType = RKMIMETypeJSON;
192+
if (completion) {
193+
completion(isTokenFetchedSuccessful);
194+
}
195+
}@weakselfend];
196+
}@weakselfend];
148197
}
149198

150199
@end

Classes/Core/JSRESTBase.m

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,21 @@ - (void)sendRequest:(nonnull JSRequest *)jsRequest additionalHTTPHeaderFields:(n
178178
if (descriptiorHolder && [[descriptiorHolder class] respondsToSelector:@selector(rkRequestDescriptorsForServerProfile:)]) {
179179
[self.restKitObjectManager addRequestDescriptorsFromArray:[[descriptiorHolder class] rkRequestDescriptorsForServerProfile:self.serverProfile]];
180180
}
181-
182-
NSMutableURLRequest *urlRequest = [self.restKitObjectManager requestWithObject:jsRequest.body method:jsRequest.method path:fullUri parameters:jsRequest.params];
183-
181+
182+
NSMutableURLRequest *urlRequest;
183+
if (jsRequest.multipartFormConstructingBodyBlock) {
184+
urlRequest = [self.restKitObjectManager multipartFormRequestWithObject:self
185+
method:jsRequest.method
186+
path:fullUri
187+
parameters:nil
188+
constructingBodyWithBlock:jsRequest.multipartFormConstructingBodyBlock];
189+
} else {
190+
urlRequest = [self.restKitObjectManager requestWithObject:jsRequest.body
191+
method:jsRequest.method
192+
path:fullUri
193+
parameters:jsRequest.params];
194+
}
195+
184196
RKHTTPRequestOperation *httpOperation = [[RKHTTPRequestOperation alloc] initWithRequest:urlRequest];
185197
NSOperation *requestOperation = httpOperation;
186198

Classes/Core/JSRequest.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ typedef enum {
131131
*/
132132
@property (nonatomic, assign) BOOL redirectAllowed;
133133

134+
/**
135+
Allow construct mulpipart body
136+
137+
@since 2.1.2
138+
*/
139+
@property (nonatomic, copy) void(^multipartFormConstructingBodyBlock)(id <AFMultipartFormData> formData);
134140

135141
/**
136142
Returns a request instance with predefined uri.

Classes/Helpers/JSEncryptionManager.m

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ - (NSString *)encryptText:(NSString *)text
6262
{
6363
NSData *publicKeyData = [self generatePublicKeyDataFromModulus:self.modulus exponent:self.exponent];
6464
SecKeyRef publicKeyRef = [self addPublicKeyWithTagName:kJSAuthenticationTag keyBits:publicKeyData];
65-
// There is issue with iOS9 when SecItemCopyMatching() - works wrong.
65+
66+
// There is an issue with iOS9 when SecItemCopyMatching() - works wrong.
6667
if (!publicKeyRef) {
6768
return text;
6869
}
@@ -92,7 +93,6 @@ - (NSData *)generatePublicKeyDataFromModulus:(NSString *)modulus exponent:(NSStr
9293

9394
- (SecKeyRef)addPublicKeyWithTagName:(NSString *)tagName keyBits:(NSData *)publicKey
9495
{
95-
OSStatus sanityCheck = 0;
9696
SecKeyRef peerKeyRef = NULL;
9797
CFTypeRef persistPeer = NULL;
9898

@@ -105,13 +105,11 @@ - (SecKeyRef)addPublicKeyWithTagName:(NSString *)tagName keyBits:(NSData *)publi
105105
peerPublicKeyAttr[(__bridge id) kSecAttrApplicationTag] = peerTag;
106106
peerPublicKeyAttr[(__bridge id) kSecReturnPersistentRef] = @(YES);
107107

108-
sanityCheck = SecItemDelete((__bridge_retained CFDictionaryRef)peerPublicKeyAttr);
109-
// NSLog(@"delete item status: %ld", sanityCheck);
108+
SecItemDelete((__bridge CFDictionaryRef)peerPublicKeyAttr);
110109

111110
peerPublicKeyAttr[(__bridge id) kSecValueData] = publicKey;
112111

113-
sanityCheck = SecItemAdd((__bridge_retained CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&persistPeer);
114-
// NSLog(@"add item status: %ld", sanityCheck);
112+
SecItemAdd((__bridge CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&persistPeer);
115113

116114
if (persistPeer) {
117115
NSMutableDictionary* query = [
@@ -120,14 +118,12 @@ - (SecKeyRef)addPublicKeyWithTagName:(NSString *)tagName keyBits:(NSData *)publi
120118
(__bridge id) kSecReturnRef : @YES
121119
} mutableCopy];
122120

123-
sanityCheck = SecItemCopyMatching((__bridge_retained CFDictionaryRef)query, (CFTypeRef*)&peerKeyRef);
124-
// NSLog(@"copy matching from persistent ref status: %ld", sanityCheck);
121+
SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef*)&peerKeyRef);
125122
} else {
126123
[peerPublicKeyAttr removeObjectForKey:(__bridge id)kSecValueData];
127124
peerPublicKeyAttr[(__bridge id) kSecReturnRef] = @YES;
128125
// Let's retry a different way.
129-
sanityCheck = SecItemCopyMatching((__bridge_retained CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&peerKeyRef);
130-
// NSLog(@"copy matching from tag status: %ld", sanityCheck);
126+
SecItemCopyMatching((__bridge CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&peerKeyRef);
131127
}
132128

133129
if (persistPeer) CFRelease(persistPeer);
@@ -146,6 +142,7 @@ - (NSData *)encryptText:(NSString *)plainTextString withKey:(SecKeyRef)publicKey
146142
&cipherBuffer[0],
147143
&cipherBufferSize);
148144
NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];
145+
free(cipherBuffer);
149146
return encryptedData;
150147
}
151148

@@ -172,7 +169,6 @@ - (NSData *)dataFromString:(NSString *)string
172169
whole_byte = (unsigned char) strtol(byte_chars, NULL, 16);
173170
[result appendBytes:&whole_byte length:1];
174171
}
175-
NSLog(@"%@", result);
176172

177173
return result;
178174
}

Classes/Helpers/KeychainItemWrapper/KeychainItemWrapper.m

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,9 @@ - (id)objectForKey:(id)key
191191
- (void)resetKeychainItem
192192
{
193193
OSStatus junk = noErr;
194-
if (!keychainItemData)
195-
{
196-
self.keychainItemData = [[NSMutableDictionary alloc] init];
197-
}
198-
else if (keychainItemData)
199-
{
194+
if (!keychainItemData) {
195+
keychainItemData = [[NSMutableDictionary alloc] init];
196+
} else {
200197
NSMutableDictionary *tempDictionary = [self dictionaryToSecItemFormat:keychainItemData];
201198
junk = SecItemDelete((CFDictionaryRef)tempDictionary);
202199
NSAssert( junk == noErr || junk == errSecItemNotFound, @"Problem deleting current dictionary." );

0 commit comments

Comments
 (0)