Self login in Salesforce API in iPhone? - iphone

I am using Salesforce api and i want to login automatically(hard code user name and password). i am using REST API and here is the login code which shows login form:
- (void)login {
SFOAuthCredentials *credentials = [[[SFOAuthCredentials alloc] initWithIdentifier:remoteAccessConsumerKey] autorelease];
credentials.protocol = #"https";
credentials.domain = OAuthLoginDomain;
credentials.redirectUri = OAuthRedirectURI;
self.coordinator = [[[SFOAuthCoordinator alloc] initWithCredentials:credentials] autorelease];
self.coordinator.delegate = self;
NSLog(#"%#",self.coordinator);
// remove this line if we want to cache the key, and use refresh flow
//effectively, we are saying, purge the old login and re-authenticate each time
[self.coordinator revokeAuthentication];
//now let's authenticate
[self.coordinator authenticate];
}
What i want, to automatically login (not ask username or password) so where i insert user name and password?

The Salesforce toolkit for iOS page shows an example of it using ZKSForce which returns a token that can be used by the REST API calls, see the document here
The REST API typically uses an OAuth token which saves the user from having to enter their username and password into a third party system such as yours. They enter the login once and the system refreshes the token to stay logged in (this is an oversimplified explanation). Either use OAuth which is the correct way with mobile and the REST API or use the session ID from an old style SOAP login request.

A quick Google and I found this - https://github.com/superfell/zkSforce
Haven't tried it yet though!

Include zkforce in your project
Add These files in your project
#import "ZKSforce.h"
#import "FDCServerSwitchboard.h"
#import "ZKLoginResult.h"
Add this code in .m
NSString *username =
NSString *password =
NSString *token = #"amnwcg24Uu5IenCvAJM5HgRq";
NSString *passwordToken = [NSString stringWithFormat:#"%#%#", password, token];
[[FDCServerSwitchboard switchboard] loginWithUsername:username password:passwordToken target:self selector:#selector(loginResult:error:)];
See result
- (void)loginResult:(ZKLoginResult *)result error:(NSError *)error
{
if (result && !error)
{
NSLog(#"Hey, we logged in!");
//[self fetchAccounts];
}
else if (error)
{
NSLog(#"An error occurred while trying to login.");
}
}

Related

iOS Twitter User-Timeline fetching with v1.1 API

Recently Twitter has changed API to v1.1. With this API, it is now required to first login on Twitter and only then we can fetch timeline. Is that true?
Can we fetch user timeline without user login?
Thanks
I tried FHSTwitterEngine but I found STTwitter better:
https://github.com/nst/STTwitter
look at FHSTwitterEngine you can use newly FHSTwitterEngine and if you request this method without autenticating, the users status is removed... you have to send consumer key and token along with screen_name..
In FHSTwitterEngine
//get username pass to method. In Dictionary you can get all info
NSString *username = [[FHSTwitterEngine sharedEngine]loggedInUsername];
NSDictionary *data=[[FHSTwitterEngine sharedEngine]getUserProfile:username];
// method to get all user info
-(id)getUserProfile:(NSString *)username
{
if (username.length == 0) {
return getBadRequestError();
}
NSURL *baseURL = [NSURL URLWithString:url_users_show];
OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
OARequestParameter *usernameP = [OARequestParameter requestParameterWithName:#"screen_name" value:username];
NSArray *params = [NSArray arrayWithObjects:usernameP, nil];
id userShowReturn = [self sendGETRequest:request withParameters:params];
return userShowReturn;
}
You can perfectly fetch a user timeline even if the user is not logged in.
You have to use the new "App Only" mode in which only the application is authentified.
See more details in this answer.

iOS 6 Facebook posting procedure ends up with "remote_app_id does not match stored id" error

I'm trying to perform a simple posting procedure:
- (IBAction)directPostClick:(id)sender {
self.statusLabel.text = #"Waiting for authorization...";
if (self.accountStore == nil) {
self.accountStore = [[ACAccountStore alloc] init];
}
ACAccountType * facebookAccountType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSArray * permissions = #[#"publish_stream", #"user_checkins", #"publish_checkins", #"user_likes", #"user_videos"];
NSDictionary * dict = #{ACFacebookAppIdKey : #"My app id here", ACFacebookPermissionsKey : permissions, ACFacebookAudienceKey : ACFacebookAudienceOnlyMe};
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
__block NSString * statusText = nil;
if (granted) {
statusText = #"Logged in";
NSArray * accounts = [self.accountStore accountsWithAccountType:facebookAccountType];
self.facebookAccount = [accounts lastObject];
NSLog(#"account is: %#", self.facebookAccount);
self.statusLabel.text = statusText;
[self postToFeed];
}
else {
self.statusLabel.text = #"Login failed";
NSLog(#"error is: %#", error);
}
}];
}
EDITED:
The problem is that when I click on alertView's OK button (don't allow doesn't work either) nothing happens! - This behavoir now changed with this
iOS 6 Facebook posting procedure ends up with "remote_app_id does not match stored id" So instead of just "nothing happens" I've got an error
"The Facebook server could not fulfill this access request: remote_app_id does not match stored id"
So , it seems that alert view's click handler doing nothing, my completionHandler is never called.
I do have the similar problem already: iOS 6 Social integration - go to settings issue
And I think that it is the same problem here. What do you guys think about it?
P.S.
I'm running on MAC mini, OS X 10.8.1 with latest xcode 4.5 (4G182) and using iPhone 6.0 simulator.
ADDED:
By the Bjorn's request adding the postToFeed method although it is never called:
- (void)postToFeed {
NSDictionary * parameters = #{#"message" : #"Hello world!"};
NSURL * feedUrl = [NSURL URLWithString:#"https://graph.facebook.com/me/feed"];
SLRequest * request = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodPOST URL:feedUrl parameters:parameters];
request.account = self.facebookAccount;
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
self.statusLabel.text = #"Posted!";
});
}];
}
I also experienced some difficulties when working with the Accounts Framework and the Facebook integration. Here is what I've learned and how I got it working.
1. Make sure you've setup your App on Facebook correctly
You need to set how your App integrates with Facebook to Native iOS App and enter the Bundle ID of your App into the designated field. (Edit: Note that bundle IDs are case sensitive) You can set the iTunes ID to 0 for now. Enable Facebook Login and set the App Type in the advanced settings tab to Native/Desktop.
Also set App Secret in Client to No.
If one or more of these options are not set correctly it's very likely you get the error The Facebook server could not fulfill this access request: remote_app_id does not match stored id.
(Edit: You also have to ensure the sandbox is disabled.)
2. Installing the Facebook App for the first time
When first installing an App via the native Facebook integration on iOS (and Mac OS X too), you must ask for a basic read permission only! Nothing else as email, user_birthday and user_location is allowed here. Using user_about_me, which is also a basic read permission according to the Facebook documentation, does not work. This is pretty confusing if you previously worked with the Facebook JavaScript SDK or the Facebook PHP SDK, because it asks for the basic permissions by default without you having to do something. Facebook also updated their documentation with a short step-by-step guide on how to use the new Facebook SDK on iOS 6.
3. Requesting additional permissions
It's important to know, that you may not ask for read and write permissions at the same time. That's also something experienced Facebook SDK developers may find confusing. Requesting the read_stream permission along with the publish_stream permission will make the request fail, resulting in the error An app may not aks for read and write permissions at the same time.
As Facebook does not really distinguish between read/write permissions in the Permission Reference, you must identify write permissions by yourself. They're usually prefixed with manage_*, publish_*, create_* or suffixed by *_management.
Facebook does also not recommend to ask for additional permissions immediately after getting basic permissions. The documentation says "You are now required to request read and publish permission separately (and in that order). Most likely, you will request the read permissions for personalization when the app starts and the user first logs in. Later, if appropriate, your app can request publish permissions when it intends to post data to Facebook. [...] Asking for the two types separately also greatly improves the chances that users will grant the publish permissions, since your app will only seek them at the time it needs them, most likely when the user has a stronger intent.".
4. Sample Code
The following sample code should work on iOS and Mac OS X:
ACAccountType * facebookAccountType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
// At first, we only ask for the basic read permission
NSArray * permissions = #[#"email"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"My app id here", ACFacebookAppIdKey, permissions, ACFacebookPermissionsKey, ACFacebookAudienceOnlyMe, ACFacebookAudienceKey, nil];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
if (granted && error == nil) {
/**
* The user granted us the basic read permission.
* Now we can ask for more permissions
**/
NSArray *readPermissions = #[#"read_stream", #"read_friendlists"];
[dict setObject:readPermissions forKey: ACFacebookPermissionsKey];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
if(granted && error == nil) {
/**
* We now should have some read permission
* Now we may ask for write permissions or
* do something else.
**/
} else {
NSLog(#"error is: %#",[error description]);
}
}];
} else {
NSLog(#"error is: %#",[error description]);
}
}];
make sure sandbox mode is not activated if you are trying to access facebook account from application for non developer users.

GTM OAuth2 retrieving access_token via Keychain not successful

I'm following Google's examples on how to authorize an app to access one or more APIs.
The problem is that when i authorise successfully i get the access_token, but after this i can't get it from the keychain it is stored into. I read somewhere that iPhone Simulator doesn't work with Keychain, is it because of that, and if it is can you tell me some other way to store my access token?
Here is my code:
static NSString *const kKeychainItemName = #"OAuthGoogleReader";
GTMOAuth2Authentication *auth;
auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
clientID:kClientID
clientSecret:kClientSecret];
BOOL isSignedIn = [auth canAuthorize];
if (isSignedIn) {
NSLog(#"Signed");
self.window.rootViewController = self.viewController;
auth.accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"accessToken"];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.google.com/reader/api/0/subscription/list?access_token=%#", [auth accessToken]]]];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
// optional upload body data
//[myFetcher setPostData:[postString dataUsingEncoding:NSUTF8StringEncoding]];
[myFetcher setAuthorizer:auth];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher:finishedWithData:error:)];
// - (void)myFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)retrievedData error:(NSError *)error;
}else{
NSString *scope = #"https://www.google.com/reader/api/";
GTMOAuth2ViewControllerTouch *viewController;
viewController = [[GTMOAuth2ViewControllerTouch alloc] initWithScope:scope
clientID:kClientID
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)];
self.window.rootViewController = viewController;
}
I get error:
2012-08-22 16:54:47.253 greader[20833:c07] Signed
2012-08-22 16:54:47.705 greader[20833:c07] Cannot authorize request with scheme http (<NSMutableURLRequest http://www.google.com/reader/api/0/subscription/list?access_token=(null)>)
as you can see access_token is just nil.
Also some simple examples on how to use this library would be great.
Thank you!
The gtm-oauth2 library handles storing and retrieving the access token and other auth values on the keychain. The app should not need to use the access token string directly, nor should the app put the authorization tokens into NSUserDefaults, as that is insufficiently secure.
gtm-auth2 also by default will refuse to attach an access token to a URL with an http: scheme. OAuth 2 is secure only when used with https: scheme URLs.

Invalid Facebook access token

I am developing an application which posts videos to Facebook.
I have registered this app on Facebook, received APIkey, APIsecret, the app successfully passes authentication and receives the access token. Here is my code for authentication:
m_Facebook = [[Facebook alloc] init];
[m_Facebook logout:self];
m_FacebookUploader = [[FBVideoUpload alloc]init];
NSArray *permissions = [NSArray arrayWithObjects:#"publish_stream", #"offline_access",#"read_stream",nil];
m_Facebook.forceOldStyleAuth = YES;
[m_Facebook authorize:kApiKey permissions:permissions delegate:self];
However when trying to upload a video, the class FBVideoUpload tries to separate the access token into several parts:
- (NSString*) sessionID
{
NSArray *components = [accessToken componentsSeparatedByString:#"|"];
NSLog(#"components: %#", components);
return [components count] < 2 ? nil : [components objectAtIndex:1];
}
According to http://developers.facebook.com/docs/authentication/ the access token should contain several componenets, separated by "|", but the one I receive at authentication does not contain several components separated by a "|". The access_token I receive looks as follows:
AAA*GXJapke*BAGRlZC7aBLhiZB*MUEV*AAF6*ZBhZBw*0ER1M*vkXlRUZCwO*czfgs*wHbnA*BcTU*VrPZC*Yw3p*JmCIMZ*xSnCP*GqPRWZALgZDZ*
(I replaced some symbols with "*")
Here is my code for uploading the video:
[m_FacebookUploader setApiKey:kApiKey];
[m_FacebookUploader setAccessToken:m_Facebook.accessToken];
[m_FacebookUploader setAppSecret:kApiSecret];
[m_FacebookUploader startUploadWithURL:url params:params delegate:self];
I receive an error here:
if ([self sessionID] == nil) {
NSLog(#"Unable to retrieve session key from the access token.");
return;
}
Which not surprising since sessionID really returns nil.
Whatever library you're using to do that video upload is using some outdated logic to handle uploads. That whole method where it breaks apart the session key doesn't need to exist. Just use the access token you get back from FB with your video upload request. Also, be sure you're using our latest SDK https://github.com/facebook/facebook-ios-sdk

Twitter integrated in Iphone App

I used MGTwitterEngine
which try to login then request fail error comes
Error Detail
connectionIdentifier 6260FAFD-AE4E-4F05-AE67-FFA1DA18578F
error description The operation couldn’t be completed. (HTTP error 401.)
error user info
({
body = "\n\n Client application is not permitted to use xAuth.\n /oauth/access_token\n\n";
response = "";
})
Any Idea
-Amit Battan
Basic authentication is no longer supported by Twitter. You can use Twitter-oAuth-iPhone. It added oAuth with MGTwitterEngine. There is a demo code project included too. However, you will require SDK >= 3.2 to compile the latest version.
The problem with xAuth that you need to request to the Twitter API team providing detail of the application. In case of oAuth that is not required. You will need to create an application in Twitter Dev and then you need to use the keys in the project. That's all.
MGTwitterEngine is significantly outdated at this point, as it doesn't use xAuth/oAuth. See this tutorial on using MGTwitterEngine with xAuth:
Switching from Basic to xAuth with mgtwitterengine on iPhone
The OAuth do not need the permission from Twitter. But XAuth is required.
I'm not using MGTwitterEngine, with the official document of Twitter, I scratched a client with C, to calculated the nonce and signature, then use the tool cURL, then I can get the oauth_token and token_secret.
Additional message about cURL is that you must have created your App in Twitter, you can use the OAuth tool in your App(not required to be the current App your're working on) setting. If the App in twitter is not your current App, you should generate the cURL command line first. Set the Request Settings to POST and the Request URI to http://api.twitter.com/oauth/request_token, leave other setting as default, then click the button on the page bottom, you then see the cURL command, it seems like that:
curl --request 'POST' 'http://api.twitter.com/oauth/request_token' --header 'Authorization: OAuth oauth_consumer_key="your_consumer_key", oauth_nonce="your_random_string", oauth_signature="your_signature", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1329273306", oauth_token="451145411-AxGXG8xNdW1Eymwx85hs3sc1OE3NYsXe578AUtPe", oauth_version="1.0"' --verbose
replace the oauth_consumer_key , oauth_timestamp and oauth_signature with yours, delete the oauth_token and its value, copy the command to your cmd or shell and execute it. Another important trick is that, you must explicitly mark the oauth_callback in Authorization, and set the value as oob:
auth_callback="oob"
If your consumer_key and oauth_signature is correct, this steps will not lead to the Client application is not permitted to use xAuth error.
#taskinoor
there the code I am using ...
I have create application on twitter already
Controller .h file
#import <UIKit/UIKit.h>
#import "MGTwitterEngine.h"
#class OAToken;
#interface TwitterTestViewController : UIViewController <MGTwitterEngineDelegate> {
MGTwitterEngine *twitterEngine;
OAToken *token;
}
#end
Controller .m file
#import "TwitterTestViewController.h"
#implementation TwitterTestViewController
- (void)awakeFromNib{
// Put your Twitter username and password here:
NSString *username = #"amit_bursys";
NSString *password = #"mypassword";
NSString *consumerKey = #"my_key";
NSString *consumerSecret = #"my_seret";
if (! username || ! password || !consumerKey || !consumerSecret) {
NSLog(#"You forgot to specify your username/password/key/secret in AppController.m, things might not work!");
NSLog(#"And if things are mysteriously working without the username/password, it's because NSURLConnection is using a session cookie from another connection.");
}
twitterEngine = [[MGTwitterEngine alloc] initWithDelegate:self];
[twitterEngine setUsesSecureConnection:NO];
[twitterEngine setConsumerKey:consumerKey secret:consumerSecret];
[twitterEngine setUsername:username];
[twitterEngine getXAuthAccessTokenForUsername:username password:password];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)dealloc {
[super dealloc];
}
#pragma mark MGTwitterEngineDelegate methods
- (void)requestSucceeded:(NSString *)connectionIdentifier{
NSLog(#"Request succeeded for connectionIdentifier = %#", connectionIdentifier);
}
- (void)requestFailed:(NSString *)connectionIdentifier withError:(NSError *)error{
NSLog(#"Request failed for connectionIdentifier = %#, error = %# (%#)",
connectionIdentifier,
[error localizedDescription],
[error userInfo]);
}
- (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)connectionIdentifier{
NSLog(#"Got statuses for %#:\r%#", connectionIdentifier, statuses);
}
- (void)directMessagesReceived:(NSArray *)messages forRequest:(NSString *)connectionIdentifier{
NSLog(#"Got direct messages for %#:\r%#", connectionIdentifier, messages);
}
- (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString *)connectionIdentifier
{
NSLog(#"Got user info for %#:\r%#", connectionIdentifier, userInfo);
}
#end
and Code log is
2010-12-21 11:14:31.533 TwitterTest[734:207] Request failed for connectionIdentifier = D28BD476-7315-4510-B51A-968E516D169D, error = The operation couldn’t be completed. (HTTP error 401.) ({
body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <request>/oauth/access_token</request>\n <error>Client application is not permitted to use xAuth.</error>\n</hash>\n";
response = "<NSHTTPURLResponse: 0x6022470>";
})