I need to connect and authenticate users from java desk top application , i have tried facebook-java-api using facebookjsonclient and facebookRestclient but not able to get session key. is there any changes in facebook due to which we r not able to connect , or is there asny other best java api or example how to connect. my code is
private static void getUserID(String email, String password){
String session = null;
try {
HttpClient http = new HttpClient();
http.getHostConfiguration().setHost("www.facebook.com");
String api_key = "key";
String secret = "sec";
FacebookJaxbRestClient client = new FacebookJaxbRestClient(api_key, secret);
System.out.println("====>"+client.isDesktop());
String token = client.auth_createToken();
System.out.println(" :::::::"+token);
System.out.println(" :::::::::: "+token);
PostMethod post = new PostMethod("/login.php?");
post.addParameter("api_key", api_key);
post.addParameter("email", email);
post.addParameter("pass", password);
int postStatus = http.executeMethod(post);
System.out.println("url : " + post.getURI());
System.out.println("Response : " + postStatus);
for (Header h : post.getResponseHeaders()) {
System.out.println(h);
}
session = client.auth_getSession(token); // Here I am getting error
System.out.println("Session string: " + session);
long userid = client.users_getLoggedInUser();
//System.out.println("User Id is : " + userid);*/
} catch (FacebookException fe) {
fe.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
}
AFAIK , there is no way as of now to connect to facebook from a "desktop app" in a straight forward way. You can use apache http client library to mimick a browser and get it done. But it cannot be guranteed to work always.I have also been trying to do it for sometime with some libraries,but they seem broken.
I've had some success doing this. My approach was to use an embedded browser to display the authentication to the user. Facebook handles the authentication and redirects you to a "login successful" page with the access token and expiration time tacked onto the URL as GET data. Most of the code below is for creating and displaying the browser using the org.eclipse.swt library.
private static final String APP_ID = "###########";
private static final String PERMISSIONS =
"COMMA SEPARATED LIST OF REQUESTED PERMISSIONS";
private String access_token;
private long expirationTimeMillis;
/**
* Implements facebook's authentication flow to obtain an access token. This
* method displays an embedded browser and defers to facebook to obtain the
* user's credentials.
* According to facebook, the request as we make it here should return a
* token that is valid for 60 days. That means this method should be called
* once every sixty days.
*/
private void authenticationFlow() {
Display display = new Display();
Shell shell = new Shell(display);
final Browser browser;
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 3;
shell.setLayout(gridLayout);
try {
browser = new Browser(shell, SWT.NONE);
} catch (SWTError e){
System.err.println("Could not instantiate Browser: " + e.getMessage());
display.dispose();
display = null;
return;
}
browser.setJavascriptEnabled(true);
GridData data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
data.horizontalSpan = 3;
data.grabExcessHorizontalSpace = true;
data.grabExcessVerticalSpace = true;
browser.setLayoutData(data);
final ProgressBar progressBar = new ProgressBar(shell, SWT.MOZILLA);
data = new GridData();
data.horizontalAlignment = GridData.END;
progressBar.setLayoutData(data);
/* Event Handling */
browser.addProgressListener(new ProgressListener(){
public void changed(ProgressEvent event){
if(event.total == 0) return;
int ratio = event.current * 100 / event.total;
progressBar.setSelection(ratio);
}
public void completed(ProgressEvent event) {
progressBar.setSelection(0);
}
});
browser.addLocationListener(new LocationListener(){
public void changed(LocationEvent e){
// Grab the token if the browser has been redirected to
// the login_success page
String s = e.location;
String token_identifier = "access_token=";
if(s.contains("https://www.facebook.com/connect/login_success.html#access_token=")){
access_token = s.substring(s.lastIndexOf(token_identifier)+token_identifier.length(),s.lastIndexOf('&'));
String expires_in = s.substring(s.lastIndexOf('=')+1);
expirationTimeMillis = System.currentTimeMillis() + (Integer.parseInt(expires_in) * 1000);
}
}
public void changing(LocationEvent e){}
});
if(display != null){
shell.open();
browser.setUrl("https://www.facebook.com/dialog/oauth?"
+ "client_id=" + APP_ID
+ "&redirect_uri=https://www.facebook.com/connect/login_success.html"
+ "&scope=" + PERMISSIONS
+ "&response_type=token");
while(!shell.isDisposed()) {
if(!display.readAndDispatch()){
display.sleep();
if(access_token != null && !access_token.isEmpty()){
try{ Thread.sleep(3000);}catch(Exception e){}
shell.dispose();
}
}
}
display.dispose();
}
}
So all you have to do is figure out what permissions you're going to need to have for your application to work. Be aware that "second dialog" permissions can be picked from by the user so there is no guarantee that you will actually have these permissions.
First off, you need to get the access_token and then I would recommend using restfb library. In order to get the token I would recommend reading this: https://developers.facebook.com/docs/authentication/
A simple summary:
HTTP GET: https://www.facebook.com/dialog/oauth?
client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&scope=email,read_stream&
response_type=token
Use the code you get from above and then, do: https://graph.facebook.com/oauth/access_token?
client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&
client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE
Exact the access_token and use FacebookClient from restfb to make the API requests.
Related
In order to improve app quality i'm working on testing: unit tests and UI tests. Since i'm having Dropbox support in the app i'd like to test it and i need to auth to Dropbox account before testing (in my android app the users are able to save the files, read them, rename, etc - basic file routines).
Dropbox provides Java/Android SDK v2 with examples but even command-line tool requires some manual actions - open browser app with the URL and select account:
// Run through Dropbox API authorization process
DbxRequestConfig requestConfig = new DbxRequestConfig("examples-authorize");
DbxWebAuth webAuth = new DbxWebAuth(requestConfig, appInfo);
DbxWebAuth.Request webAuthRequest = DbxWebAuth.newRequestBuilder()
.withNoRedirect()
.build();
String authorizeUrl = webAuth.authorize(webAuthRequest);
System.out.println("1. Go to " + authorizeUrl);
System.out.println("2. Click \"Allow\" (you might have to log in first).");
System.out.println("3. Copy the authorization code.");
System.out.print("Enter the authorization code here: ");
String code = new BufferedReader(new InputStreamReader(System.in)).readLine();
if (code == null) {
System.exit(1); return;
}
code = code.trim();
DbxAuthFinish authFinish;
try {
authFinish = webAuth.finishFromCode(code);
} catch (DbxException ex) {
System.err.println("Error in DbxWebAuth.authorize: " + ex.getMessage());
System.exit(1); return;
}
System.out.println("Authorization complete.");
System.out.println("- User ID: " + authFinish.getUserId());
System.out.println("- Access Token: " + authFinish.getAccessToken());
Any possibility to make Dropbox auth automatically without manual interaction? I expect to provide app key/secret, account email/password and get accessToken for the session.
PS. I'd like to avoid using Robelectric+Espresso and keep it in unit/integration tests, not in UI tests.
No, the Dropbox API doesn't offer a way to automate the app authorization flow.
Note that you can store and re-use access tokens though, so you may want to just get one for your test account once manually, and then re-use that.
Here is my test template (i hope it helps somebody).
You have to do TODO and run the test manually twice at least (to paste auth code and access token) and then you can do the testing. All the next tests invocations do not require to do anything manually.
public class DropboxFileSystemTest {
// credentials
private static final String APP_KEY = ""; // TODO : paste your app key
private static final String APP_SECRET = ""; // TODO : paste your app secret
// do run the test and follow the instructions
private static final String accountEmail = "test#domain.com"; // TODO : paste your test Dropbox account
private static String authCode; // TODO : run the test and paste auth code
private static String accessToken // TODO : run the test and paste access
private DbxAppInfo appInfo = new DbxAppInfo(APP_KEY, APP_SECRET);
// Run through Dropbox API authorization process
private DbxRequestConfig requestConfig = new DbxRequestConfig(DropboxFileSystemTest.class.getSimpleName());
private DbxWebAuth webAuth = new DbxWebAuth(requestConfig, appInfo);
private void startAuth() throws IOException {
DbxWebAuth.Request webAuthRequest = DbxWebAuth.newRequestBuilder()
.withNoRedirect()
.build();
String authorizeUrl = webAuth.authorize(webAuthRequest);
System.out.println("1. Go to " + authorizeUrl);
System.out.println("2. Click \"Allow\" (you might have to log in first). WARNING: log-in to " + accountEmail);
System.out.println("3. Copy the authorization code.");
System.out.println("4. Paste the authorization code to this test `this.authCode` value");
System.out.println("5. Re-run the test");
}
private DbxClientV2 client; // to be used for the requests
private void initWithAccessToken() {
DbxRequestConfig config = new DbxRequestConfig(UUID.randomUUID().toString());
client = new DbxClientV2(config, accessToken);
}
private void initAndVerifyAccount() throws DbxException {
initWithAccessToken();
// check expected account (trying to prevent user account to be wiped out)
DbxClientV2 client = DbxClientHolder.get().getClient();
FullAccount account = client.users().getCurrentAccount();
if (!account.getEmail().equals(accountEmail))
throw new RuntimeException("Wrong account: current is " + account.getEmail() + ", but " + accountEmail + " is expected");
}
private void clearFileSystem() throws FileSystemException {
// TODO : clear Dropbox file system
}
#Before
public void setUp() throws IOException, FileSystemException, DbxException {
auth();
clearFileSystem();
}
private void finishAuth() {
DbxAuthFinish authFinish;
try {
authFinish = webAuth.finishFromCode(authCode);
} catch (DbxException ex) {
System.err.println("Error in DbxWebAuth.authorize: " + ex.getMessage());
System.exit(1); return;
}
System.out.println("Authorization complete.");
System.out.println("- User ID: " + authFinish.getUserId());
System.out.println("- Access Token: " + authFinish.getAccessToken());
System.out.println();
System.out.println("1. Copy the access token");
System.out.println("2. Paste the access token to this test `this.accessToken` value");
System.out.println("3. Re-run the test");
accessToken = authFinish.getAccessToken();
}
private void auth() throws IOException, FileSystemException, DbxException {
if (accessToken == null) {
if (authCode != null ) {
finishAuth();
throw new RuntimeException("Manual actions required: copy-paste access token");
} else {
startAuth();
throw new RuntimeException("Manual actions required: copy-paste authCode");
}
} else {
initAndVerifyAccount();
}
}
#After
public void tearDown() throws FileSystemException {
if (client != null) {
clearFileSystem();
}
}
#Test
public void testSmth() {
// TODO : write your test using `this.client` for requests
}
I am using ex3ndr for creating a telegram client. now i want to send a message witch has a photo and a caption or description. I send photo using this code snippet:
private static void sendMedia(PeerState peerState, String fileName) {
TLAbsInputPeer inputPeer = peerState.isUser() ? new TLInputPeerContact(peerState.getId()) : new TLInputPeerChat(peerState.getId());
int task = api.getUploader().requestTask(fileName, null);
api.getUploader().waitForTask(task);
int resultState = api.getUploader().getTaskState(task);
Uploader.UploadResult result = api.getUploader().getUploadResult(task);
TLAbsInputFile inputFile;
if (result.isUsedBigFile()) {
inputFile = new TLInputFileBig(result.getFileId(), result.getPartsCount(), "file.jpg");
} else {
inputFile = new TLInputFile(result.getFileId(), result.getPartsCount(), "file.jpg", result.getHash());
}
try {
TLAbsStatedMessage res = api.doRpcCall(new TLRequestMessagesSendMedia(inputPeer, new TLInputMediaUploadedPhoto(inputFile), rnd.nextInt()), 30000);
res.toString();
} catch (IOException e) {
e.printStackTrace();
}
}
but I donot know how can add caption to this photo?(this code snippet is a sample from this url: ex3ndr sample
)
ex3ndr library only support layer 12 of Telegram API where sendMedia method doesn't support captions in photos. That's means this library is not able to send captions with photos, the layer should be updated before being able of doing so (and the repository seems to be abandoned).
To use my app, the user must log in to their instagram account and give my app permission to access their information.
Once this is done, a URL with a code attached to the back will be returned (e.g. www.google.com/code=123456789).
The code is the exchanged for an access token.
My question is:
Can my app automatically get the code from the url and use it instead of the user having to copy and paste it in?
Thank you for reading!
Code:
TextField code = new TextField("Enter Code: ");
Button button = new Button("Click here to authenticate");
String callbackUrl = "http://reveal-it.appspot.com/oauthtest";
String clientID = "XXX";
String clientSecret = "XXX";
Token EMPTY_TOKEN = null;
InstagramService service = new
InstagramAuthService().apiKey(clientId)
.apiSecret(clientSecret)
.callback(callbackUrl)
.build();
String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
button.addClickListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
getUI().getPage().open(authorizationUrl, "_blank");
next();
}
});
public void next(){
String verifierCode = code.getValue();
Verifier verifier = new Verifier(verifierCode);
Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
Instagram instagram = new Instagram(accessToken);
UserInfo userInfo = instagram.getCurrentUserInfo();
}
Step 1: Authenticate User
Step 2: Get URL with code attached at the back that user has to copy and paste into textfield
(This is a test url that prints the code)
These social platformas usually use oauth for login and right granting.
There exists a vaadin addon for this.
https://vaadin.com/directory#addon/oauth-popup-add-on
I am working on an Android application which allow user to write feedback and then the articleID, ticketID and ticketnumber of the user will be generated by the server and be returned to the user.
There are two activity in this application. MainActivity allow the user to enter their details and a submit button will start Process activity that will send the details to the server and shows the articleID, ticketID and ticketnumber that are returned.
The problem is, it will only work once every time the application is started. For example, a user open the application and enter his details, the submit button is pressed and the corresponding articleID, ticketID and ticketnumber are returned. Then he tries to submit a second one by returning to the previous activity. He enters his detail again and press submit. This time, null is returned.
Images of example is shown here http://imgur.com/a/uY6gR
However, the application works again if it is quitted and the RAM is cleared.
I tried to use this method here to restart the application but still it did not work.
Below is the kSoap code in the Process activity.
public class Process extends Activity{
private String URL = " /*WORKING URL*/";
private String NAMESPACE = "/*WORKING URL*/";
private String soapUsername = "/*WORKING USERNAME*/";
private String soapPass = "/*WORKING PASSWORD*/";
private String METHOD_NAME = "TicketCreate";
private String SOAP_ACTION = "/*WORKING URL*/";
private Handler handler = new Handler();
private Thread thread;
TextView emailT, subjectT, complaintT, responseT, nameT;
String email, subject, complaint, name;
String articleid , ticketid ,ticketnumber;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.process);
webservice();
nameT = (TextView) findViewById(R.id.name);
emailT = (TextView) findViewById(R.id.email);
subjectT = (TextView) findViewById(R.id.subject);
complaintT = (TextView) findViewById(R.id.complaint);
responseT = (TextView) findViewById(R.id.responsevalue);
Intent i = getIntent();
// Receiving the Data
name = i.getStringExtra("name");
email = i.getStringExtra("email");
subject = i.getStringExtra("subject");
complaint = i.getStringExtra("complaint");
// Displaying Received data
nameT.setText(name);
emailT.setText(email);
subjectT.setText(subject);
complaintT.setText(complaint);
Button fin= (Button)findViewById(R.id.finish);
fin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
finish();
}
});
}
public void webservice(){
thread = new Thread(){
public void run(){
try
{
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
// Set all input params
request.addProperty("UserLogin", soapUsername);
request.addProperty("Password", soapPass);
Hashtable<String, String> ticket = new Hashtable<String, String>();
ticket.put("Title", subject);
ticket.put("CustomerUser", email);
ticket.put("CustomerID", "soapwebnologin");
ticket.put("QueueID", "3");
ticket.put("State", "new");
ticket.put("PriorityID", "1");
ticket.put("Lock", "unlock");
ticket.put("OwnerID", "1");
request.addProperty("Ticket", ticket);
Hashtable<String, String> article = new Hashtable<String, String>();
article.put("Subject", subject);
article.put("Body", complaint);
article.put("ContentType", "text/plain; charset=utf8");
request.addProperty("Article", article);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
new MarshalHashtable().register(envelope);
envelope.dotNet = true;
envelope.bodyOut = request;
String check = checkSSL(URL);
if(check == "SSL"){
KeepAliveHttpsTransportSE httpT = new KeepAliveHttpsTransportSE("/*WORKING URL*/", /*WORKING PORT*/, METHOD_NAME, 15000);
httpT.debug = true;
httpT.call(SOAP_ACTION, envelope);
KvmSerializable ks = (KvmSerializable)envelope.bodyIn;
articleid = ks.getProperty(0).toString();
ticketid = ks.getProperty(1).toString();
ticketnumber = ks.getProperty(2).toString();
Log.e("dump Request: " ,httpT.requestDump);
Log.e("dump response: " ,httpT.responseDump);
Log.e("object response : ", ks.toString());
}
else{
HttpTransportSE httpT = new HttpTransportSE(URL);
httpT.debug = true;
httpT.call(SOAP_ACTION, envelope);
KvmSerializable ks = (KvmSerializable)envelope.bodyIn;
articleid = ks.getProperty(0).toString();
ticketid = ks.getProperty(1).toString();
ticketnumber = ks.getProperty(2).toString();
Log.e("dump Request: " ,httpT.requestDump);
Log.e("dump response: " ,httpT.responseDump);
Log.e("object response : ", ks.toString());
}
}
catch(Exception e)
{
e.printStackTrace();
}
handler.post(createUI);
}
};
thread.start();
}
final Runnable createUI = new Runnable() {
public void run(){
responseT.setText("Your ticket id =" + ticketid+ " Article id ="+ articleid+" TICKET NUMBER ="+ ticketnumber);
}
};
protected String checkSSL(String url){
String https = url.substring(0, 4);
if(https == "https"){
return "SSL";
}
else{
return "noSSL";
}
}
}
EDIT: When I rotate the the screen, it requested another ticket from the server and it actually works. I am so confused.
Apparently it is a bug which can be fixed by adding this line:
System.setProperty("http.keepAlive", "false");
I ran into an Android OS bug recently that is pretty harsh related to
HTTPS connections. Basically, what happens is this:
You want to setup a connection between the phone and a server, and you need to control both the input and the output. As a result, you
use URL.openConnection(), with setDoInput() and setDoOutput() set to
true:
URL url = new URL("https://blahblahblah.com"); URLConnection conn =
url.openConnection(); conn.setDoInput(true); conn.setDoOutput(true);
At some point you use both conn.getOutputStream() to write to the
stream, then conn.getInputStream() to get the response.
You're doing an HTTPS connection. Some people report this happening on normal HTTP, but I've only seen it happen on HTTPS.
The first request goes through fine and dandy.
The second time you try to make the request, the connection doesn't send any data out and doesn't receive any data; it looks like it
happens instantly. If you cast to an HttpURLConnection,
conn.getResponseCode() returns -1 instead of anything meaningful.
In other words, every other request, the request fails outright. This
is a noted bug in Android, but it isn't fixed yet in any released
versions. Even when it's fixed, you'll still have to deal with this on
older versions of Android.
There are a few workarounds. The first is to simply not use
URLConnection; if you can find some way around it, avoid it. The
second is to repeatedly make the same request until it works; it's a
little too much of a hack for my tastes, but it'll work.
Then there's the third workaround, which I do not claim to understand
why it fixes the issue but it does. Just set this setting when your
application begins:
System.setProperty("http.keepAlive", "false");
Unfortunately this has some drawbacks (keep-alive is a good thing
normally), but in comparison to mysteriously failed requests I'll
ditch it.
Source: http://daniel-codes.blogspot.com/2010_07_01_archive.html
And regarding the problems with orientation change, read here
Change screen orientation in Android without reloading the activity
My question is very similar to the one at this page, except that I don't have access to the remote server, nor know how it does its authentication.
I'm trying to maintain logged in status across webpages that I can request using webclient.getPage(). The website I'm accessing uses a standard login form with username, password pair. What I've done before is to create a little function to do that for me:
public static HtmlPage logIn(HtmlPage page) {
HtmlPage nextpage = null;
final HtmlForm form = page.getFormByName("login_form");
final HtmlSubmitInput button = form.getInputByValue("Login");
final HtmlTextInput username = form.getInputByName("username");
final HtmlPasswordInput password = form.getInputByName("password");
username.setValueAttribute("user_foo");
password.setValueAttribute("pwd_bar");
// hit submit button and return the requested page
try {
nextpage = button.click();
} catch (IOException e) {
e.printStackTrace();
}
return nextpage;
}
The problem with this is that I have to manually search the page returned by this function in order to find the link to the page I want. More troubling is that this only works for the page right after login, but for not other pages.
Instead, I would like to hold the login information within the browser simulator, "webclient", so that I can seamlessly access any protected page within the site. In addition to attempting the solution in the previous question (linked above), I have attempted the following solution without success:
private static void setCredentials(WebClient webClient) {
String username = "user_foo";
String password = "pwd_bar";
DefaultCredentialsProvider creds = (DefaultCredentialsProvider) webClient.getCredentialsProvider();//new DefaultCredentialsProvider();
try {
creds.addCredentials(username, password);
webClient.setCredentialsProvider(creds);
}
catch (Exception e){
System.out.println("!!! Problem login in");
e.printStackTrace();
}
Edited: here is the main function showing how I use webClient:
public static void main(String[] args) throws Exception {
// Create and initialize WebClient object
WebClient webClient = new WebClient(/*BrowserVersion.CHROME_16*/);
webClient.setThrowExceptionOnScriptError(false);
webClient.setJavaScriptEnabled(false);
webClient.setCssEnabled(false);
webClient.getCookieManager().setCookiesEnabled(true);
setCredentials(webClient);
HtmlPage subj_page = null;
//visit login page and get it
String url = "http://www.website.com/index.php";
HtmlPage page = (HtmlPage) webClient.getPage(url);
HtmlAnchor anchor = null;
page = logIn(page);
// search for content
page = searchPage(page, "recent articles");
// click on the paper link
anchor = (HtmlAnchor) page.getAnchorByText("recent articles");
page = (HtmlPage) anchor.click();
// loop through found articles
//{{{page
int curr_pg = 1;
int last_pg = 5;
page = webClient.getPage(<starting URL of the first article>); // such URLs look like: "www.website.com/view_articles.php?publication_id=17&page=1"
do {
// find sections on this page;
List <HtmlDivision> sections = new ArrayList<HtmlDivision>();
List <HtmlDivision> artdivs = new ArrayList<HtmlDivision>();
List <HtmlDivision> tagdivs = new ArrayList<HtmlDivision>();
sections = (List<HtmlDivision>) page.getByXPath("//div[#class='article_section']");
artdivs = (List<HtmlDivision>) page.getByXPath("//div[#class='article_head']");
tagdivs = (List<HtmlDivision>) page.getByXPath("//div[#class='article_tag']");
int num_ques = sections.size();
HtmlDivision section, artdiv, tagdiv;
// for every section, get its sub-articles
for (int i = 0; i < num_ques; i++) {
section = sections.get(i);
artdiv = artdivs.get(i);
tagdiv = tagdivs.get(i);
// find the sub-article details and print to xml file
String xml = getXMLArticle(artdiv, section.asText(), tagdiv);
System.out.println(xml);
System.out.println("-----------------------------");
}
//remove IllegalMonitorStateException *
synchronized (webClient) {
webClient.wait(2000); // wait for 2 seconds
}
String href = "?publication_id=17&page=" + curr_pg;
anchor = page.getAnchorByHref(href);
page = anchor.click();
System.out.println("anchor val: " + anchor.getHrefAttribute());
curr_pg++;
} while (curr_pg < last_pg);
//}}}page
webClient.closeAllWindows();
}
Other info: I do not have info about the remote site server's authentication mechanism since I have no access to it, but your help would be great. Thank you!