-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added Token Based Reconnection and everything is tested
- Loading branch information
Andres Canal
committed
Jul 11, 2016
1 parent
c5ab86f
commit 8ffcfca
Showing
12 changed files
with
506 additions
and
1 deletion.
There are no files selected for viewing
17 changes: 17 additions & 0 deletions
17
Authentication/Token-Based-Reconnection/XMPPStream+XMPPTBRAuthentication.h
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// XMPPStream+XMPPTBRAuthentication.h | ||
// XMPPFramework | ||
// | ||
// Created by Andres Canal on 7/6/16. | ||
// Copyright © 2016 Inaka. All rights reserved. | ||
// | ||
|
||
#import "XMPPFramework.h" | ||
#import "XMPPStream.h" | ||
|
||
@interface XMPPStream (XMPPTBRAuthentication) | ||
|
||
- (BOOL)authenticateWithTBR:(NSString *)authToken error:(NSError **)errPtr; | ||
- (BOOL)supportsTBRAuthentication; | ||
|
||
@end |
53 changes: 53 additions & 0 deletions
53
Authentication/Token-Based-Reconnection/XMPPStream+XMPPTBRAuthentication.m
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// | ||
// XMPPStream+XMPPTBRAuthentication.m | ||
// XMPPFramework | ||
// | ||
// Created by Andres Canal on 7/6/16. | ||
// Copyright © 2016 Inaka. All rights reserved. | ||
// | ||
|
||
#import "XMPPStream+XMPPTBRAuthentication.h" | ||
#import "XMPPTBRAuthentication.h" | ||
#import "XMPPInternal.h" | ||
|
||
@implementation XMPPStream (TBRAuthentication) | ||
|
||
- (BOOL)supportsTBRAuthentication{ | ||
return [self supportsAuthenticationMechanism:[XMPPTBRAuthentication mechanismName]]; | ||
} | ||
|
||
- (BOOL)authenticateWithTBR:(nonnull NSString *)authToken error:(NSError **)errPtr { | ||
|
||
__block BOOL result = YES; | ||
__block NSError *err = nil; | ||
|
||
dispatch_block_t block = ^{ @autoreleasepool { | ||
|
||
if ([self supportsTBRAuthentication]) { | ||
|
||
XMPPTBRAuthentication *tbrAuthentication = [[XMPPTBRAuthentication alloc] initWithStream:self | ||
token:authToken]; | ||
|
||
result = [self authenticate:tbrAuthentication error:&err]; | ||
} else { | ||
NSString *errMsg = @"The server does not support Token-based reconnection."; | ||
NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; | ||
|
||
err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info]; | ||
|
||
result = NO; | ||
} | ||
}}; | ||
|
||
if (dispatch_get_specific(self.xmppQueueTag)) | ||
block(); | ||
else | ||
dispatch_sync(self.xmppQueue, block); | ||
|
||
if (errPtr) | ||
*errPtr = err; | ||
|
||
return result; | ||
} | ||
|
||
@end |
17 changes: 17 additions & 0 deletions
17
Authentication/Token-Based-Reconnection/XMPPTBRAuthentication.h
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// XMPPTBRAuthentication.h | ||
// XMPPFramework | ||
// | ||
// Created by Andres Canal on 7/6/16. | ||
// Copyright © 2016 Inaka. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
#import "XMPPSASLAuthentication.h" | ||
#import "XMPPStream.h" | ||
|
||
@interface XMPPTBRAuthentication : NSObject <XMPPSASLAuthentication> | ||
|
||
- (nonnull instancetype)initWithStream:(nonnull XMPPStream *)stream token:(nonnull NSString *)aToken; | ||
|
||
@end |
71 changes: 71 additions & 0 deletions
71
Authentication/Token-Based-Reconnection/XMPPTBRAuthentication.m
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// | ||
// XMPPTBRAuthentication.m | ||
// XMPPFramework | ||
// | ||
// Created by Andres Canal on 7/6/16. | ||
// Copyright © 2016 Inaka. All rights reserved. | ||
// | ||
|
||
#import "XMPPTBRAuthentication.h" | ||
#import "XMPPInternal.h" | ||
#import "NSXMLElement+XMPP.h" | ||
|
||
@implementation XMPPTBRAuthentication { | ||
#if __has_feature(objc_arc_weak) | ||
__weak XMPPStream *xmppStream; | ||
#else | ||
__unsafe_unretained XMPPStream *xmppStream; | ||
#endif | ||
NSString *authToken; | ||
} | ||
|
||
+ (NSString *)mechanismName { | ||
return @"X-OAUTH"; | ||
} | ||
|
||
- (id)initWithStream:(nonnull XMPPStream *)stream password:(nonnull NSString *)password { | ||
return [super init]; | ||
} | ||
|
||
- (id)initWithStream:(nonnull XMPPStream *)stream token:(nonnull NSString *)aToken { | ||
if( self = [super init]) { | ||
xmppStream = stream; | ||
authToken = aToken; | ||
} | ||
|
||
return self; | ||
} | ||
|
||
- (BOOL)start:(NSError **)errPtr { | ||
|
||
if(!authToken) { | ||
NSString *errMsg = @"Missing auth token."; | ||
NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; | ||
|
||
NSError *err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidParameter userInfo:info]; | ||
|
||
if (errPtr) *errPtr = err; | ||
return NO; | ||
} | ||
|
||
// <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="X-OAUTH">auth_token</auth> | ||
|
||
NSXMLElement *auth = [NSXMLElement elementWithName:@"auth" xmlns:@"urn:ietf:params:xml:ns:xmpp-sasl"]; | ||
[auth addAttributeWithName:@"mechanism" stringValue:@"X-OAUTH"]; | ||
auth.stringValue = authToken; | ||
|
||
[xmppStream sendAuthElement:auth]; | ||
|
||
return true; | ||
} | ||
|
||
- (XMPPHandleAuthResponse)handleAuth:(NSXMLElement *)auth { | ||
|
||
if ([[auth name] isEqualToString:@"success"]) { | ||
return XMPP_AUTH_SUCCESS; | ||
} | ||
|
||
return XMPP_AUTH_FAIL; | ||
} | ||
|
||
@end |
21 changes: 21 additions & 0 deletions
21
Authentication/Token-Based-Reconnection/XMPPTBReconnection.h
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// | ||
// XMPPTBReconnection.h | ||
// XMPPFramework | ||
// | ||
// Created by Andres Canal on 7/5/16. | ||
// Copyright © 2016 Inaka. All rights reserved. | ||
// | ||
|
||
#import "XMPPFramework.h" | ||
#import "XMPPIDTracker.h" | ||
|
||
@interface XMPPTBReconnection : XMPPModule { | ||
XMPPIDTracker *responseTracker; | ||
} | ||
- (void) getAuthToken; | ||
@end | ||
|
||
@protocol XMPPTBReconnectionDelegate | ||
- (void)xmppTBReconnection:(nonnull XMPPTBReconnection *)sender didReceiveToken:(nonnull NSDictionary<NSString *, NSString *> *) token; | ||
- (void)xmppTBReconnection:(nonnull XMPPTBReconnection *)sender didFailToReceiveToken:(nonnull XMPPIQ *)iq; | ||
@end |
81 changes: 81 additions & 0 deletions
81
Authentication/Token-Based-Reconnection/XMPPTBReconnection.m
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// | ||
// XMPPTBReconnection.m | ||
// XMPPFramework | ||
// | ||
// Created by Andres Canal on 7/5/16. | ||
// Copyright © 2016 Inaka. All rights reserved. | ||
// | ||
|
||
#import "XMPPTBReconnection.h" | ||
#import "XMPPFramework.h" | ||
#import "XMPPIQ.h" | ||
|
||
@implementation XMPPTBReconnection | ||
|
||
- (void) getAuthToken { | ||
// <iq from='crone1@shakespeare.lit/desktop' | ||
// id='create1' | ||
// to='coven@muclight.shakespeare.lit' | ||
// type='get'> | ||
// <query xmlns='erlang-solutions.com:xmpp:token-auth:0'/> | ||
// </iq> | ||
|
||
dispatch_block_t block = ^{ @autoreleasepool { | ||
|
||
NSString *iqID = [XMPPStream generateUUID]; | ||
NSXMLElement *iq = [NSXMLElement elementWithName:@"iq"]; | ||
[iq addAttributeWithName:@"id" stringValue:iqID]; | ||
[iq addAttributeWithName:@"to" stringValue:self.xmppStream.myJID.full]; | ||
[iq addAttributeWithName:@"type" stringValue:@"get"]; | ||
|
||
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"erlang-solutions.com:xmpp:token-auth:0"]; | ||
[iq addChild:query]; | ||
|
||
[responseTracker addID:iqID | ||
target:self | ||
selector:@selector(handleGetAuthToken:withInfo:) | ||
timeout:60.0]; | ||
|
||
[xmppStream sendElement:iq]; | ||
}}; | ||
|
||
if (dispatch_get_specific(moduleQueueTag)) | ||
block(); | ||
else | ||
dispatch_async(moduleQueue, block); | ||
} | ||
|
||
- (void)handleGetAuthToken:(XMPPIQ *)iq withInfo:(id <XMPPTrackingInfo>)info { | ||
if ([[iq type] isEqualToString:@"result"]){ | ||
NSXMLElement *items = [iq elementForName:@"items"]; | ||
|
||
NSMutableDictionary *tokensDictionary = [[NSMutableDictionary alloc] init]; | ||
for (NSXMLElement *element in items.children) { | ||
tokensDictionary[element.name] = element.stringValue; | ||
} | ||
[multicastDelegate xmppTBReconnection:self didReceiveToken:tokensDictionary]; | ||
}else{ | ||
[multicastDelegate xmppTBReconnection:self didFailToReceiveToken:iq]; | ||
} | ||
} | ||
|
||
- (BOOL)activate:(XMPPStream *)aXmppStream { | ||
if ([super activate:aXmppStream]){ | ||
responseTracker = [[XMPPIDTracker alloc] initWithDispatchQueue:moduleQueue]; | ||
|
||
return YES; | ||
} | ||
return NO; | ||
} | ||
|
||
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq { | ||
NSString *type = [iq type]; | ||
if ([type isEqualToString:@"result"] || [type isEqualToString:@"error"]){ | ||
return [responseTracker invokeForID:[iq elementID] withObject:iq]; | ||
} | ||
|
||
return NO; | ||
} | ||
|
||
|
||
@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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// | ||
// XMPPTBRAuthenticationTests.m | ||
// XMPPFrameworkTests | ||
// | ||
// Created by Andres Canal on 7/6/16. | ||
// | ||
// | ||
|
||
#import <XCTest/XCTest.h> | ||
#import "XMPPMockStream.h" | ||
#import "XMPPTBReconnection.h" | ||
#import "XMPPTBRAuthentication.h" | ||
#import "XMPPJID.h" | ||
#import "XMPPStream+XMPPTBRAuthentication.h" | ||
|
||
@interface XMPPTBRAuthenticationTests : XCTestCase <XMPPStreamDelegate> | ||
@property (nonatomic, strong) XCTestExpectation *delegateExpectation; | ||
@end | ||
|
||
@implementation XMPPTBRAuthenticationTests | ||
|
||
- (void)testTBRNotSupported { | ||
NSError *error; | ||
|
||
XMPPMockStream *streamTest = [[XMPPMockStream alloc] init]; | ||
streamTest.supportsTBR = NO; | ||
[streamTest authenticateWithTBR:@"token-token-token" error:&error]; | ||
|
||
XCTAssertEqualObjects(error.domain, XMPPStreamErrorDomain); | ||
XCTAssertEqual(error.code, XMPPStreamUnsupportedAction); | ||
XCTAssertEqualObjects(error.userInfo[NSLocalizedDescriptionKey], @"The server does not support Token-based reconnection."); | ||
} | ||
|
||
- (void)testSuccessTBR { | ||
self.delegateExpectation = [self expectationWithDescription:@"TBR expectation"]; | ||
|
||
XMPPMockStream *streamTest = [[XMPPMockStream alloc] init]; | ||
streamTest.supportsTBR = YES; | ||
streamTest.myJID = [XMPPJID jidWithString:@"andres@test.com"]; | ||
|
||
streamTest.elementReceived = ^void(NSXMLElement *element) { | ||
XCTAssertEqualObjects(element.name, @"auth"); | ||
XCTAssertEqualObjects([element attributeForName:@"mechanism"].stringValue, @"X-OAUTH"); | ||
XCTAssertEqualObjects(element.stringValue, @"token-token-token"); | ||
|
||
[self.delegateExpectation fulfill]; | ||
}; | ||
|
||
[streamTest authenticateWithTBR:@"token-token-token" error:nil]; | ||
|
||
[self waitForExpectationsWithTimeout:5 handler:^(NSError * _Nullable error) { | ||
if(error){ | ||
XCTFail(@"Expectation Failed with error: %@", error); | ||
} | ||
}]; | ||
} | ||
|
||
- (void)testFailureHandleAuth { | ||
XMPPMockStream *streamTest = [[XMPPMockStream alloc] init]; | ||
XMPPTBRAuthentication *auth = [[XMPPTBRAuthentication alloc] initWithStream:streamTest token:@"test"]; | ||
|
||
NSXMLElement *failureElement = [NSXMLElement elementWithName:@"failure" xmlns:@"urn:ietf:params:xml:ns:xmpp-sasl"]; | ||
NSXMLElement *notAuthorized = [NSXMLElement elementWithName:@"not-authorized"]; | ||
[failureElement addChild:notAuthorized]; | ||
|
||
XCTAssertEqual([auth handleAuth:failureElement], XMPP_AUTH_FAIL); | ||
} | ||
|
||
- (void)testSuccessHandleAuth { | ||
XMPPMockStream *streamTest = [[XMPPMockStream alloc] init]; | ||
XMPPTBRAuthentication *auth = [[XMPPTBRAuthentication alloc] initWithStream:streamTest token:@"test"]; | ||
|
||
NSXMLElement *successElement = [NSXMLElement elementWithName:@"success" xmlns:@"urn:ietf:params:xml:ns:xmpp-sasl"]; | ||
XCTAssertEqual([auth handleAuth:successElement], XMPP_AUTH_SUCCESS); | ||
} | ||
|
||
@end |
Oops, something went wrong.