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

Refactoring and creds memoization with the original code formatting #9

Closed
wants to merge 8 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ @interface ViewController () <JAHPAuthenticatingHTTPProtocolDelegate, UIAlertVie
@property (nonatomic, strong) UIAlertView *authAlertView;
@property (nonatomic, strong) JAHPAuthenticatingHTTPProtocol *authenticatingHTTPProtocol;

@property (nonatomic, strong) NSURLCredential* userInput;

@end

@implementation ViewController
Expand All @@ -28,13 +30,25 @@ - (void)viewDidLoad {
[JAHPAuthenticatingHTTPProtocol setDelegate:self];
[JAHPAuthenticatingHTTPProtocol start];
self.webView.delegate = self;
[self.webView loadRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://httpbin.org/basic-auth/foo/bar"]]];
[self.webView loadRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://httpbin.org/basic-auth/foo/bar"]]];
}

#pragma mark - JAHPAuthenticatingHTTPProtocolDelegate

- (BOOL)authenticatingHTTPProtocol:(JAHPAuthenticatingHTTPProtocol *)authenticatingHTTPProtocol canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
BOOL canAuthenticate = [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic];

NSArray* interceptedAuthMethods =
@[
NSURLAuthenticationMethodHTTPBasic
, NSURLAuthenticationMethodHTTPDigest
, NSURLAuthenticationMethodNTLM
];

NSSet* interceptedAuthMethodsSet = [NSSet setWithArray: interceptedAuthMethods];

BOOL canAuthenticate =
[interceptedAuthMethodsSet containsObject: protectionSpace.authenticationMethod];

return canAuthenticate;
}

Expand All @@ -44,6 +58,13 @@ - (BOOL)authenticatingHTTPProtocol:(JAHPAuthenticatingHTTPProtocol *)authenticat
- (JAHPDidCancelAuthenticationChallengeHandler)authenticatingHTTPProtocol:(JAHPAuthenticatingHTTPProtocol *)authenticatingHTTPProtocol didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
self.authenticatingHTTPProtocol = authenticatingHTTPProtocol;

if (nil != self.userInput) {

[self passCredentialsInputToConnection];
return;
}


self.authAlertView = [[UIAlertView alloc] initWithTitle:@"JAHPDemo"
message:@"Enter 'foo' for the username and 'bar' for the password"
delegate:self
Expand All @@ -70,8 +91,35 @@ - (void)authenticatingHTTPProtocol:(JAHPAuthenticatingHTTPProtocol *)authenticat
}
#else
- (JAHPDidCancelAuthenticationChallengeHandler)authenticatingHTTPProtocol:(JAHPAuthenticatingHTTPProtocol *)authenticatingHTTPProtocol didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {

__weak ViewController* weakSelf = self;
self.authenticatingHTTPProtocol = authenticatingHTTPProtocol;


JAHPDidCancelAuthenticationChallengeHandler result =
^(JAHPAuthenticatingHTTPProtocol *authenticatingHTTPProtocol, NSURLAuthenticationChallenge *challenge) {
ViewController* strongSelf = weakSelf;

[strongSelf.authAlertView dismissWithClickedButtonIndex:strongSelf.authAlertView.cancelButtonIndex
animated:YES];
strongSelf.authAlertView = nil;
strongSelf.authenticatingHTTPProtocol = nil;

[[[UIAlertView alloc] initWithTitle:@"JAHPDemo"
message:@"The URL Loading System cancelled authentication"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil] show];
};



if (nil != self.userInput) {

[self passCredentialsInputToConnection];
return result;
}

self.authAlertView = [[UIAlertView alloc] initWithTitle:@"JAHPDemo"
message:@"Enter 'foo' for the username and 'bar' for the password"
delegate:self
Expand All @@ -82,24 +130,18 @@ - (JAHPDidCancelAuthenticationChallengeHandler)authenticatingHTTPProtocol:(JAHPA
self.authAlertView.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
[self.authAlertView show];

return ^(JAHPAuthenticatingHTTPProtocol *authenticatingHTTPProtocol, NSURLAuthenticationChallenge *challenge) {
[self.authAlertView dismissWithClickedButtonIndex:self.authAlertView.cancelButtonIndex
animated:YES];
self.authAlertView = nil;
self.authenticatingHTTPProtocol = nil;

[[[UIAlertView alloc] initWithTitle:@"JAHPDemo"
message:@"The URL Loading System cancelled authentication"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil] show];
};
return result;
}
#endif

- (void)authenticatingHTTPProtocol:(JAHPAuthenticatingHTTPProtocol *)authenticatingHTTPProtocol logWithFormat:(NSString *)format arguments:(va_list)arguments {
NSLog(@"logWithFormat: %@", [[NSString alloc] initWithFormat:format arguments:arguments]);
}

// It's ok to not overload this method.
// Then all logs will go to the `authenticatingHTTPProtocol:logMessage:` method
//
//- (void)authenticatingHTTPProtocol:(JAHPAuthenticatingHTTPProtocol *)authenticatingHTTPProtocol logWithFormat:(NSString *)format arguments:(va_list)arguments {
//
// NSLog(@"logWithFormat: %@", [[NSString alloc] initWithFormat:format arguments:arguments]);
//}

- (void)authenticatingHTTPProtocol:(JAHPAuthenticatingHTTPProtocol *)authenticatingHTTPProtocol logMessage:(NSString *)message {
NSLog(@"logMessage: %@", message);
Expand Down Expand Up @@ -144,7 +186,18 @@ - (void)useAuthAlertViewUsernamePasswordForChallenge {
NSURLCredential *credential = [NSURLCredential credentialWithUser:username
password:password
persistence:NSURLCredentialPersistenceNone];
[self.authenticatingHTTPProtocol resolvePendingAuthenticationChallengeWithCredential:credential];
self.userInput = credential;


[self passCredentialsInputToConnection];
}

-(void)passCredentialsInputToConnection {

NSParameterAssert(nil != self.userInput);
NSParameterAssert(nil != self.authenticatingHTTPProtocol);

[self.authenticatingHTTPProtocol resolvePendingAuthenticationChallengeWithCredential:self.userInput];
self.authenticatingHTTPProtocol = nil;
}

Expand Down
59 changes: 57 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,66 @@ JiveAuthenticatingHTTPProtocol
Based on [Apple's CustomHTTPProtocol](https://developer.apple.com/library/prerelease/ios/samplecode/CustomHTTPProtocol/Introduction/Intro.html),
`JiveAuthenticatingHTTPProtocol` provides authentication callbacks for a `UIWebView`.

#### Note :

```
No cleanup of the sample code has been done, so there might be some strange "patterns" inside.
```

See https://github.com/jivesoftware/JiveAuthenticatingHTTPProtocol/issues/3 for more details.


Usage
-----
`JiveAuthenticatingHTTPProtocol` captures all `NSURLConnection` traffic. Ensure that no other `NSURLConnection`s can start after you call `+[JAHPAuthenticatingHTTPProtocol start]`. Before loading an `NSURLRequest` that may require handling an authentication callback, call `+[JAHPAuthenticatingHTTPProtocol setDelegate:]`, then `+[JAHPAuthenticatingHTTPProtocol start]`. Finally, load your `NSURLRequest`, and handle the callbacks from `JAHPAuthenticatingHTTPProtocolDelegate`.
`JiveAuthenticatingHTTPProtocol` captures all `NSURLConnection` traffic.

1. Ensure that no other `NSURLConnection`s can start after you call `+[JAHPAuthenticatingHTTPProtocol start]`.
2. Before loading an `NSURLRequest` that may require handling an authentication callback, call `+[JAHPAuthenticatingHTTPProtocol setDelegate:]`,
3. Then call `+[JAHPAuthenticatingHTTPProtocol start]`.
4. Finally, load your `NSURLRequest`, and handle the callbacks from `JAHPAuthenticatingHTTPProtocolDelegate`.

See `JiveAuthenticatingHTTPProtocolDemo/ViewController.m` for an example.

It might be a good idea to memoize the credentials entered by the user to avoid "spamming" them with the data input alerts. This is an absolute "must" if your page contains the video which requires authorization.



Supported Authorization Methods
-----
This library supports all of the authentication schemes `NSURLAuthentication` supports.

This has been tested with `NTLM` and `ADFS` authentication, (which `NSURLAuthentication` natively supports). Basically, if an authentication method works in `Safari`, it'll probably work here, too.

You can add more authorization methods like this :

```obj-c
- (BOOL)authenticatingHTTPProtocol:(JAHPAuthenticatingHTTPProtocol *)authenticatingHTTPProtocol
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
NSArray* interceptedAuthMethods =
@[
NSURLAuthenticationMethodHTTPBasic
, NSURLAuthenticationMethodNTLM
];

NSSet* interceptedAuthMethodsSet = [NSSet setWithArray: interceptedAuthMethods];

BOOL canAuthenticate =
[interceptedAuthMethodsSet containsObject: protectionSpace.authenticationMethod];

return canAuthenticate;
}
```


#### Caution :

```
Stubbing the above function to always return "true" is not always a good idea.
If you do so, it would be your responsibility to implement all the required handshakes.
```


See JiveAuthenticatingHTTPProtocolDemo/ViewController.m for an example.

License
-------
Expand Down
Loading