Launching a URL in Safari is easy enough in an iPhone application - UIApplication's openURL method.
However, I'm doing some OAuth stuff, and want to follow the pattern that pownce used to handle OAuth. But since OAuth wants me to explicitly set the Authorization header, I don't know how to proceed. I can set headers via NSMutableURLRequest... but how does that translate into creating an NSURL that my app can pass to the UIApplication method?
During server to server interactions the recommended method of passing OAuth parameters from the Consumer to the Service Provider is using the HTTP Authorization header. But when the user is redirected by the Consumer to the Service Provider OAuth actually specifies that an HTTP GET request should be used (see section 6.2.1, I can't link b/c I'm a new user and can only post one hyperlink -- very annoying StackOverflow). So there's no need to pass an NSURLRequest off to mobile safari, simply open the URL as you described.
If you're interested in seeing a code example of the full OAuth flow on the iPhone feel free to check out the sample FireEagle app I wrote. It was implemented in much the same way the Pownce app was.
From what I've seen, the usual way to implement OAuth support in an iPhone application is to present a modal sheet with a webview in it. This allows you to use an NSURLRequest with custom headers.
Related
I'm a beginner developer. I am writing an iOS application using Flutter. I need to use an API to identify my user. The provider of that API asks me to send them a redirect URL. From what I understand, when an user identify themselves on my app, a request will be send to the API provider, and once the user is correctly identified, the API provider want to know where to send the user (the redirect URL). But I want the user to stay on my app.
How should I set up that ?
Thanks
The usual way to implement this is via the AppAuth pattern, where the app invokes an ASWebAuthenticationSession window, which is a secure browser. From a UX viewpoint it looks integrated and remains a part of the app.
As a next step, maybe have a look at my iOS AppAuth Basic Tutorial to see what this looks like. The simplest option is a private URI scheme based redirect URL that looks like this:
net.openid.appauthdemo:/oauth2redirect
Once the concepts are understood, and your team has reviewed the user experience etc, the next step would be to implement this behaviour in Flutter.
I have an application that may access authenticated content. I know that the webview can't handle authentication so I do some NSConnection magic to make it work (something similar to this)
The thing is that there is some content that can be accessible using this web view, but there is some other content that event after a sucessfull authentication, the web view is not able to load.
BUT.. if I enter the same url with mobile safari, enter the needed credentials and then I go back to my app, the WebView seems to load the content fine.
I tried reviewing the cookies before and after the auth in Safari is done using this code
[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
and the cookies are the same.
As far as I understand that code will retrieve the cookies my app generates and not the ones available in iOS, so apparently this is not the way to look for a hint...
Any ideas?
Recently, i've lurked for the same question over the internet, and the answer is "no" =(.
Objects of UIWebView class and Safari or other browsers live apart and are sandboxed.
Here is official position about cookies.
TO the best of my understanding, Cookies can not be sent with the first request from a Webview, but can be sent with subsequent requests to the same URL, if and only if, the first request was successful.
This causes problems with authentication services that require cookies to authenticate on the first request to the URL.
Possibly user credentials are stored via keychain api. Keychain is shared between apps, so stored login/pass in Safari can appear in your app UIWebView.Can you elaborate this as i also need this.
I am building a mobile app with jQueryMobile and I intend to deploy it onto iPhone thanks to PhoneGap.
My question is : how can I authenticate myself with Foursquare using the OAuth2 protocol in my jQueryMobile app ? One solution would be to use the useragent flow of OAuth2 but this would force the iPhone to launch Safari and thus not stay within the app. Are there any better solutions than this ?
For an iPhone-based or client-side application like you would have in PhoneGap,
Foursquare recommends one of these methods.
If you have no substantive server code, you can embed a web browser and use the token flow, redirecting the user to a dummy page on your domain. You can then grab the token off of the URL and close the browser. We have sample Android and iOS code for your reference.
If you have a server as part of your application, you can use the server flow above, possibly in an embedded browser. Similar to the Facebook API, you can add display=touch to your authorize or authenticate URLs to get a mobile optimized interface.
An alternative to the above is to use the server flow and an external browser, but redirect to a custom URI handler that brings the user back to our application. You can embed the secret in your application and exchange the provided code for an access token. PLEASE take steps to obfuscate your client secret if you include it in released code, and be prepared to rotate it if needed.
https://developer.foursquare.com/docs/oauth.html
This could probably be handled with the ClientBrowser plugin for PhoneGap or just adapting the sample code they have provided into PhoneGap plugins.
One of the core intentions of OAuth2 is to not allow browserless authentication flow like we did with XAuth in the past. Service providers want consumers to see what permissions they are signing off on, and want control of that process.
I'm not very experienced with Phonegap, as I'm a native developer, but if there's a way of instantiating a UIWebView and showing it to the user, you could at least keep the web interaction 'inside' of the application. Given phonegap is basically showing a UIWebView this should be possible. It is possible to examine the source of the html within a UIWebView using
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
I made an application that uses UIWebView to display a site that uses basic authentication. It stopped displaying the content since iOS3.2 (on both iPhone and iPad).
My approach for authenticating users are:
create a NSURLConnection
implement didReceiveAuthenticationChallenge to provide the credential
implement didReceiveResponse to receive the response and load the request in a UIWebView, i.e. [webView loadRequest:]
Ever since iOS3.2, the authentication was broken; UIWebView doesn't seem to check against the shared credential storage any more.
For iOS4 on iPhone, I managed to work around this issue by, stupidly, including the login informatino in the URL (i.e. https://username:password#www.somesite.com) to the initial load request passed to the webView.
For iOS3.2 on iPad, that isn't enough. The initial request is authenticated all right, but the subsequent calls still aren't authenticated.
Any suggestions?
Use setDefaultCredential:forProtectionSpace: on the shared NSURLCredentialStorage
the Webview still uses the default credential, it does not work when you use setCredential:forProtectionSpace.
I'm working on an iPhone app that ideally uses OAuth to communicate with Twitter. I know a lot of people are doing the OAuth workflow inside of their apps using a UIWebView, but I don't agree with that and am going with the Pownce approach.
The problem is, Twitter has this whole scheme for working with desktop apps, using a pin number. When I register my app with Twitter, they have a web form asking me if I'm a desktop or web client. If I choose desktop client, when I try to have the user authorize, I can set the oauth_callback parameter but Twitter will ignore it after authorization and show a pin number. If, on twitter's form, I specify that I'm a web client, it requires me to enter a URL to redirect to after authorization. And, since I'm using an iPhone app-specific url scheme, their web form fails on validation as it only seems to accepts URLs conforming to the HTTP protocol.
So, it seems like I'm stuck - I can't say "desktop" because I don't want to bother with a pin, and I can't say "web" or I can't use an iPhone app URL. Any solution to this?
From your question:
I know a lot of people are doing the OAuth workflow inside of their apps using a UIWebView, but I don't agree with that and am going with the Pownce approach.
The Pownce article suggests that quitting your application and opening Mobile Safari to perform the authentication step is problematic, and that they started receiving bad reviews from users for doing it that way. They also experienced a failure rate of around 40%.
Pownce's solution is to use a UIWebView within your application instead, so I have a feeling you may have misinterpreted their recommendations. That being said, they do label this as a "naive" solution and go on to suggest a bunch of theoretical "ideal" solutions.
Another point you might not realise is that desktop applications (using the "out of band" / pin number method) and web applications need to open the Twitter site in either an embedded or external browser.
So you've got two choices on the iPhone:
Open up twitter.com in a UIWebView, specifying no oauth_callback parameter or oauth_callback=oob to start the pin-based out-of-band flow. The user then needs to copy the pin using the iPhone's copy-paste functionality, manually close the UIWebView, and paste the pin into your application. The pin can then be used converted to an access token.
Do it how everyone else is doing it (UIWebView + custom-uri://foo.bar in the callback parameter).
For obvious reasons, the first option is pretty crap and really only useful on platforms where Twitter is unable to redirect to a custom URI.
A simple solution may be to create an HTTP page that always sends a 301 redirect to your custom URL scheme and then provide that HTTP URL to the twitter web API.
Aside from that, Nathan's answer is very complete.
Here's how I do it: tell Twitter you're a web app, and make up any old HTTP:// URL to satisfy Twitter during registration of your oauth client.
Then in your app, pass the URL you want to in the callback parameter. Twitter (in my experience) uses the one you give it.
You could use an intermediate website for the authentication. Your app creates a unique id (hardware based?) and stores it. It then records it has sent the user for authentication and sends the unique id to your website. It then redirects the user to your website. Your website then sends the user to Twitter using oAuth. The user returns to your website and you mark the unique id as authenticated and store the authentication information. The user restarts the app on the iPhone, it reads it has sent the user for authentication and contacts your website with the unique id - and reads in the authentication information.
Long winded and needs another website, but it should work.