Invalid parameter exception on client.auth_getSession() in Facebook java API - java

I want to connect to a my facebook application using the facebook java api 2.1.1(http://code.google.com/p/facebook-java-api/). My application is in "Desktop" mode so I should be able to access it outside of a web application. I have not defined any callback url for it as well. My code looks something like this.
FacebookJsonRestClient client = new FacebookJsonRestClient( FB_APP_API_KEY, FB_APP_SECRET );
String token = client.auth_createToken();
HttpClient http = new HttpClient();
http.setParams(new HttpClientParams());
http.setState(new HttpState());
final String LOGIN = "https://login.facebook.com/login.php";
GetMethod get = new GetMethod(LOGIN + "?api_key=" + FB_APP_API_KEY + "&v=1.0&auth_token=" + token );
http.executeMethod(get);
PostMethod post = new PostMethod(LOGIN);
post.addParameter(new NameValuePair("api_key", FB_APP_API_KEY));
post.addParameter(new NameValuePair("v", "1.0"));
post.addParameter(new NameValuePair("auth_token", token));
post.addParameter(new NameValuePair("email", "my-email"));
post.addParameter(new NameValuePair("pass", "my-password"));
http.executeMethod(post);
String session = client.auth_getSession(token);
However instead of returning the session the API throws an exception:
com.google.code.facebookapi.FacebookException: Invalid parameter
at com.google.code.facebookapi.FacebookJsonRestClient.parseCallResult(FacebookJsonRestClient.java:354)
at com.google.code.facebookapi.ExtensibleClient.callMethod(ExtensibleClient.java:535)
at com.google.code.facebookapi.ExtensibleClient.callMethod(ExtensibleClient.java:472)
at com.google.code.facebookapi.FacebookJsonRestClient.auth_getSession(FacebookJsonRestClient.java:278)
Can anyone please tell me whats wrong with this code? And what is the correct way to access a facebook application in desktop mode using the java api (v. 2.1.1).
Thanks for your help.
Regards
Nabeel Mukhtar

As far as I understand FB's API, you're not supposed to provide username and password manually but instead let the user input them manually and then allow the Facebook Login to redirect the user back to your application. This means that instead of providing "email" and "pass" you provide "next" and "cancel" URL:s instead.
This is purely a security feature of FB API and while the theory behind it is alright, the execution is far from optimal.

See this discussion thread on the Google Code site. There's a link in the that thread to a wiki page which explains how to do desktop auth.

Related

Accessing kerberos secured WebHDFS without SPnego

I have a working application for managing HDFS using WebHDFS.
I need to be able to do this on a Kerberos secured cluster.
The problem is, that there is no library or extension to negotiate the ticket for my app, I only have a basic HTTP client.
Would it be possible to create a Java service which would handle the ticket exchange and once it gets the Service ticket to just pass it to the app for use in a HTTP request?
In other words, my app would ask the Java service to negotiate the tickets and it would return the Service ticket back to my app in a string or raw string and the app would just attach it to the HTTP request?
EDIT: Is there a similar elegant solution like #SamsonScharfrichter described for HTTPfs? (To my knowledge, it does not support delegation tokens)
EDIT2: Hi guys, I am still completly lost. Im trying to figure out the Hadoop-auth client without any luck. Could you please help me out again? I already spent hours reading upon it without luck.
The examples say to do this:
* // establishing an initial connection
*
* URL url = new URL("http://foo:8080/bar");
* AuthenticatedURL.Token token = new AuthenticatedURL.Token();
* AuthenticatedURL aUrl = new AuthenticatedURL();
* HttpURLConnection conn = new AuthenticatedURL(url, token).openConnection();
* ....
* // use the 'conn' instance
* ....
Im lost already here. What initial connection do I need? How can
new AuthenticatedURL(url, token).openConnection();
take two parameters? there is no constructor for such a case. (im getting error because of this). Shouldnt a principal be somewhere specified? It is probably not going to be this easy.
URL url = new URL("http://<host>:14000/webhdfs/v1/?op=liststatus");
AuthenticatedURL.Token token = new AuthenticatedURL.Token();
HttpURLConnection conn = new AuthenticatedURL(url, token).openConnection(url, token);
Using Java code plus the Hadoop Java API to open a Kerberized session, get the Delegation Token for the session, and pass that Token to the other app -- as suggested by #tellisnz -- has a drawback: the Java API requires quite a lot of dependencies (i.e. a lot of JARs, plus Hadoop native libraries). If you run you app on Windows, in particular, it will be a tough ride.
Another option is to use Java code plus WebHDFS to run a single SPNEGOed query and GET the Delegation Token, then pass it to the other app -- that option requires absolutely no Hadoop library on your server. The barebones version would be sthg like
URL urlGetToken = new URL("http://<host>:<port>/webhdfs/v1/?op=GETDELEGATIONTOKEN") ;
HttpURLConnection cnxGetToken =(HttpURLConnection) urlGetToken.openConnection() ;
BufferedReader httpMessage = new BufferedReader( new InputStreamReader(cnxGetToken.getInputStream()), 1024) ;
Pattern regexHasToken =Pattern.compile("urlString[\": ]+(.[^\" ]+)") ;
String httpMessageLine ;
while ( (httpMessageLine =httpMessage.readLine()) != null)
{ Matcher regexToken =regexHasToken.matcher(httpMessageLine) ;
if (regexToken.find())
{ System.out.println("Use that template: http://<Host>:<Port>/webhdfs/v1%AbsPath%?delegation=" +regexToken.group(1) +"&op=...") ; }
}
httpMessage.close() ;
That's what I use to access HDFS from a Windows Powershell script (or even an Excel macro). Caveat: with Windows you have to create your Kerberos TGT on the fly, by passing to the JVM a JAAS config pointing to the appropriate keytab file. But that caveat also applies to the Java API, anyway.
You could take a look at the hadoop-auth client and create a service which does the first connection, then you might be able to grab the 'Authorization' and 'X-Hadoop-Delegation-Token' headers and cookie from it and add it to your basic client's requests.
First you'll need to have either used kinit to authenticate your user for application before running. Otherwise, you're going to have to do a JAAS login for your user, this tutorial provides a pretty good overview on how to do that.
Then, to do the login to WebHDFS/HttpFS, we'll need to do something like:
URL url = new URL("http://youhost:8080/your-kerberised-resource");
AuthenticatedURL.Token token = new AuthenticatedURL.Token();
HttpURLConnection conn = new AuthenticatedURL().openConnection(url, token);
String authorizationTokenString = conn.getRequestProperty("Authorization");
String delegationToken = conn.getRequestProperty("X-Hadoop-Delegation-Token");
...
// do what you have to to get your basic client connection
...
myBasicClientConnection.setRequestProperty("Authorization", authorizationTokenString);
myBasicClientConnection.setRequestProperty("Cookie", "hadoop.auth=" + token.toString());
myBasicClientConnection.setRequestProperty("X-Hadoop-Delegation-Token", delegationToken);

OpenAM Authentication - logout

I'm beginner with OpenAM, I'm working on an existing project.
I use this documentation to improve our authentication service:
http://docs.forgerock.org/en/openam/10.0.0/dev-guide/index/chap-authentication.html
The login works fine, I receive my token Id and add it in the cookies. I stay connected when I browse restricted web pages.
Now I want to do a clean logout.
When you read the documentation about logout, they propose this code:
protected void logout(AuthContext lc)
throws AuthLoginException {
lc.logout();
System.out.println("Logged Out!!");
}
But in my program, I do not have the login AuthContext anymore.
Is there a way to get or create an AuthContext associated with my user ? This call is it necessary ? (actually, We modify the cookies to be rejected by OpenAM)
Thank you.
Answer:
SSOToken ssoToken = SSOTokenManager.getInstance().createSSOToken(tokenId);
AuthContext authContext = new AuthContext(ssoToken);
authContext.logout();
Firstly I think you should be able to create a new AuthContext by having access to the session token, by using this constructor.
Secondly it is not necessary to use the ClientSDK to perform authentication remotely, you could also just use the REST APIs, which probably would be a bit more lightweight.

jBPM 6 API usage to call REST API

I looked through the jBPM6 user guide, and I found that there are URL's available for each operation, like: http://serverurl:8080/business-central/rest/task/query?potentialOwner=bpmuser
This URL is used to get the tasks assigned to bpmuser. I'm able to request this URL using Google's REST client without any errors. The problem is though, that I'm getting an authorization error when I try to request this URL from my Java program. Could anybody help me with the problem I'm having?
You can send authentication details in header as below.
String authData = "krisv" + ":" + "krisv";
String encoded = new sun.misc.BASE64Encoder().encode(authData.getBytes());
get.setHeader("Authorization", "Basic " + encoded);
See my answer in this thread for a working example.
Did you read the documentation?
http://docs.jboss.org/jbpm/v6.0.1/userguide/jBPMRemoteAPI.html
Are you sending the user / password?
Look at this section -> 17.1.1. The REST Remote Java RuntimeEngine Factory

Google Client Login Handling AuthToken

I have a non-gae, gwt application and it have a module that allows users to create documents online via google docs api.
To do that, i first ask user to enter the name and type of the document, than create a new document via google docs api with the given parameters and onSucces part of that servlet returns edit link which is used in client side to open a new page to edit the created document.
Problem that, eachtime i try to open that editLink user have to enter login informations. To solve this i try to use Google Client Login but i am totally lost i think.
First i have username and password of user and can directly use them, after searching i tried some examples which usually returns a token like this and that. Now what should i do with token? How can it be used to complete login process or should totally find another way to do login? All those oauth1,oauth2 and etc. documentations confused me a little bit.
here are my steps;
Server side;
LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();
// Login
DocumentList docList = new DocumentList("document");
docList.login(ServletUtil.googleDocsLoginInfo().get("username"), ServletUtil.googleDocsLoginInfo().get("password"));
//Create document with a unique suffix
String docName= parameterName+ "-Created-" + new Date();
docList.createNew(docName, dosyaTur);
// Find the created document and store editLink
DocumentListFeed feed = docList.getDocsListFeed("all");
for (final DocumentListEntry entry : feed.getEntries()) {
if (entry.getTitle().getPlainText().equals(docName)) {
hashMap.put("editlink", entry.getDocumentLink().getHref());
}
}
return hashMap;
And Client side;
#Override
public void onSuccess(LinkedHashMap<String, String> result) {
String editLink = result.get("editlink");
Window.open(editLink,"newwindow","locationno");
}
Thanks for your helps.
If I may suggest using OAuth instead of Client Login, which is outdated and less secure.
The functionality is basically the same (for OAuth 2.0 there are more ways to handle the login).
I know, trying to understand how to access the api via OAuth is very confusing, so I try to break it down a little:
If you use OAuth 2.0 you may want to use a library like this one or you can try out my own (although I wrote it for Android, this could work with other Java Apps including Web Apps)
This is what happens when a user logs in the first time with your app:
> Your App sends an authorization request containing some information about your app - for example your app needs to be registered with google and therefore has a special application key
< The Server sends you a url, open it in a new browser window and let the user login. There he will be asked to allow your app to access his account (or some parts of it) - when he confirms he will be prompted an Authorization Code which he needs to copy
> The user gets back to your app, where you will ask him for the authorization code. After he gave it, your app connects again with the server and sends the code as some kind of authorization grant of the user.
< The Server answers with a access token
All you need to do is use this access token (also called a bearer token) in all your requests to the server hidden in the header message.
I am sorry I can't give you a more precise answer right now, since I never used GWT. All I can say is, try using OAuth2, it is actually very simple (after you learn what all this confusing things like authorization flow, bearer token etc are) and really comfortable for your user, once the he has done the first login.

Acegi throws AuthenticationCredentialsNotFoundException when opening URl with BrowserLauncher 2

We have a JSF web application that uses Acegi security. We also have a standalone Java Swing application. One function of the Swing app is to load the user's home page in a browser window.
To do this we're currently using Commons HttpClient to authenticate the user with the web app:
String url = "http://someUrl/j_acegi_security_check";
HttpClient client = new HttpClient();
System.setProperty(trustStoreType, "Windows-ROOT");
PostMethod method = new PostMethod(url);
method.addParameter("j_username", "USERNAME");
method.addParameter("j_password", "PASSWORD");
int statusCode = client.executeMethod(method);
if (statusCode == HttpStatus.SC_MOVED_TEMPORARILY ) {
Header locationHeader= method.getResponseHeader("Location");
String redirectUrl = locationHeader.getValue();
BrowserLauncher launcher = new BrowserLauncher();
launcher.openURLinBrowser(redirectUrl);
}
This returns a HTTP 302 redirect response, from which we take the redirect url and open it using BrowserLauncher 2. The url contains the new session ID, something like:
http://someUrl/HomePage.jsf;jsessionid=C4FB2F643CE48AC2DE4A8A4C354033D4
The problem we're seeing is that Acegi processes the redirect but throws an AuthenticationCredentialsNotFoundException. It seems that for some reason the authenticated credentials cannot be found in the security context.
Does anyone have an idea as to why this is happening? If anyone needs more info then I'll be happy to oblige.
Many thanks,
Richard
I have never done Acegi/SpringSecurity, but the symptoms are clear enough: some important information is missing in the request. You at least need to investigate all the response headers if there isn't something new which needs to be passed back in the header of the subsequent request. Maybe another cookie entry which represents the Acegi credentials.
But another caveat is that you in fact cannot open just the URL in a local browser instance, because there's no way to pass the necessary request headers along it. You'll need to have your Swing application act as a builtin webbrowser. E.g. get HTML response in an InputStream and render/display it somehow in a Swing frame. I would check if there isn't already an existing API for that, because it would involve much more work than you'd initially think .. (understatement).
In this case you can do Basic Authentication and set this header in every request instead of sending the jsessionid:
AUTHORIZATION:Basic VVNFUk5BTUU6UEFTU1dPUkQ=
The token VVNFUk5BTUU6UEFTU1dPUkQ= is the username and the password encoded base64.
Example:
scott:tiger
is:
c2NvdHQ6dGlnZXI=
One more thing: use SSL.

Categories