I working with restFB for calling FaceBook Graph api to login, get posts and etc of users.
Created an app in developers account of Facebook.
Tried to call user details, with token generated here,
https://developers.facebook.com/tools/explorer?method=GET&path=8560751784547897&version=v2.8
For Example: accessToken from the above url provides = EAA....F
I am able to get all user details, when I am hitting url in browser as follows,
https://graph.facebook.com/v2.8/me?fields=id,name,email,birthday?access_token=EAA....f
I am getting following response in browser,
{
"id": "1127949",
"name": "youtr name",
"email": "youmail\u0040gmail.com"
"birthday": "10/27/1998"
}
I used following code to generate accesstoken dynamically,
StringBuffer callbackURLbuffer = request.getRequestURL();
int index = callbackURLbuffer.lastIndexOf("/");
callbackURLbuffer.replace(index, callbackURLbuffer.length(), "").append("/callback");
callbackURL = URLEncoder.encode(callbackURLbuffer.toString(), "UTF-8");
String authURL = "https://graph.facebook.com/oauth/authorize?client_id="
+ facebookAppId
+ "&redirect_uri="
+ callbackURL
+ "&scope=user_about_me,"
+ "user_actions.books,user_actions.fitness,user_actions.music,user_actions.news,user_actions.video,user_activities,user_birthday,user_education_history,"
+ "user_events,user_photos,user_friends,user_games_activity,user_groups,user_hometown,user_interests,user_likes,user_location,user_photos,user_relationship_details,"
+ "user_relationships,user_religion_politics,user_status,user_tagged_places,user_videos,user_website,user_work_history,ads_management,ads_read,email,"
+ "manage_notifications,manage_pages,publish_actions,read_friendlists,read_insights,read_mailbox,read_page_mailboxes,read_stream,rsvp_event";
In my callbackURL servlet, I am getting accessToken with code value, as follows,
StringBuffer redirectURLbuffer = request.getRequestURL();
int index = redirectURLbuffer.lastIndexOf("/");
redirectURLbuffer.replace(index, redirectURLbuffer.length(), "").append("/callback");
redirectURL = URLEncoder.encode(redirectURLbuffer.toString(), "UTF-8");
code = request.getParameter("code");
if(null!=code) {
accessURL = "https://graph.facebook.com/oauth/access_token?client_id=" + facebookAppId +
"&redirect_uri=" + redirectURL + "&client_secret=" + facebookAppSecret + "&code=" + code;
webContent = getWebContentFromURL(accessURL);
accessToken = getAccessTokenFromWebContent(webContent);
other functions used for this above code,
private static String getWebContentFromURL(String webnames) {
try {
URL url = new URL(webnames);
URLConnection urlc = url.openConnection();
//BufferedInputStream buffer = new BufferedInputStream(urlc.getInputStream());
BufferedReader buffer = new BufferedReader(new InputStreamReader(urlc.getInputStream(), "UTF8"));
StringBuffer builder = new StringBuffer();
int byteRead;
while ((byteRead = buffer.read()) != -1)
builder.append((char) byteRead);
buffer.close();
String text=builder.toString();
return text;
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
And,
private static String getAccessTokenFromWebContent (String webContent) {
String accessToken = null;
int s = webContent.indexOf("access_token=") + ("access_token=".length());
int e = webContent.indexOf("&");
accessToken = webContent.substring(s, e);
return accessToken;
}
Lets say this accessToken = EAA....2
If I call the below url with this Token,
https://graph.facebook.com/v2.8/me?fields=id,name,email,birthday&access_token=EAA....2
I am getting following response,
{
"id": "1127949",
"name": "youtr name",
"email": "youmail\u0040gmail.com"
}
If I hit following url, with bio feild, I got error msg in json as follows,
{
"error": {
"message": "(#12) bio field is deprecated for versions v2.8 and higher",
"type": "OAuthException",
"code": 12,
"fbtrace_id": "ARkoFJVP/Jk"
}
}
can some one say why this is happening for me.
Take a look here, to get about the user permission.
https://developers.facebook.com/docs/facebook-login/permissions/#reference-user_about_me.
As per your comment, regarding debuggin your token, sounds like you didn't get the permission enabled for user_about_me by facebook.
You have to send Facebook for a review about your app and need to approve by Facebook, then only you can access the user details and other things.
Follow these steps,
Go to - https://developers.facebook.com/apps/your_app_id/review-status/
Click on Start a submission button.
Select the check boxes,which you needs for permission. Then Click add Items button.
Then click on Edit Notes for each permission.
Here, breif about your app with this permission and upload a video of demo of your app.
Facebook will review it and accept/reject as per the norms.
This is what you are missing and it causes for your problem..
Related
I Know this question has been asked multiple times, but I couldn't find one working for me.
Basically I am trying to get a youtube video basic info which I get the proper result for that but then when I trigger to get the comments of that video the error pops out saying:
There was a service error: 403 : Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.
My code:
public String getyoutubeitemfull_details(String URI) throws SQLException, IOException{
try {
YouTube youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest request) throws IOException {
}
}).setApplicationName("APP_ID").build();
String apiKey = "API Key";
YouTube.Videos.List listVideosRequest = youtube.videos().list("statistics");
listVideosRequest.setId("qUvPzjSWMSM");
listVideosRequest.setKey(apiKey);
VideoListResponse listResponse = listVideosRequest.execute();
Video video = listResponse.getItems().get(0);
BigInteger viewCount = video.getStatistics().getViewCount();
BigInteger Likes = video.getStatistics().getLikeCount();
BigInteger DisLikes = video.getStatistics().getDislikeCount();
BigInteger Comments = video.getStatistics().getCommentCount();
System.out.println("[View Count] " + viewCount);
System.out.println("[Likes] " + Likes);
System.out.println("[Dislikes] " + DisLikes);
System.out.println("[Comments] " + Comments);
CommentThreadListResponse videoCommentsListResponse = youtube.commentThreads()
.list("snippet").setVideoId("qUvPzjSWMSM").setMaxResults(50l).setTextFormat("plainText").execute();
List<CommentThread> videoComments = videoCommentsListResponse.getItems();
for (CommentThread videoComment : videoComments) {
CommentSnippet snippet = videoComment.getSnippet().getTopLevelComment().getSnippet();
System.out.println(" - Author: " + snippet.getAuthorDisplayName());
System.out.println(" - Comment: " + snippet.getTextDisplay());
System.out.println("\n-------------------------------------------------------------\n");
}
} catch (GoogleJsonResponseException e) {
System.err.println("There was a service error: " + e.getDetails().getCode() + " : "
+ e.getDetails().getMessage());
} catch (IOException e) {
System.err.println("There was an IO error: " + e.getCause() + " : " + e.getMessage());
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
FYI: So much of question that I have been through so far talk about adding listVideosRequest.setKey(apiKey); which I have it done. I also Have enable OAuth 2.0 enabled in my google console.
Thanks to #DalmTo for throwing to its direction.
Basically Api Key doesn't have priviledges to retrieve comments and things like that. for deep priviledges I had to use Oauth, which basically is being created the same was as API Key but in Oauth you receive a client_secrets.json file containing: client secret, client ID and etc...
Then you call that in you code.
Note: Their is verious ways of calling you client_secrets.json file but it depends on your need.
My way: Reader clientSecretReader = new InputStreamReader(
new FileInputStream("/home/Downloads/src/client_secrets.json"));
I am doing Salesforce trailhead from the link : https://trailhead.salesforce.com/modules/apex_integration_services/units/apex_integration_webservices.
In this tutorial they've use access_token to call the GET request. But they have not guided us how to get the access_token, which is an important steps to call the APEX Rest from outside.
I tied to do something like below its saying me the error:
https://ap5.salesforce.com/services/oauth2/token?client_id="3MVG9d8..z.hDcPJZPIzGJ5UZDuKCOqbH8CCGCPnmwQuRbwLZ_2f.thbqWMX82H7JRGx4
6VYyEkuwzQ9._ww5"&client_secret="1180508865211885204"&username="pXXXXXXXXXXXXXXX.com"&password="AgXXXXXXXX"&grant_type=password
I understood the concept now and thanks for sharing other links.
client_id, client_secret, username, password and grant_type should be sent in a HTTP POST body not in header.
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setHeader('Content-Type','application/x-www-form-urlencoded');
req.setEndpoint('https://ap5.salesforce.com/services/oauth2/token');
String CLIENT_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXX';
String CLIENT_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXX';
String USERNAME = 'XXXXXXXXXXXXXX';
String PASSWORD = 'XXXXXXXXXXXXXX';
req.setBody('grant_type=password' + '&client_id='+CLIENT_ID +
'&client_secret='+CLIENT_SECRET + '&username='+USERNAME + '&password='+PASSWORD);
Http http = new Http();
HTTPResponse response = http.send(req);
System.debug('Body ' + response.getBody());
System.debug('Status ' + response.getStatus());
System.debug('Status code ' + response.getStatusCode());
You might need to call api to get the access token.
Here's my code in C# to get the access token
async public static Task GetAccessTokenByUserNamePasswordAuthenticationFlowAsync(string username, string password, string token, string consumerKey, string consumerSecret)
{
HttpClient authClient = new HttpClient();
string sfdcConsumerKey = consumerKey;
string sfdcConsumerSecret = consumerSecret;
string sfdcUserName = username;
string sfdcPassword = password;
string sfdcToken = token;
string loginPassword = sfdcPassword + sfdcToken;
HttpContent content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{"grant_type","password"},
{"client_id",sfdcConsumerKey},
{"client_secret",sfdcConsumerSecret},
{"username",sfdcUserName},
{"password",loginPassword}
}
);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11; //tuanv2t: Salesforce has changed to use TLS 1.1 ->
//tuanv2t: Without, responseString will like this {"error":"unknown_error","error_description":"retry your request"}
HttpResponseMessage message = await authClient.PostAsync("https://login.salesforce.com/services/oauth2/token", content);
string responseString = await message.Content.ReadAsStringAsync();
//JObject obj = JObject.Parse(responseString);
//var oauthToken = (string)obj["access_token"];
//var serviceUrl = (string)obj["instance_url"];
var result = new GetAccessTokenResponse();
result.HttpResponseMessage = message;
//Convert json string into object
var accessTokenAPI = JsonConvert.DeserializeObject<AccessTokenAPI>(responseString);
if (accessTokenAPI != null)
{
result.AccessToken = new AccessTokenModel();
result.AccessToken.AccessToken = accessTokenAPI.access_token;
result.AccessToken.Id = accessTokenAPI.id;
result.AccessToken.InstanceUrl = accessTokenAPI.instance_url;
result.AccessToken.IssuedAt = accessTokenAPI.issued_at;
result.AccessToken.Signature = accessTokenAPI.signature;
result.AccessToken.TokenType = accessTokenAPI.token_type;
}
return result;
}
It's able to download all my source code example here ( include SOAP API as well )
https://bitbucket.org/tuanv2t/salesforceapidemo
So I have a tomcat server that I can successfully send a query such as... localhost:8080/AnarchyChatServer/AnarchyChatServlet?message=asdf&sendto=x&sendfrom=y
This will run the doGet() in my tomcat server, I have nothing in doPost()
Which will simply return asdf x y in the response BODY as HTML. Now in my C# I am trying to build the query string and send the message as such...
public string sendMessage(string message)
{
string url = "";
string response = "No server response.";
using (var wb = new WebClient())
{
UriBuilder baseUri = new UriBuilder("localhost:8080/AnarchyChatServer/AnarchyChatServlet");
message = message.Replace("&", "(AMPERSAND)");
message = message.Replace("?", "(QUESTIONMARK)");
string queryToAppend = "message=" + message;
if (baseUri.Query != null && baseUri.Query.Length > 1)
baseUri.Query = baseUri.Query.Substring(1) + "&" + queryToAppend;
else
baseUri.Query = queryToAppend;
url = baseUri.Uri.ToString();
queryToAppend = "sendto=" + sending;
if (baseUri.Query != null && baseUri.Query.Length > 1)
baseUri.Query = baseUri.Query.Substring(1) + "&" + queryToAppend;
else
baseUri.Query = queryToAppend;
url = baseUri.Uri.ToString();
queryToAppend = "sentfrom=" + account[0];
if (baseUri.Query != null && baseUri.Query.Length > 1)
baseUri.Query = baseUri.Query.Substring(1) + "&" + queryToAppend;
else
baseUri.Query = queryToAppend;
url = baseUri.Uri.ToString();
try
{
response = wb.DownloadString(baseUri.Uri);
}
catch (System.Net.WebException)
{
}
}
return response;
}
Ignore the hideous code reuse and whatnot. Basically the query building seems to work correct as if I output "url" it will return the proper url with the query string, but the issue is is that when I print out response after the call has been made to the server it just says "No server response" as it was initialized at the top of the C# code. Basically I'm wondering how I can query the server. Any insight would be helpful.
Your first problem is the lack of protocol in the Uri. Try this:
UriBuilder baseUri = new UriBuilder("http://localhost:8080/AnarchyChatServer/AnarchyChatServlet");
By the way... To debug these issues in the future, use:
catch (Exception ex)
{ <- breakpoint here
}
And examine ex. Or turn on breaking on thrown CLR exceptions in Visual Studio and debug the code (or just don't swallow the exception). Then you would see this:
Ignoring exceptions when debugging code is not a good idea in general...
I am trying to upload video to vimeo and I understand that you need the ticket_id in order to be able to upload.
The think is I can not figure out how to get this ticket_id by using scribe.
Does anyone have any example how to do this?
Thanks in advance.
When I use:
OAuthRequest request = new OAuthRequest(Verb.GET, "http://vimeo.com/api/rest/v2");
request.addQuerystringParameter("method", "vimeo.videos.upload.getTicket");
this results in:
<err code="401" expl="The consumer key passed was not valid." msg="Invalid consumer key"/>
When I use method:
request.addQuerystringParameter("method", "vimeo.videos.upload.getQuota");
everything works fine. I tried putting some fake api key in the vimeo.videos.upload.getQuota method. That also resulted in invalid key. So it is not like method vimeo.videos.upload.getQuota does not need the api key. In fact it does and if you don't provide the valid key it wil not work. Somehow when calling method vimeo.videos.upload.getTicket, with the same api key that works for the mehod getQuota, I get response:
<err code="401" expl="The consumer key passed was not valid." msg="Invalid consumer key"/>
full code with fake api keys:
public class VimeoServiceConcept {
public static void main(String[] args) {
String apikey="api key";
String apisecret="secret";
String accessToken="access token";
String accessTokenSecret="access token secret";
OAuthService service = new ServiceBuilder()
.provider(VimeoApi.class)
.apiKey(apikey)
.apiSecret(apisecret)
.build();
Token token = new Token(accessToken, accessTokenSecret);
OAuthRequest request = new OAuthRequest(Verb.GET, "http://vimeo.com/api/rest/v2");
// request.addQuerystringParameter("method", "vimeo.videos.upload.getQuota");
request.addQuerystringParameter("format", "xml");
request.addQuerystringParameter("method", "vimeo.videos.upload.getTicket");
request.addQuerystringParameter("upload_method", "post");
service.signRequest(token, request);
System.out.println(request.getCompleteUrl());
Response response = request.send();
System.out.println("Got it! Lets see what we found...");
System.out.println(response.getHeader("code"));
System.out.println(response.getCode());
System.out.println(response.getBody());
}
}
Try getting the ticket after you get the quota. I have never tried getting the ticket without the quota first because their documentation explicitly states you need to check quota before you get the ticket. It looks like you just comment out what you're not testing. Try this instead:
public class VimeoServiceConcept {
public static void main(String[] args) {
String apikey="api key";
String apisecret="secret";
String accessToken="access token";
String accessTokenSecret="access token secret";
OAuthService service = new ServiceBuilder().provider(VimeoApi.class).apiKey(apiKey).apiSecret(apiSecret).build();
OAuthRequest request;
Response response;
accessToken = new Token("your_token", "your_tokens_secret");
accessToken = checkToken(vimeoAPIURL, accessToken, service);
if (accessToken == null) {
return;
}
// Get Quota
request = new OAuthRequest(Verb.GET, vimeoAPIURL);
request.addQuerystringParameter("method", "vimeo.videos.upload.getQuota");
signAndSendToVimeo(request, "getQuota", true);
// Get Ticket
request = new OAuthRequest(Verb.GET, vimeoAPIURL);
request.addQuerystringParameter("method", "vimeo.videos.upload.getTicket");
request.addQuerystringParameter("upload_method", "streaming");
response = signAndSendToVimeo(request, "getTicket", true);
//... the rest of your code...
}
}
Here's checkToken:
/**
* Checks the token to make sure it's still valid. If not, it pops up a dialog asking the user to
* authenticate.
*/
private static Token checkToken(String vimeoAPIURL, Token vimeoToken, OAuthService vimeoService) {
if (vimeoToken == null) {
vimeoToken = getNewToken(vimeoService);
} else {
OAuthRequest request = new OAuthRequest(Verb.GET, vimeoAPIURL);
request.addQuerystringParameter("method", "vimeo.oauth.checkAccessToken");
Response response = signAndSendToVimeo(request, "checkAccessToken", true);
if (response.isSuccessful()
&& (response.getCode() != 200 || response.getBody().contains("<err code=\"302\"")
|| response.getBody().contains("<err code=\"401\""))) {
vimeoToken = getNewToken(vimeoService);
}
}
return vimeoToken;
}
Here's getNewToken:
/**
* Gets authorization URL, pops up a dialog asking the user to authenticate with the url and the user
* returns the authorization code
*
* #param service
* #return
*/
private static Token getNewToken(OAuthService service) {
// Obtain the Authorization URL
Token requestToken = service.getRequestToken();
String authorizationUrl = service.getAuthorizationUrl(requestToken);
do {
String code = JOptionPane.showInputDialog("The token for the account (whatever)" + newline
+ "is either not set or is no longer valid." + newline
+ "Please go to the URL below and authorize this application." + newline
+ "Paste the code you're given on top of the URL here and click \'OK\'" + newline
+ "(click the 'x' or input the letter 'q' to cancel." + newline
+ "If you input an invalid code, I'll keep popping up).", authorizationUrl + "&permission=delete");
if (code == null) {
return null;
}
Verifier verifier = new Verifier(code);
// Trade the Request Token and Verfier for the Access Token
System.out.println("Trading the Request Token for an Access Token...");
try {
Token token = service.getAccessToken(requestToken, verifier);
System.out.println(token); //Use this output to copy the token into your code so you don't have to do this over and over.
return token;
} catch (OAuthException ex) {
int choice = JOptionPane.showConfirmDialog(null, "There was an OAuthException" + newline
+ ex + newline
+ "Would you like to try again?", "OAuthException", JOptionPane.YES_NO_OPTION);
if (choice == JOptionPane.NO_OPTION) {
break;
}
}
} while (true);
return null;
}
Here's signAndSend:
/**
* Signs the request and sends it. Returns the response.
*
* #param request
* #return response
*/
public static Response signAndSendToVimeo(OAuthRequest request, String description, boolean printBody) throws org.scribe.exceptions.OAuthException {
System.out.println(newline + newline
+ "Signing " + description + " request:"
+ ((printBody && !request.getBodyContents().isEmpty()) ? newline + "\tBody Contents:" + request.getBodyContents() : "")
+ ((!request.getHeaders().isEmpty()) ? newline + "\tHeaders: " + request.getHeaders() : ""));
service.signRequest(accessToken, request);
printRequest(request, description);
Response response = request.send();
printResponse(response, description, printBody);
return response;
}
I have written a REST web service with Jersey Server (that totally rocks !).
I am now developing the client part of it, with Jersey Client as well.
On the server side, I have chosen a DIGEST authentication, because I personally think that BASIC authentication is an heresy that should be marked as "DEPRECATED" in our heads.
Unfortunately, I do not see any support of the Digest authentication on the client side.
For BASIC authentication, one does something like :
client.addFilter(
new HTTPBasicAuthFilter(
user,
password));
But I see no "HTTPDigestAuthFilter" counterpart.
Am I missing something ?
Thanks for your help,
Raphael
I have just implemented it.
I have created a feature request in the Jersey issue tracker, and posted my implementation there, as attachment :
https://jersey.dev.java.net/issues/show_bug.cgi?id=542
It works fine for communicating with a DIGEST authentication of a Tomcat server.
I have not tested for other web servers yet.
Here I wrote some random uri. Please fill your desired URI
For sample testing you can take help of google services which are available in the internet for open.
import javax.ws.rs.core.*;
import org.apache.commons.codec.digest.*;
import org.codehaus.jettison.json.*;
import com.sun.jersey.api.*;
public class DigestClient {
//Dividing into two parts because we need to send the last part of uri in our second request to service.
static String baseUri = "https://www.something.com";
static String subUri = "/later-part";
public static void main(String[] args) throws JSONException{
ClientConfig cc = new DefaultClientConfig();
Client client = Client.create(cc);
WebResource webResource = client.resource(baseUri+subUri);
ClientResponse response = webResource.get(ClientResponse.class);
// Basically in Digest-Authentication mechanism, we hit the rest service two times.
// First time with No Authentication, which returns some values (qop, nonce, realm) which are used as inputs in second call to rest service.
/*--------------- First call-----------------*/
// We get 401, Unauthorized
System.out.println(response.getStatus()+" "+response.getStatusInfo());
// Here is the complete header information
System.out.println(response.getHeaders());
// We need "WWW-Authenticate" part information for our second call to rest
System.out.println("WWW-Authenticate: \t" + response.getHeaders().get("www-Authenticate"));
String noAuthResp = response.getHeaders().get("www-Authenticate").toString();
noAuthResp = noAuthResp.replace("Digest ", "");
noAuthResp = noAuthResp.replace('[', '{');
noAuthResp = noAuthResp.replace(']', '}');
// Creating a JSONObject for easy information retrieval
JSONObject resp = new JSONObject(noAuthResp);
/*--------------- Second call-----------------*/
// Here client has to set the fields which was returned from the first call
String user = "postman"; // username
String password = "password"; // password
String realm = resp.getString("realm"); // realm value from the first rest-call response
String qop = resp.getString("qop"); //qop value from the first rest-call response
String nonce = resp.getString("nonce"); // nonce value from the first rest-call response
String opaque = resp.getString("opaque"); // Some times if we don't get this value, set it with ""
String algorithm = "MD5"; // The algorithm set by the client
int nonceCount = 678; // Some numerical input from the client
String clientNonce = "afdjas0"; // Some random text from the client for encryption
String method = "GET"; // HTTP method
String ha1 = new DigestClient().formHA1(user, realm, password);
String ha2 = new DigestClient().formHA2(method, subUri);
String responseCode = new DigestClient().generateResponse(ha1, nonce, nonceCount, clientNonce, qop, ha2);
// Header to be sent to the service
String value = "Digest username=\""+user+"\", realm=\""+realm+"\", nonce=\""+nonce+"\", uri=\""+subUri+"\", qop="+qop+", nc="+nonceCount+", cnonce=\""+clientNonce+"\", response=\""+responseCode+"\", opaque=\""+opaque+"\"";
// Hitting the service
response = webResource.header("authorization", value).type(MediaType.TEXT_PLAIN).accept("*").get(ClientResponse.class);
System.out.println("\nComplete Response:\n"+response+"\n");
String output = response.getEntity(String.class);
System.out.println("Response Text: "+output);
}
// For generating HA1 value
public String formHA1(String userName,String realm,String password){
String ha1 = DigestUtils.md5Hex(userName + ":" + realm + ":" + password);
return ha1;
}
// For generating HA2 value
public String formHA2(String method,String uri){
String ha2=DigestUtils.md5Hex(method + ":" + uri);
return ha2;
}
// For generating response at client side
public String generateResponse(String ha1,String nonce,int nonceCount,String clientNonce,String qop,String ha2){
String response=DigestUtils.md5Hex(ha1 + ":" + nonce + ":" + nonceCount + ":" +clientNonce +":" + qop + ":" +ha2);
return response;
}
}