Not getting email from LinkedIn Objective-C - ios

I am using the Objective C library for LinkedIn and trying to fetch user's primary emailId.
I am doing following :-
1)https://api.linkedin.com/uas/oauth/requestToken?scope=r_emailaddress >> Passing this as the url while requesting for request token.
2) And http://api.linkedin.com/v1/people/~:(id,first-name,industry,email-address) while fetching profile for user but
I never received email address.
Can you please let me know, what am I missing.
Thanks in advance

I am able to get the email address successfully. Only change was in the request method for requestToken to pass the scope parameter while requesting for permission in a different way not described in the reference guide on LinkedIn developer page.
Its in "RDLinkedInEngine.m" file >> "sendTokenRequestWithURL:token:onSuccess:onFailure" method >>
OARequestParameter *nameParam = [[OARequestParameter alloc] initWithName:#"scope" value:#"r_basicprofile+rw_nus+r_emailaddress"];
NSArray *params = [NSArray arrayWithObjects:nameParam, nil];
[request setParameters:params];
OARequestParameter * scopeParameter=[OARequestParameter requestParameterWithName:#"scope"
value:#"r_emailaddress r_fullprofile rw_nus"];
[request setParameters:[NSArray arrayWithObject:scopeParameter]];
Make sure that while requesting for access token , you keep the method as it is provided by default because the same method is used to get request token as well as access token.

Related

Apigee user authentication, access_token, and cache login session in iOS

I'm new to Apigee and can't seem to wrap my head around it. I am familiar with implementing an iOS app that talks to a database via a webservice call. The call would involve passing back and forth JSON or variables though POST, GET, etc.
The user flow I envision is a lot like Facebook long term token storage. Here are the steps:
Type username and password to login.
The app will remember the access_token in the keychain.
The access_token will be used with any future requests such as updating profile. This way the user doesn't have re-login every time he/she is using the app.
Log out will clear all the token.
If the token is invalid or expired, the app will take the user back to login.
I've taken multiple routes and ended up getting stuck on all of them when it comes to Apigee.
ROUTE 1
I made a call to logInUser and receive access_token in return.
[self.apigeeDataClient logInUser:username password:password];
All this is good until I want to update user's email address using the code below.
NSMutableDictionary *requestDict = [NSMutableDictionary dictionary];
[requestDict setObject:email forKey:kDataEmail];
NSString *url = [NSString stringWithFormat:#"%#/%#/%#/users/%#?access_token=%#", BASE_URL, UG_ORG_NAME, APP_NAME, [userData objectForKey:kDataUUID], self.accessToken];
NSString *op = #"PUT";
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithDictionary:requestDict]
options:0
error:&error];
[self.apigeeDataClient apiRequest:url operation:op data:[NSString stringWithUTF8String:[jsonData bytes]]];
It seems that every other time it's giving me "No content to map to Object due to end of input" error. I checked out this thread but have no luck. I made sure the JSON object is not null. I tried changing the operation from PUT to POST and GET. None of which update the email address in the database.
ROUTE 2
Instead of using apiRequest, I switched to updateEntity.
NSMutableDictionary *requestDict = [NSMutableDictionary dictionary];
[requestDict setObject:email forKey:kDataEmail];
[requestDict setObject:kDataUsers forKey:kDataType];
[requestDict setObject:self.accessToken forKey:kDataAccessToken];
NSString *entityID = [userData objectForKey:kDataUUID];
[self.apigeeDataClient updateEntity:entityID entity:requestDict];
It looks promising except I started getting "Subject does not have permission" like the issue described in this thread. I tried calling assignPermissions like mentioned in Apigee document but that didn't solve the problem. I even provide access_token with the call, even though I shouldn't have to.
In the attempt to avoid calling login also tried calling storeOAuth2TokensInKeychain and retrieveStoredOAuth2TokensFromKeychain mentioned here. That didn't work either.
The only thing way to resolve this error is by calling logInUser before making a call to updateEntity. This means the user will have to login every time he/she wants to use the app. I know I can store username/password in the keychain. But before I do that I'm wondering if there's better solution out there.
I know it's a long post. So thank you for reading this far. Any pointers are greatly appreciated.

Use post request to receive LinkedIn user profile information in iOS

I am looking for a way to retrieve the profile information of a LinkedIn user by making a post request, I have read these two LinkedIn pages but it doesn't seem to explain much, or I couldn't understand much of it:
REST API LinkedIn
basic profile informations
I have seen these example on stackoverflow but I didn't understood to much:
http://api.linkedin.com/v1/people/~:(id,first-name,last-name,maiden-name,email-address,formatted-name,phonetic-last-name,location:(country:(code)),industry,distance,current-status,current-share,network,skills,phone-numbers,date-of-birth,main-address,positions:(title),educations:(school-name,field-of-study,start-date,end-date,degree,activities))
I am only interested to retrieve the skills section the one that on the website appears as so:
There's a fantastic library for LinkedIn-iOS integration by Kirsten Jones, you can use that to make calls to the LinkedIn API. You need an access token to make calls.
https://github.com/PrincessPolymath/LinkedIn-OAuth-Sample-Client
Make calls like this:
NSURL *url = [NSURL URLWithString:#"http://api.linkedin.com/v1/people/~:(id,first-name,last-name,maiden-name,formatted-name,phonetic-last-name,location:(country:(code)),industry,distance,current-status,current-share,network,skills,phone-numbers,date-of-birth,main-address,positions:(title),educations:(school-name,field-of-study,start-date,end-date,degree,activities))"]];
OAMutableURLRequest *request =
[[OAMutableURLRequest alloc] initWithURL:url
consumer:oAuthLoginView.consumer
token:oAuthLoginView.accessToken
callback:nil
signatureProvider:nil];
[request setValue:#"json" forHTTPHeaderField:#"x-li-format"];
OADataFetcher *fetcher = [[OADataFetcher alloc] init];
[fetcher fetchDataWithRequest:request
delegate:self
didFinishSelector:#selector(profileApiCallResult:didFinish:)
didFailSelector:#selector(profileApiCallResult:didFail:)];
- (void)profileApiCallResult:(OAServiceTicket *)ticket didFinish:(NSData *)data
{
NSString *responseBody = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSDictionary *profile = [responseBody objectFromJSONString];
if ( profile )
{
name.text = [[NSString alloc] initWithFormat:#"%# %#",
[profile objectForKey:#"firstName"], [profile objectForKey:#"lastName"]];
headline.text = [profile objectForKey:#"headline"];
.....and get skills and other user details
}
}
Use tool:https://apigee.com/console/linkedin
API to get the list of Skills:
https://api.linkedin.com/v1/people/~:(id,num-connections,skills)?format=json
I tried it in the Console tool and able to fetch the skills for my profile. I think the individual skill ID with above request should help you to get further information. Try it out.
If anyone is reading this answer, the LinkedIn API has limited access as of May 2015. You will need to apply to their Apply with LinkedIn program to access full profile fields including skills.
https://developer.linkedin.com/docs/fields
I have fair amount of experience working with the linkedIn API. It's been a little while, but hopefully this will set you on the right track.
To get profile information from a linked in user who is one of your connections you need a format like follows:
NSString *theRequest = [NSString stringWithFormat:#"https://api.linkedin.com/v1/people/id=abc123:(first-name,last-name,picture-url,location:(name))?oauth2_access_token=%#&format=json", accessToken];
This request will return the first name, last name, profile picture url, and location of the user with the id specified.
You can see a list of field types you can request by checking out linkedIn's documentation on their profile field descriptions here:
https://developer.linkedin.com/docs/fields
If you're wondering how to get the id of the user whose profile information you want request in the first place, you can make request for some basic info (including ids) of all your connections like this:
NSString *basicConnectionInfo = [NSString stringWithFormat:#"https://api.linkedin.com/v1/people/~/connections:(id,first-name,last-name)?oauth2_access_token=%#&format=json", accessToken];
This request will give you the id, first name, and last name of all of your connections. After you've gotten the id of the person you want, you can make a request using the user's id (as shown in the first example).
Now for the slightly unfortunately news... If you followed the link provided above, you'll notice that the skills field is part of the "Member profile fields available to Apply with LinkedIn developers". I'm assuming you'll have to follow this link they provided: https://developer.linkedin.com/docs/apply-with-linkedin in order to access the skills member profile field.
I have not applied with LinkedIn. So, I haven't tested a call to the skills field. But, I'm guessing it'll be similar to the examples I've shown you. Hope this helps!

Cannot access Google Places API with generated Key

I have generated an API Key using google's console for my project. Then as they have mentioned in their documentation, I have added the key in my applications AppDelegate in the didFinishLaunchingWithOptions method. The following code:
[GMSServices provideAPIKey:#"{MY_API_KEY}"];
Then I used the following code to send a Google Places Auto complete request from inside my ViewController:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=%#&sensor=false&key={MY_API_KEY}",searchString]]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:120];
placesListConnection = [NSURLConnection connectionWithRequest:request delegate:self];
And I am getting the following response:
{
"error_message" : "This IP, site or mobile application is not authorized to use this API key.",
"predictions" : [],
"status" : "REQUEST_DENIED"
}
What am I doing wrong here? How to rectify this?
Finally solved the issue. Instead of using API_KEY for IOS, i created an API_KEY for web that doesn't need a referrer and then sent the request using that key. Now it is working perfectly.
Have you checked Developers Console? Is Places API enabled under APIs & auth > APIs?

'ASIHTTPRequest' is not responding to setPostValue, need to pass email id as parameter

i am new to iOS development , recently i'm working with 'ASIHTTPRequest' library. i have downloaded it's example from Here. it's working fine. I need to send a parameter to my web service as 'email' and also authentication needed.
i tried following
[request setPostValue:#"abcd#gmail.com" forKey:#"email"]; based on this Reference
but it's give me warning that Instance method -setPostValue:forKey() not found. How can i pass email id as parameter to web service? For your reference i use web service to reset password when user forgot it.
EDIT :
Now , i need to convert following code into ASIFormDataRequest from ASIHTTPRequest with email id parameter and authentication. can you help me now ?
`
[self setRequest:[ASIHTTPRequest requestWithURL:[NSURL URLWithString:#"http://abc.foo.com/api/forgot_password/"]]];
[request setUseKeychainPersistence:[useKeychain isOn]];
[request setDelegate:self];
[request setShouldPresentAuthenticationDialog:[useBuiltInDialog isOn]];
[request setDidFinishSelector:#selector(topSecretFetchComplete:)];
[request setDidFailSelector:#selector(topSecretFetchFailed:)];
[request startAsynchronous];
`
That's because ASIHTTPRequest doesn't include a -setPostValue:forKey: method. ASIFormDataRequest, on the other hand, does.
It sounds like you're using a pointer of type ASIHTTPRequest* to send a message to an instance of ASIFormDataRequest. That's okay if the pointer really points to a form data request, ASIFormDataRequest being a subclass of ASIHTTPRequest, but if you're sure enough about the type of the object that you can send it a message specific to it's type, you also know enough to either use the more specific type in the first place or use a type cast to let the compiler know that it doesn't need to complain.

Not able to get access token for google+ through Oauth 2.0 in iPhone application

I am trying to access Google+ APIs with Oauth 2.0 in iPhone Application. For this purpose I am using OauthConsumer library. I got the unauthorized request_token and also authorization code but not able to exchange that request_token for access_token using authorization code. I am getting error as "invalid_request". Below is the code snippet, am I doing anything wrong or missing any parameter?
Code:
-(void)getAccessTokenWithAuthorizationCode:(NSString *)code
{
NSURL *accessTokenURL = [NSURL URLWithString:#"https://accounts.google.com/o/oauth2/token"];
OAMutableURLRequest *accessRequest = [[OAMutableURLRequest alloc] initWithURL:accessTokenURL
consumer:consumer
token:requestToken
realm:nil // our service provider doesn't specify a realm
signatureProvider:nil]; // use the default method, HMAC-SHA1
[accessRequest setHTTPMethod:#"POST"];
OARequestParameter *authCode = [[OARequestParameter alloc] initWithName:#"code" value:code];
OARequestParameter *redirectURI = [[OARequestParameter alloc] initWithName:#"redirect_uri" value:kRedirectURI];
OARequestParameter *granType = [[OARequestParameter alloc] initWithName:#"grant_type" value:#"authorization_code"];
[accessRequest setParameters:[NSArray arrayWithObjects:authCode, redirectURI, granType, nil]];
OADataFetcher *fetcher = [[OADataFetcher alloc] init];
[fetcher fetchDataWithRequest:accessRequest
delegate:self
didFinishSelector:#selector(accessTokenTicket:didFinishWithData:)
didFailSelector:#selector(accessTokenTicket:didFailWithError:)];
}
FYI - I'm not familiar with Objective-C, but hopefully some knowledge of OAuth will help you figure this out.
"authorized request tokens" are used in OAuth 1.0
"authorization codes" are used in OAuth 2.0
I'm not seeing anything saying that OauthConsumer supports OAuth 2.0
You asked:
"am I doing anything wrong or missing any parameter?"
I think you are missing the client secret, which is necessary to exchange an authorization code for an access token in OAuth 2.0. See the Google OAuth 2.0 documentation for more information on what you need to provide to exchange an authorization code for an access token.
You might want to check out the Google Toolbox for Mac - OAuth 2 Controllers:
http://code.google.com/p/gtm-oauth2/wiki/Introduction

Resources