Add support for invalid/untrusted SSL certificates (for debugging) #204
Add support for invalid/untrusted SSL certificates (for debugging) #204
Conversation
…FNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES_ is set. This is useful if you debug on custom servers in SSL mode, or just want to use Charles to capture the packets in SSL. It's only a minor change and doesn't get compiled if the constant is not set.
There are some other ways to achieve that with private API, but this solution only uses public API. (It just really shouldn't be enabled in a release build) |
I might be misunderstanding the purpose of the authentication block. I thought @mattt added that specifically for this case in mind. I would be really interested to hear his feedback on this issue because I occasionally run into the bad cert issue with a development server, but haven't tried to solve the problem in any of my AF projects yet. I imagined some sort of implementation like this in your - (AFHTTPRequestOperation*)HTTPRequestOperationWithRequest:(NSURLRequest *)request success:(void (^)(AFHTTPRequestOperation *, id))success failure:(void (^)(AFHTTPRequestOperation *, NSError *))failure{
AFHTTPRequestOperation * operation = [super HTTPRequestOperationWithRequest:request success:success failure:failure];
#ifdef DEBUG
[operation setAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
}];
#endif
return operation;
}; |
Without also overriding canAuthenticateAgainstProtectionSpace, the authentication challenge is never called. So while I could use this block, i'd still need to override/monkey patch AFURLConnectionOperation. |
Ah gotcha. Missed that. I think the best solution would be doing it without requiring a AF level #define to do it. I know ASI had a property you simply set to ON. |
I'm really not sure what the best practice on this is - I feel the default setup (protecting you from man in the middle attacks etc) and this not even calling the auth-code is the best way of handling it - this protects you from possible mistakes on the actual auth challenge. I really just want a solution that is (like in my app) automatically enabled in DEBUG but doesn't even get compiled into a release build. |
I had planned to add another block property to intercept that protection space delegate method (maybe roll into the other auth method) for 0.9, but (and this is a pretty dumb reason) I couldn't figure out a good name for any of that. A block is the right solution for the same reasons it works for the can authenticate method. If anyone has any opinions about how to package that up, I'm all ears. On 2012/02/08, at 16:15, Peter Steinbergerreply@reply.github.com wrote:
|
Well, we could name it canAuthenticateBlock(NSURLProtectionSpace * protectionSpace) because it returns a BOOL. Still, I would love to have sth like AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES in the codebase as I'm sure there are more developers that will need this, and it's a lot easier to just set this define than adding blocks (again, those blocks may be already used for custom auth on some properties, so we would need additional logic) and also the devs first would need to look up how you allow invalid SSL certs in the first place. The code needed e.g. "[protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];" is not obvious at all. |
Would it make sense to have a BOOL property like ASI had, that encapsulated the logic needed to allow invalid SSL certs, while also still potentially exposing blocks for people to do more advanced things with the call backs? It could be modeled after the @steipete Is the code not even getting compiled into the app a deal breaker for you? I feel like surrounding the code that sets the flag to YES with a #ifdef DEBUG would be sufficient. |
I took an (untested) pass here at a potential implementation: The one issue to look at is the case of when a canAuthenticateProtectionSpace block is set AND the allowsInvalidSSLCertificates is set to YES. Currently the block gets ignored, and the logic used to handle invalid SSL certs is run, but perhaps that is backwards? Any comments on the implementation would be great. EDIT: Doh realized I misread the docs on canAuthenticateProtectionSpace callback. This checkin should bring that implementation in line with the expected behavior. |
@kcharwood looks good to me! I don't really care that much if it gets compiled or not - as long as the default is NO it's ok. A property is even more visible to new developers, so +1 on that. |
Cool. I also couldn't come up with a good name, so maybe that changes as well. Be interested to hear @mattt's thoughts. Would be happy to update that with better names if anyone has options before submitting a pull for it. |
Just a thought on accepting invalid certificates: I think the most clean way (for a production app, not what @steipete wants to do) would be to present a "Trust this server?" dialog to the user. Once the server is trusted this will not appear again, until the certificate changes. This way you could connect to servers with untrusted certificates (necessary in my app) but also hint the user when something strange is happening. Is this something that should be considered for AFNetworking or should it be done in each app individually? |
+1 for the option to ignore invalid certificates It would be useful for testing against test-servers with self-signed certificates, and in one of our apps we need it to integrate with some of our customers who (unfortunately) are still using self-signed certificates for a couple of servers. |
@Shukuyen - I think 'clean' is a relative term. In your approach we'll need to pop a localized Alert View and persist the response locally about a particular certificate. I am guessing that is something that @mattt would probably be against (but I could be wrong!) Your approach sounds like something that may be best done in the individual application. I think the use case most people have here is in a dev environment with a self signed cert that is not going to be used in production code. |
Great contributions, @steipete & @kcharwood! I just pushed 17f5584, which borrows from both approaches to make what I think is a solid feature. First, this commit adds Secondly, this commit also adds Thanks again, everyone! |
@mattt thanks for getting this pulled in! I had a comment I wanted to make on the implementation. Since If we choose to go the property route, we can specify which API should allow invalid SSL certs, while also making sure that other API's correctly fail if they run into an invalid SSL. One more comment on my approach I made above - I added a property to I'll reopen the issue just to get feedback on this comment. If @mattt feels this corner case isn't worth solving, then go ahead and close out again. EDIT: Doh I don't have permission to reopen :( |
@kcharwood I appreciate your concern about this issue. The compromise of a compiler macro essentially offers two modes: regular mode, and "F it, I just want it to work right now while I'm developing". In the case that someone interacts with two APIs, developing in "F it" mode for both is alright, and each can eventually set their own auth blocks for the real implementation. That is to say, what is accomplished by the macro can be replicated by simply setting the correct auth block. For the sake of simplicity, I prefer to keep as many properties about operations configured in |
Hi neither of these defines work for me. What Im I missing? Should these defines be in a certain file? #define AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES Thanks in advance |
@idennis try putting it in your AppName-Prefix.pch like so:
|
Thanks! |
Hmm, not working for me, even when I define the flag in my prefix file. Any other gotchas? EDIT: For the record, my problem was that I have AFNetworking installed through CocoaPods, so setting the variable in my project's prefix file didn't do the trick. I needed to set it in CocoaPods' prefix file, instead. |
... if the constant AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES is set.
This is useful if you debug on custom servers in SSL mode, or just want to use Charles to capture the packets in SSL. It's only a minor change and doesn't get compiled if the constant is not set.