Difficulties signing in to Twitter from iPhone - iphone

I'm using MGTwitterEngine to add Twitter functionality to my app. It's very easy to simply prompt the user for a username and password and then start posting. Strangely, however, I've noticed other apps (eg Foursquare and Brightkite) require you to visit their website to associate your Twitter account with your foursquare/brightkite/whatever account.
Why do they do it this way?
Is there a reason why my app shouldn't prompt the user for a Twitter username and password, even though it would be so easy?
Thanks a bunch!
Tristan

This is because you're using Basic Auth, which is just a username/password. Most new Twitter apps use the more robust OAuth, which requires you to visit Twitter.com to allow access, but does not require a username/password. The Twitter API docs claim that support for Basic Auth will be dropped soon, so you should be using OAuth as well.

Twitter supports OAuth, which allows you to access their account without asking for their password directly.
The main concern is security. What happens if/when your database gets hacked? The attackers will have access to all of your user's twitter passwords.
On hte other hand, those sites don't store their users passwords; if they get hacked, twitter can easily disable the oauth credentials, locking out any attackers before they can do harm.
Use OAuth; it's a lot safer.

Just replace YOUR_TWITTER_USERNAME and YOUR_TWITTER_PASSWORD. The code below has to be included in your viewController.m
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL: [NSURL
URLWithString: #”http: //YOUR_TWITTER_USERNAME: YOUR_TWITTER_PASSWORD#twitter. com/
statuses/update. xml”]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval: 60. 0] ;
[theRequest setHTTPMethod: #”POST”] ;
[theRequest setHTTPBody: [[NSString stringWithFormat: #”status=%#”,
themessage] dataUsingEncoding: NSASCIIStringEncoding] ] ;
NSURLResponse* response;
NSError* error;
NSData* result = [NSURLConnection sendSynchronousRequest:theRequest
returningResponse: &response error: &error] ;
NSLog( #”%#”, [[[ NSString alloc] initWithData: result
encoding: NSASCIIStringEncoding] autorelease] ) ;

Related

http authentication in devise and rails 3

I have an application which uses devise on rails 3. I would like to enable http authentication so that I can authenticate to my web app from an iPhone app. How can I authenticate from my iPhone app to devise?
Is this secure or should I be authenticating differently?
From the design point of view you have got 3 options:
1) Use basic http authentication: your IPhone app has a secret key -which is baked in your IPhone app code - that uses to authenticate each request with the web app.
Google search: "Devise basic http authentication"
2) You can use https by having a public certificates in your IPhone app and a private certificates on your web app. This is a lot of work to configure right, it is very secure since your IPhone app and the Rails server are exchanging messages over an encrypted channel. The security is also transparent to your rails code since authentication is done at the transport level.
3) The IPhone app connects to the web app using https, get an authentication token that it then uses to make calls to the web app over regular http. More secure than 1 since the key can expire, quite a bit of work to implement and very scalable.
(http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/)
Most of apps use solution 1.
Hope this help.
EDIT: to implement http authentication (either basic or digest) I suggest you look at:
http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic.html
and
https://github.com/plataformatec/devise/wiki/How-To:-Use-HTTP-Basic-Authentication
The precise steps will depends on your Rails server stack.
EDIT 2: I do not think Devise provide a way to get the auth_token. I can see you can try several solutions:
when the user logs in the server retrieves the authentication_token and puts it in the cookie. Not very secure unless you encrypt it with a shared secret key.
you can provide a https web service that your IPhone app uses to get a user token. Your IPhone app would make the request right after receiving the user request to sign in.
Sorry I cannot be of more help with some real code.
This largely depends on how you are implementing things on the server side, but we implemented this using Matteo's 3rd option. I have a rails 3.1 implementation using devise. The route to the login is /users/login.json . First build up the JSON body for login with code like this:
NSMutableDictionary *loginDictionary = [NSMutableDictionary dictionary];
NSMutableDictionary *usernamePasswordDictionary = [NSMutableDictionary dictionary];
[usernamePasswordDictionary setObject:username forKey:#"email"];
[usernamePasswordDictionary setObject:password forKey:#"password"];
[loginDictionary setObject:usernamePasswordDictionary forKey:#"user"];
NSData *data = [NSJSONSerialization dataWithJSONObject:loginDictionary options:0 error:&error];
which yields this JSON:
{"user":{"password":"blahblahblah","email":"admin#*****.com"}}
I send a POST url request with code like this:
NSString *postUrlString = [NSString stringWithFormat:#"%#users/login.json", kServerAPIBaseURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:postUrlString] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:kTimeoutInterval];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-type"];
[request setHTTPBody:data];
The response I get back contains JSON. We configured the server side to return the a session_auth_token:
{
admin = 1;
"created_at" = "2012-01-25T00:15:58Z";
"current_sign_in_at" = "2012-04-04T04:29:15Z";
"current_sign_in_ip" = "75.163.148.101";
email = "admin#******.com";
"encrypted_password" = "*****";
"failed_attempts" = 0;
id = 1;
"last_sign_in_at" = "2012-04-03T03:37:18Z";
"last_sign_in_ip" = "75.163.148.101";
"locked_at" = "<null>";
name = "Joe Smith";
"remember_created_at" = "2012-03-29T20:35:43Z";
"reset_password_sent_at" = "<null>";
"reset_password_token" = "<null>";
"session_auth_token" = "3FRgX6CYlzQJGC8tRWwqEjFaMMFKarQAYKTy3u84M0U=";
"sign_in_count" = 145;
status = 1;
"unlock_token" = "<null>";
"updated_at" = "2012-04-04T04:29:15Z";
}
We store that session_auth_token and then send it back with every request in a header, something like this:
NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[self postUrlString]]...
[postRequest setHTTPMethod:#"POST"];
[postRequest setValue:#"application/json" forHTTPHeaderField:#"Content-type"];
[postRequest setValue:[self sessionAuth] forHTTPHeaderField:#"X-CSRF-Token"];
[postRequest setHTTPBody:data];
That parameter [self sessionAuth] contains the session_auth_token.
Let me know if you need clarification.

Upload image from iphone to facebook without dialog

i want to send image from my iphone to facebook of my account without showing any dialog (in fbconnect there is dialog) . I want a simple way to just test whether it is uploaded in the facebook are not.
I tested with twitter api send message from my iphone and its work fine its few lines of code,
I pasted below
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://username:password#twitter.com/statuses/update.xml"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval: 60.0];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody:[[NSString stringWithFormat:#"status=%#", #"test message sends from iphone"] dataUsingEncoding:NSASCIIStringEncoding]];
NSURLResponse* response;
NSError* error;
NSData* result = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
NSLog(#"%#", [[[NSString alloc] initWithData:result encoding:NSASCIIStringEncoding] autorelease]);
Like wise i want to send text and photo to facebook account ? Is it possible ?
The fbconnect is more no of blocks and lines , can anyone help me ? a simple way to understand it ?
Thanks in advance
With the new OAuth Facebook API and the new facebook-ios-sdk I don't think you can do without the dialog. The whole point is that your app never sees and stores the user credentials. If you then close the app and the login dialog appears again a cookie (set/used by the UIWebView, AFAIK) logs you in without you needing to enter the credentials again.

iPhone - HTTPS connection to Server with Self-Signed Certificate [duplicate]

I have a cocoa class set up that I want to use to connect to a RESTful web service I'm building. I have decided to use HTTP Basic Authentication on my PHP backend like so…
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
//Stuff that users will see if they click 'Cancel'
exit;
}
else {
//Validation Code
echo "You entered info.";
}
?>
At this point I'm using a synchronous NSURLConnection, which I understand the Apple documentation states has less support for Authentication.
But is it even possible at all? I can do cookie authentication very easily sans NSURLProtectionSpaces or NSURLCredentials or any of the authentication classes. Also, are there any resources where I can read more about the Cocoa Authentication classes?
Thanks.
UPDATE: mikeabdullahuk
The code you supplied (the second example) is almost identical to what I had written. I have done some more investigating, and discovered that the NSURLConnection is returning an error…
Error Domain=NSURLErrorDomain Code=-1012 UserInfo=0x1a5170 "Operation could not be completed. (NSURLErrorDomain error -1012.)"
The code corresponds to NSURLErrorUserCancelledAuthentication. So apparently my code is not accessing the NSURLCredentialStorage and instead is canceling the authentication. Could this have anything to do with the PHP HTTP Authentication functions? I'm quite confused at this point.
A synchronous NSURLConnection will absolutely work with NSURLCredentialStorage. Here's how things usually work:
NSURLConnection requests the page from the server
The server replies with a 401 response
NSURLConnection looks to see what credentials it can glean from the URL
If the URL did not provide full credentials (username and password), NSURLConnection will also consult NSURLCredentialStorage to fill in the gaps
If full credentials have still not been determined, NSURLConnection will send the -connection:didReceiveAuthenticationChallenge: delegate method asking for credentials
If the NSURLConnection now finally has full credentials, it retries the original request including authorization data.
By using the synchronous connection method, you only lose out on step 5, the ability to provide custom authentication. So, you can either pre-provide authentication credentials in the URL, or place them in NSURLCredentialStorage before sending the request. e.g.
NSURLRequest *request =
[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://user:pass#example.com"]];
[NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL];
or:
NSURLCredential *credential = [NSURLCredential credentialWithUser:#"user"
password:#"pass"
persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:#"example.com"
port:0
protocol:#"http"
realm:nil
authenticationMethod:nil];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential
forProtectionSpace:protectionSpace];
[protectionSpace release];
NSURLRequest *request =
[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://example.com"]];
[NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL];
In a situation where a 401 or other authentication challenge is unacceptable/impossible, I sometimes use a dummy CFHTTPMessage to generate the authetication line, then copy that back into the NSURLRequest:
// assume NSString *username and *password exist and NSURLRequest *urlRequest
// exists and is fully configured except for HTTP Basic Authentication..
CFHTTPMessageRef dummyRequest =
CFHTTPMessageCreateRequest(
kCFAllocatorDefault,
CFSTR("GET"),
(CFURLRef)[urlRequest URL],
kCFHTTPVersion1_1);
CFHTTPMessageAddAuthentication(
dummyRequest,
nil,
(CFStringRef)username,
(CFStringRef)password,
kCFHTTPAuthenticationSchemeBasic,
FALSE);
authorizationString =
(NSString *)CFHTTPMessageCopyHeaderFieldValue(
dummyRequest,
CFSTR("Authorization"));
CFRelease(dummyRequest);
[urlRequest setValue:authorizationString forHTTPHeaderField:#"Authorization"];
This may seem completely a bizarre way to do it but it is tolerant of situations where the username/password aren't URL clean and where NSURLRequest refuses to consult the NSURLCredentialStorage because the server isn't actually sending a HTTP 401 (for example it sends a regular page instead).
I would note mikeabdullahuk's answer is good but also if you use NSURLCredentialPersistencePermanent instead of per session it will store the credentials in the users keychain so next time you can check NSURLCredentialStorage for a non nil value for the default credentials for a protection space and if you get a non nil value you can just pass the credentials in. I am using this method right now for a delicious.com client I am writing and it works very well in my tests.
Set your credential as the default credential for the protectionspace:
// Permananent, session, whatever.
NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence: NSURLCredentialPersistencePermanent];
// Make sure that if the server you are accessing presents a realm, you set it here.
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:#"blah.com" port:0 protocol:#"http" realm:nil authenticationMethod:NSURLAuthenticationMethodHTTPBasic];
// Store it
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
At this point, any subsequent NSURLConnection that is challenged using a protection space that matches what you set will use this credential

Has anyone implemented the PayPal API through a native iPhone app?

It seems the only way to stay "in app" is to give them a UIWebView of the paypal mobile site and let them complete the transaction there, otherwise the user would need to use their API key.
Does this sound right and has anyone got or seen any sample code? I have to think this is a common piece of code.
UPDATE:
Will Apple allow this?
It is a charity app, so I am assuming there is no issue.
Re-UPDATE:
I assumed wrong.
Apple will not allow payments directly within apps using paypal. You have to re-direct to a web interface.
Re-Update:
As answered below this code may still be useful for the purchase of physical goods
Update:
Although this code works, App Store terms won't allow you to use this code within an app.
Original Answer:
I figured this out after some heavy API research. Below is a method that creates an HTTP POST to send to Paypal and makes an NSURLRequest. You can fill in the appropriate string format variables. I used HTTP Client to check what I was doing.
- (void)sendPayPalRequestPOST{
perfomingSetMobileCheckout=YES;
recordResults = FALSE;
NSString *parameterString = [NSString stringWithFormat:#"USER=%#&PWD=%#&SIGNATURE=%#&VERSION=57.0&METHOD=SetMobileCheckout&AMT=%.2f&CURRENCYCODE=USD&DESC=%#&RETURNURL=%#", userName, password, signature, self.donationAmount, #"Some Charge", returnCallURL];
NSLog(parameterString);
NSURL *url = [NSURL URLWithString:paypalUrlNVP];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [parameterString length]];
[theRequest addValue: msgLength forHTTPHeaderField:#"Content-Length"];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody: [parameterString dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if( theConnection ){
webData = [[NSMutableData data] retain];
[self displayConnectingView];
}else{
NSLog(#"theConnection is NULL");
}
}
After this you need to parse the response, grab the session key and create a UIWebView to take them to the mobile paypal site. Paypal lets you specify a "return URL" which you can make anything you want. Just keep checking the UIWebview in the delegate method for this address and then you know the transaction is complete.
Then you send one more HTTP Post (similar to the one above) to Paypal to finalize the transaction. You can find the API information in the Paypal Mobile Checkout API docs.
Apple will allow custom checkouts for physical purchases. I talked with them at the iPhone Tech Talks in London and they said that they will not support physical purchases with In App Purchase as they would have to deal with refunds, etc. They also referred to existing apps that have custom checkouts.
When you say "I assumed wrong" about Apple allowing charitable donations within an app, can you provide any more information? I'm working on an app and there's a requirement to allow charitable donations...I haven't been able to find anything from Apple strictly forbidding it, but I haven't been able to find an app that allows charitable donations in the store, either.
(I struggled with whether to post this here and not as a new top-level question, but you're the first person I've come across with direct knowledge about the charitable giving within an iPhone app question).
Is it not possible using Paypal's Mobile Payment Library?
https://www.x.com/community/ppx/xspaces/mobile/mep?view=overview
Depending on the complexity of your needs, PayPal's iOS SDK (released March 2013) might be the ticket.

Unable to POST data from IPhone using google account authentication

I'm working on an IPhone application that works with a Google App Engine application. I manage to get logged by using a google account and I get the authentication token. I'm also able to GET data from the GAE service (I did it after reading another question written here) but now I need to POST data so I need to send the authentication token in the header of the POST request. I tried several options but none of them worked.
Here is the code I use to put that auth into the header:
NSString* urlStr = [NSString stringWithFormat:#"%#%#", HOST, url];
NSMutableURLRequest* urlPost = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlStr]];
NSString* authStr = [NSString stringWithFormat:#"GoogleLogin auth=%#", token];
[urlPost addValue:authStr forHTTPHeaderField:#"Authorization"];
but it doesn't work.
Any help?
You need to use [request setHTTPMethod: #"POST"] and [request setHTTPBody: postdata] to properly configure the POST components. See the NSMutableURLRequest docs for more details.
Whenever I'm troubleshooting a problem related to HTTP, the first tool I'll grab is Charles HTTP Proxy. It will show you the entire request and response for closer examination.
If you're authenticating against an App Engine app, you need to obtain and send an authentication cookie, rather than using the GoogleLogin authentication. The source of appengine_rpc.py in the Python SDK demonstrates how.