5

I'm not talking about a UIWebView, I want to open the mobile safari app using an NSURLRequest.

Why? In my app, the user has already logged into our web server. I want to give the user the option of launching the webpage without having to reenter their credentials. However, I can't use a GET because that would put their credentials in the URL.

So, can I open the safari app (not a UIWebView) from my app with an NSURLRequest or a POST in some other form?

mtmurdock
  • 12,756
  • 21
  • 65
  • 108
  • 2
    What form of session management are you using? And, for that matter, why is it costly to have a user re-authenticate across credential boundaries? – MrGomez Mar 26 '12 at 22:44
  • I never said it was costly, but the main reason is because that's what our client wants. As for session management, the webservice MVC 3 .NET, and I believe it is just a cookie (which we wouldn't want to send over the url for the same reasons as the password). – mtmurdock Mar 26 '12 at 22:46
  • I see. Ultimately, you have to send some form of a credential over the wire to keep this secure. If you're providing for HTTPS and allow Safari to validate certs properly, I recommend some notion of a session identifier or authentication coupon sent by your client over the wire. Wouldn't this be sufficient? – MrGomez Mar 26 '12 at 22:50
  • I don't understand. You say "the user has already logged into our web server" but "a GET" would "put their credentials in the URL". How did they log in in the first place? Why would a GET expose their credentials? – jsd Mar 26 '12 at 23:54
  • Our system uses a POST to log in, which means the password is sent in the body of the request, not the URL. A GET puts the parameters in the URL, thus making them plain text (and not secure). The app does not have this problem because it can pass secure parameters. However when you open a URL in safari, you can only give them a URL (which is then opened as a GET). – mtmurdock Mar 27 '12 at 20:26
  • @MrGomez How would I send that 'coupon' securely? What would stop anyone from using it to log in? – mtmurdock Mar 27 '12 at 20:28
  • @mtmurdock I think it bears mentioning how HTTP and HTTPS work. By its standard definition, an HTTP `GET` does not limit you from providing additional headers to the request, either by way of the standard header set or by [sensibly named custom headers](http://stackoverflow.com/questions/3561381/custom-http-headers-naming-conventions). Furthermore, in the correct use of HTTPS, your full path is _only exposed to the server over a secure channel_ once TLS negotiation has succeeded. So, there is less risk here than you may be expecting, though MitM is still plausible. – MrGomez Mar 27 '12 at 20:54
  • 2
    @mtmurdock As for login and session coupons: you would need to provide some form of a guarantee that the data being sent by the client and accepted by the server is most likely to be from the requesting party. A robust way to do that would be to provide for some form of [public key authentication](https://en.wikipedia.org/wiki/Public-key_cryptography), such that the mathematical guarantees of your cryptographic functions make it extremely implausible, sans compromise, that someone else is using the connection. – MrGomez Mar 27 '12 at 20:59

2 Answers2

10

I'm going to put my neck on the line and say no — there's no way to pass an NSURLRequest directly to Safari. The (primary) inter-application communication medium on iOS is to access URLs; there's no general mechanism for passing objects from one application to another.

I think the best you're going to be able to do is to fetch a one-time key from your web server in the app, then pop into Safari with that in the URL. And, if you can, do that via HTTPS so that the URL path and query components are only visible once TLS negotiation has succeeded. That should stop anybody else from seeing the relevant credentials and stop them from being useful even if they're obtained by some other means (such as somebody next to you copying the URL from your screen).

MrGomez
  • 23,788
  • 45
  • 72
Tommy
  • 99,986
  • 12
  • 185
  • 204
  • That's an interesting solution. I'm not sure if I can guarente an https connection, but if I can that may work. – mtmurdock Mar 27 '12 at 20:46
  • I'm kind of neutral on this answer. I want to upvote it, but it leaves much of the interesting detail out, vis [how to generate a strong one-time key](https://en.wikipedia.org/wiki/One-time_pad) and the technical details of HTTPS negotiation that guarantee path-shaped credentials aren't leaked to the world. Otherwise, I agree. :) – MrGomez Mar 27 '12 at 21:07
  • @MrGomez it leaves the detail out because my knowledge of the detail is quite imprecise. I've marked the answer as community wiki so hopefully someone nice will be able to fill those bits in? – Tommy Mar 27 '12 at 21:10
  • @Tommy Done. Thanks for allowing me to do that! – MrGomez Mar 27 '12 at 21:16
0

It would be simpler to use an NSURL, or just an NSString, or just a char* for that matter. I'm not sure if that works on the iPhone, it should, since the iPhone runs parallel with Darwin just like OSX, but there are some restrictions to that on the iPhone. This definitely works on a mac though.

NSString *url = @"http://www.apple.com";
NSURL *myURL = [NSURL URLWithString:url];
system([ [NSString 
          stringWithFormat:@"Open -a Safari %@", 
          [NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:NULL] ]
          cStringUsingEncoding:NSUTF8StringEncoding]);

Also, I might suggest that that's a bad idea (if it might be avoided). As an iPhone user, I'm sure I'm not alone in finding it very irritating when developers take me away from the app I'm currently in.

Michael Dorst
  • 8,210
  • 11
  • 44
  • 71
  • Rereading your question, I think I may have misunderstood it. Sorry for the useless answer. – Michael Dorst Mar 26 '12 at 23:16
  • 1
    On an iPhone you'd use `[[UIApplication sharedApplication] openURL:myURL]` rather than making a system call to open. You'll get Safari as per Apple's rules on third parties duplicating built-in functionality, so it's basically the same as `[[NSWorkspace sharedWorkspace] openURL:myURL]` on OS X except that you can be confident you'll get Safari, as the originating poster stipulated. – Tommy Mar 26 '12 at 23:18
  • Good to know, thanks. I'm new to this site, I'm wondering if I should delete this post or leave as is? – Michael Dorst Mar 26 '12 at 23:21
  • Dafuq?! Mind I suggest to read more about `NSWorkspace` and/or `UIApplication`? Your code is like driving a tank mounted to a rocket which itself is mounted on a large spaceship into your best friends house instead of just ringing the doorbell. Edit: Damn, too much time spend on exaggerations... – JustSid Mar 26 '12 at 23:21
  • What exactly might go wrong with this code? To my knowledge, calling to the system is fairly safe, as any errors do nothing and pass harmlessly, am I wrong? Why overcomplicate the space? – Michael Dorst Mar 26 '12 at 23:27
  • 1
    @MichaelDorst it is up to you if you want to delete the answer. Sometimes wrong answers help add to the overall body of knowledge, and sometimes they are distracting. Also, I think that JustSid is referring to your coding style, not the accuracy of the code. Whenever you post anything on this site, you will want to make sure it is as clean and clear (and accurate) as possible without adding any extraneous details. Thanks for your contributions! :D – mtmurdock Mar 27 '12 at 20:31