I am trying to build authentication flow in our app for facebook in java. I am using facebook4j library.
My corresponding code is as follows -
public String authenticate() throws IOException {
Facebook facebook = new FacebookFactory().getInstance();
String redirectURL = facebook.getOAuthAuthorizationURL("http://localhost:9099/default/facebook/verify.html");
servletResponse.sendRedirect(redirectURL);
return null;
}
public String verify() throws Exception {
String code = servletRequest.getParameter("code");
Facebook facebook = new FacebookFactory().getInstance();
AccessToken accessToken = facebook.getOAuthAccessToken(code);
String token = accessToken.getToken();
servletResponse.getWriter().write(token);
return null;
}
I am getting error after redirection on this line -
AccessToken accessToken = facebook.getOAuthAccessToken(code);
The error is as follows -
FacebookException{statusCode=400, errorType='OAuthException', errorMessage='redirect_uri isn't an absolute URI. Check RFC 3986.', errorCode=191, errorSubcode=-1, version=2.2.2}
at facebook4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:179)
at facebook4j.internal.http.HttpClientWrapper.request(HttpClientWrapper.java:65)
at facebook4j.internal.http.HttpClientWrapper.get(HttpClientWrapper.java:97)
at facebook4j.auth.OAuthAuthorization.getOAuthAccessToken(OAuthAuthorization.java:107)
redirectURL that I am getting from facebook in first call is -
https://www.facebook.com/dialog/oauth?client_id=4161XXXXXX6389&redirect_uri=http%3A%2F%2Flocalhost%3A9099%2Fdefault%2Ffacebook%2Fverify.html&scope=email,public_profile,user_friends
tried without using encoding too -
https://www.facebook.com/dialog/oauth?client_id=4161XXXXXX6389&redirect_uri=http://localhost:9099/default/facebook/verify.html&scope=email,public_profile,user_friends
It is redirecting properly to 'verify' having url something like -
http://localhost:9099/default/facebook/verify.html?code=AQCE4aaIpE_c94J3NVNjge_YL_OP84vPIgUauvfRRXNCj_FOK8U2kfSxfKGrjWnFL1dqMeM8q22M6UaVbGsTpTQOQmjxYILdFHKFiSFd0Ycf_ByBE9rNX_yxvFnJ3RNLf7bjCT4C1uXuuqCXHZjVNN1lBb3LWUHz7eNkq0r8K14x7ZEVIWjbll-Vqys1FZuCIVDBrI4StoYkZR1rpCsoSqq7VdCIX3zawnw_nbPZBZU7iUeZJiBbahYjWkHIn47b9AQb3hZxxpe4xxXHXfDsP_h2fhC1YYioJbwGq4QbnWpUrP7aF-0Q_wF71zn4txCQLd4#=
facebook4j.properties
oauth.appId=416XXXXXXXXX389
oauth.appSecret=9ed3XXXXXXb6acXXXXXXXXc7acXXXX5
oauth.permissions=email,public_profile,user_friends
My Facebook App basic settings are -
The important advanced settings are -
I am totally aware that similar question has been posted earlier multiple times. I have gone through almost every question & I tried almost everything suggested to resolve this issue. But due to some reason it is not working. I decided to post my problem here after spending 3 days on the same issue.
I would highly appreciate if someone points out where exactly am I going wrong.
The redirect_uri parameter has to be specified when exchanging the code for a token as well (and has to be the same as specified earlier in the login dialog call).
I’d assume that since you are using new FacebookFactory().getInstance() in your second method, that is not the case. Take a look at the basic implementation here, https://github.com/roundrop/facebook4j-oauth-example/tree/master/src/main/java/facebook4j/examples/signin
In SignInServlet, the Facebook object instance is stored into the session, and then in CallbackServlet that same instance is retrieved and used again. Therefor, it still holds the redirect_uri value that was initially used when the Auth dialog was called, and will re-use that same value when exchanging the code for a token.
Related
I'm currently working with Google's Games API. The client sends through a user's authorization code, alongside their GPlay ID.
I'm sending this off to validate with Google, with;
var tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
new NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
"https://www.googleapis.com/oauth2/v4/token",
client_id,
client_secret,
idTokenString,
"")
.execute()
Where the client_id and client_secret are retrieved from our client_secret as retrieved from Google, and the idTokenString is the authorization code as provided by the user logging in to the client (format: 4/xxxxx..).
After retrieving the tokenResponse, the following will return the access token without issue;
var accessToken = tokenResponse.getAccessToken()
However, the idToken as retrieved from:
var idToken = tokenResponse.getIdToken()
returns with null. As such, attempting to get the user's data to validate they're the legitimate owner of the account with;
var idToken = tokenResponse.parseIdToken()
will return a nullpointer exception.
From googling on the topic, some users seem to think that the parseIdToken method is no longer in use, and that only the accessToken can be used to retrieve such information.
However, any solutions I've found have all required use of the getIdToken, which is also returning with null.
Does anyone have any ideas on what I may be doing wrong here, or if there's another expected method for retrieving the user's details after login?
It might be because getIdToken() is in BETA.
As stated in the documentation - Google API Client Library for Java:
Features marked with #Beta at the class or method level are subject to change. They might be modified or removed in any major release. Do not use beta features if your code is a library itself (that is, if your code is used on the CLASSPATH of users outside your control).
You might want to use getIdToken from GoogleSignInAccount as a workaround.
You can check the release notes for any update.
Hope this helps.
I am trying to make a Java class which would call upon Google's API to recreate an access token to a user's account with new permissions/larger scope. This class is to be instantiated by a Java servlet I had created. I want a function within that class to return a new access token. For this class to do that, I am using the Scribe library.
In Scribe's quick guide, there are two steps which concern me and have me stumped:
Step Three: Making the user validate your request token
Let’s help your users authorize your app to do the OAuth calls. For
this you need to redirect them to the following URL:
String authUrl = service.getAuthorizationUrl(requestToken);
After this either the user will get a verifier code (if this is an OOB
request) or you’ll receive a redirect from Twitter with the verifier
and the requestToken on it (if you provided a callbackUrl)
Step Four: Get the access Token
Now that you have (somehow) the verifier, you need to exchange your
requestToken and verifier for an accessToken which is the one used to
sign requests.
Verifier v = new Verifier("verifier you got from the user");
Token accessToken = service.getAccessToken(requestToken, v); // the requestToken you had from step 2
It does not seem to specify how to get that verifier from the user. How am I supposed to do that? How do I redirect my user to the authURL, and how do I get it to send its verifier back to this class of mine, which initiated the request to begin with?
If this is unclear, let me structure the question differently, taking Scribe out of the equation: To get an authorization code from Google (which would be used to then get a refresh token and access token), I would execute the following URL connection from within the servlet (yes, I've tried to answer this problem without the Scribe library, and still can't figure it out):
URL authURL = new URL("https://accounts.google.com/o/oauth2/auth");
HttpsURLConnection authCon = (HttpsURLConnection) authURL.openConnection();
authCon.setRequestMethod("GET");
authCon.setDoOutput(false);
authCon.setConnectTimeout(100000);
authCon.setRequestProperty("response_type", "code");
authCon.setRequestProperty("client_id", CLIENT_ID);
authCon.setRequestProperty("redirect_uri",
"http://**************.com/parseAuth/");
authCon.setRequestProperty("scope", convertToCommaDelimited(scopes));
authCon.setRequestProperty("state", csrfSec);
authCon.setRequestProperty("access_type", "offline");
authCon.setRequestProperty("approval_prompt", "auto");
authCon.setRequestProperty("include_granted_scopes", "true");
What has me stuck is what I should be putting for the redirect URI. After getting the user's approval for the new scope, this authorization URL would return an authorization code to the redirect URI, and seemingly nothing to whatever called it. (Am I correct in this?) So if I have another servlet as the redirect URI to parse/extract the authorization code from the response, how in the world do I get that authorization code back to my first, initial servlet? It seems to me that there is no way to have it give back the value to the servlet, in the same position of the code from which the URL was called. It looks like the function has to end there, and all new action must take place within that new servlet. But if that is the case, and I send that auth code to Google's API which would send back a refresh token and access token to ANOTHER servlet I would make to be its redirect URI, how do I possibly get that information back to what it is which called the initial servlet to begin with? That seems to be the same problem at its core, with the problem I am having with Scribe.
I've been stuck on this for many hours, and can't seem to figure out what it is I am supposed to do. I feel like I am missing some key concept, element, or step. I need this clarified. If it is at all relevant, my servlet is hosted on a Jboss application server on OpenShift.
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.
I am trying to implement the rest api sample given in the salesforce site link below.
http://wiki.developerforce.com/page/Getting_Started_with_the_Force.com_REST_API
I have set up project as said in the link, but when I am executing the project I am getting an error as "Error - no access token". When I do debug, I came to know that the variable accessToken is null.
String accessToken = (String)
request.getSession().getAttribute("ACCESS_TOKEN");
I am bit confused about this problem.
Please help me in this regard.
It seems you are missing this part in your code:
// Set a session attribute so that other servlets can get the
// access token
request.getSession().setAttribute(ACCESS_TOKEN, accessToken);
// We also get the instance URL from the OAuth response, so set it
// in the session too
request.getSession().setAttribute(INSTANCE_URL, instanceUrl);
I'm doing a simple redirect after calling OAuth2::retrieveAccessToken() with Play Framework. I'm having funny characters appended to the URL that I never put there, so the end result looks as follows:
http://localhost:9000/#_=_
Where on earth does the #_=_ come from? Here's my route definition from the routes file:
GET / Application.index
Here's the code snippet of the controller dealing with the Facebook authentication:
public static void facebookConnect() {
OAuth2 facebook = new OAuth2(
"https://graph.facebook.com/oauth/authorize",
"https://graph.facebook.com/oauth/access_token",
"2#############6",
"c##############################2"
);
if(OAuth2.isCodeResponse()) {
OAuth2.Response oauthResponse = facebook.retrieveAccessToken(facebookAuthUrl());
if(oauthResponse.error == null) {
//... Somewhere here, something is causing #_=_ to be appended to the URL?
Application.index();
}
}
facebook.retrieveVerificationCode(facebookAuthUrl());
}
EDIT:
According to this page, Facebook changed their API recently to include the = if request_uri is empty, the problem is...my request_uri has been explicitly set?
This was added after a security update.
From the Facebook developer blog:
Change in Session Redirect Behavior
This week, we started adding a fragment #_=_ to the redirect_uri
when this field is left blank. Please ensure that your app can handle
this behavior.
Maybe these characters come from the facebook callback. I was getting a FB callback like
localhost:9000?someparams#code=verylongcodefromfacebook
I could get rid of the # just by sanitizing the params before requesting the access token.