Android - Facebook Connect, Check server side - android

I was wondering how can I check if the user is connected to facebook on server side if connection comes from an Android APP.
Indeed, on my website I can easily check that in PHP when the request comes from a browser with :
// Try to get the user's id on Facebook
$userId = $this->facebook->getUser();
// If user is not yet authenticated, the id will be zero
if($userId == 0){
// Generate a login url
$data['url'] = $this->facebook->getLoginUrl(array('scope'=>'email'));
$response = array('status' => 'failed', 'error' => 'facebook_not_authentificated', 'url' => $data['url']);
$data = json_encode($response);
echo $data;
return 0;
}
But when I call the url in my Android App, I do not pass this step and I get the JSON response {'status' => 'failed', 'error' => 'facebook_not_authentificated', 'url' => '...' }
Any idea ?
Thanks

If you want to check if the user still authenticated in the device, you should use Facebook Android SDK on the device, not use the server side.
On the other hand, you can send the token you got from Facebook and send it to your server and check if it gives you a Facebook User.

If someone need the answer i finally found out after many hours of research ...
You have to pass the token (token that you get into your android app), to the server and tell the server to use it :
$facebook->setAccessToken($access_token);
To find out the token in your app :
Session.openActiveSession(InscriptionConnexionActivity.this, true, new Session.StatusCallback() {
// callback when session changes state
#Override
public void call(final Session session, SessionState state, Exception exception) {
if (session.isOpened()) {
// make request to the /me API
Request.executeMeRequestAsync(session, new Request.GraphUserCallback() {
// callback after Graph API response with user object
#Override
public void onCompleted(GraphUser user, Response response) {
if (user != null) {
System.out.println(user.getName() + " : connected");
$my_token = session.getAccessToken());
}
}
});
}
}
});

Related

AppAuth: Get authorisation code with iOS & Android app and access token on server

I'm implementing the OpenId AppAuth SDK for IOS and Android.
https://github.com/openid/AppAuth-iOS
https://github.com/openid/AppAuth-android
Our app oAuth flow:
In our app the user starts a oAuth login using the AppAuth SDK
(IOS or Android).
App retreives the authorisation code.
The app sends the authorisation code to the backend server.
The backend server creates the access token.
The app receives the following data from the backend server to perform the oAuth flow:
authorization endpoint
client_id
response_type
scope
Problem
The Android app works like a charm.
A user can login using AppAuth and the app receives the authorization code from the redirectURL.
The IOS app however...
AppAuth does open the requested login screen and can perform the oAuth login.
Then...
AppAuth dispatches an error in the callback from method:
[OIDAuthState authStateByPresentingAuthorizationRequest:presentingViewController:callback:]
The callback error:
"Connection error making token request to '': incorrect URL."`Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSLocalizedDescription=unsupported URL`
The error is correct, because an empty NSURL is used as a token_endpoint in the ServiceConfiguration.
The app does not have the token endpoint, ony the authorization endPoint.
It seems like AppAuth is automatically requesting the access token, but I only need to request the authorization code.
The Android app also uses an empty url in the ServiceConfiguration, but does not start the token request.
How can I disable automatic token retreival, using AppAuth-iOS?
Android code (java):
private void startOAuthAuthentication(){
// Create the service coniguration
// Note: The app does not have a token endpoint. An empty Uri value is used for the tokenEndpoint param
AuthorizationServiceConfiguration serviceConfig =
new AuthorizationServiceConfiguration(
Uri.parse(MY_AUTHORISATION_ENDPOINT), // authorization_endpoint
Uri.parse("")); // token_endpoint
// Build the request
AuthorizationRequest.Builder authRequestBuilder = new AuthorizationRequest.Builder(
serviceConfig,
MY_CLIENT_ID,
MY_RESPONSE_TYPE,
MY_REDIRECT_URL);
AuthorizationRequest authRequest = authRequestBuilder
.setScope(MY_SCOPE)
.setCodeVerifier(null)
.setLoginHint(null)
.build();
// Start Authorization
AuthorizationService authService = new AuthorizationService(getActivity());
Intent authIntent = authService.getAuthorizationRequestIntent(authRequest);
oAuthActivityResultLauncher.launch(authIntent);
}
// ActivityResultLauncher
ActivityResultLauncher<Intent> oAuthActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
AuthorizationResponse resp = AuthorizationResponse.fromIntent(data);
AuthorizationException ex = AuthorizationException.fromIntent(data);
if(resp != null && resp.authorizationCode != null){
// app received the authorizationCode
// resp.authorizationCode
}
}
}
});
IOS code (obj-c):
-(void) startOAuthAuthentication
{
// Create the service coniguration
// Note: The app does not have a token endpoint. An empty NSURL value is used for the tokenEndpoint param.
OIDServiceConfiguration *config =
[[OIDServiceConfiguration alloc]
initWithAuthorizationEndpoint:[NSURL URLWithString:MY_AUTHORISATION_ENDPOINT]
tokenEndpoint:[NSURL URLWithString:#""]];
// Create the Authorization Request
OIDAuthorizationRequest *request =
[[OIDAuthorizationRequest alloc] initWithConfiguration:config
clientId:MY_CLIENT_ID
clientSecret:nil
scope:MY_SCOPE
redirectURL:MY_REDIRECT_URL
responseType:MY_RESPONSE_TYPE
state:MY_STATE
nonce:nil
codeVerifier:nil
codeChallenge:nil
codeChallengeMethod:nil
additionalParameters:nil];
// Start Authorization
AppDelegate *appDelegate =
(AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.currentAuthorizationFlow =
[OIDAuthState authStateByPresentingAuthorizationRequest:request
presentingViewController:self
callback:^(OIDAuthState *_Nullable authState,
NSError *_Nullable error) {
if (authState) {
// App does not receive the authState
} else {
// App always receives the following the error:
// "Connection error making token request to '': incorrect URL."
// Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSLocalizedDescription=unsupported URL
}
}];
}

aws cognito user get id token android

I'm trying to get the current logged in user's id token for aws cognito in android.
I found this example:
session.getIdToken().getJWTToken()
where session is a CognitoUserSession object
I can't seem to figure out a way to get the current cognitousersession after the login call has been made.
I'm using the default authenticator activity from the notes tutorial:
https://docs.aws.amazon.com/aws-mobile/latest/developerguide/tutorial-android-aws-mobile-notes-auth.html
It says that the tokens are stored in the shared preferences, but I can't figure out how to retrieve them on future activities so that I can make calls to the api gateway using the id token.
The AWS Android SDK will return the JWT token without a network call when the token is not/will not expire.
The threshold for when a token should be refreshed can be set with the CognitoIdentityProviderClientConfig.setRefreshThreshold(long) method.
If you are stil curious how to retrieve the token yourself, then the code can be found in readCachedTokens() method
https://github.com/aws/aws-sdk-android/blob/master/aws-android-sdk-cognitoidentityprovider/src/main/java/com/amazonaws/mobileconnectors/cognitoidentityprovider/CognitoUser.java#L2116
As nobody has answered yet, this might help you out, be aware this is JS code:
This is my routine to receive the session from an already logged in user.
after this, i'm able to access tokens.
var user_data = {
UserPoolId: AWSConfiguration.UserPoolId,
ClientId: AWSConfiguration.ClientAppId
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(user_data);
if (userPool.getCurrentUser() != null) {
userPool.getCurrentUser().getSession(function (err, session) {
if (err) {
window.location.href = "login.html";
}
var user_params = {
IdentityPoolId: AWSConfiguration.IdPoolId,
Logins: {
'cognito-idp.eu-central-1.amazonaws.com/eu-central-1_XXX':session.idToken.jwtToken
}
};
AWS.config.credentials = new AWS.CognitoIdentityCredentials(user_params);
AWS.config.region = AWSConfiguration.region;
AWS.config.credentials.refresh((error) => {
if (error) {
console.error(error);
}
else {
user_is_authenticated();
}
});
});
}

The Facebook login doesn't work anymore since I upgraded the Firebase app to the new Console (only)

I had a working app with Facebook & Email Login feature, since I upgrade the Firebase console (only, the sdk has not been update).
The app release before the Firebase 3.0 was working before, but it is not anymore able to sign/log with Facebook after the console has been upgraded.
What I have done:
1 - Upgraded the Firebase console
Because of Firebase & Facebook console update, I also had to put the Oauth Callback to the Facebook App
2 - Pasted the Firebase Facebook OAuth Callback to the Facebook console (before it was void) `https://xxx.firebaseapp.com/__/auth/handler``
The Exception:
The firebase Auth listener trigger a Firebase Error :
Invalid authentication credentials provided. and Facebook :
{"providerErrorInfo":{"code":400,"message":"Unsuccessful debug_token
response from Facebook: {\"error\":{\"message\":\"(#100) You must
provide an app access token or a user access token that is an owner or
developer of the
app\",\"type\":\"OAuthException\",\"code\":100,\"fbtrace_id\":\"DG4lLRJHFBS\"}}"}}
The FirebaseError Code:
In the decompiled code of the FirebaseAndroidSdk, the error object is:
0 = {java.util.LinkedHashMap$LinkedEntry#22680} "code" ->
"INVALID_CREDENTIALS"
1 = {java.util.LinkedHashMap$LinkedEntry#22681}
"message" -> "Invalid authentication credentials provided."
2 = {java.util.LinkedHashMap$LinkedEntry#22682} "details" ->
"{"providerErrorInfo":{"code":400,"message":"Unsuccessful debug_token
response from Facebook: {\"error\":{\"message\":\"(#100) You must
provide an app access token or a user access token that is an owner or
developer of the app\",\"type\":\"OAuthException\",\"code\":100,\"fbtrace_id\":\"BtB3JF2qmku\"}}"}}"
with the decompiled code:
private void makeAuthenticationRequest(String urlPath, Map<String, String> params, AuthResultHandler handler) {
final AuthenticationManager.AuthAttempt attempt = this.newAuthAttempt(handler);
this.makeRequest(urlPath, HttpRequestType.GET, params, Collections.emptyMap(), new RequestHandler() {
public void onResult(Map<String, Object> result) {
Object errorResponse = result.get("error");
String token = (String)Utilities.getOrNull(result, "token", String.class);
if(errorResponse == null && token != null) {
if(!AuthenticationManager.this.attemptHasBeenPreempted(attempt)) {
AuthenticationManager.this.authWithCredential(token, result, attempt);
}
} else {
FirebaseError error = AuthenticationManager.this.decodeErrorResponse(errorResponse);
AuthenticationManager.this.fireAuthErrorIfNotPreempted(error, attempt);
}
}
public void onError(IOException e) {
FirebaseError error = new FirebaseError(-24, "There was an exception while connecting to the authentication server: " + e.getLocalizedMessage());
AuthenticationManager.this.fireAuthErrorIfNotPreempted(error, attempt);
}
});
}
At AuthListener level, the firebaseError code : -20
https://www.firebase.com/docs/java-api/javadoc/com/firebase/client/FirebaseError.html
The specified authentication credentials are invalid.
The Facebook Error Code:
code 400
Nothing relevant found here : https://developers.facebook.com/docs/graph-api/using-graph-api/#errors
The code for Authing:
public void authWithFirebase(final String provider, Map<String, String> options) {
if (options.containsKey(AUTH_OPTIONS_ERROR)) {
EventBus.getDefault().post(new MessageToDisplayEvent(options.get(AUTH_OPTIONS_ERROR), true));
} else {
if (provider.equalsIgnoreCase(AUTH_PROVIDER_TWITTER)) {
// if the provider is twitter, we must pass in additional options, so use the options endpoint
ref.authWithOAuthToken(provider, options, new AuthResultHandler(provider));
} else {
// if the provider is not twitter, we just need to pass in the oauth_token
ref.authWithOAuthToken(provider, options.get(AUTH_OPTIONS_TOKEN), new AuthResultHandler(provider));
}
}
}
TOKEN Validity:
From the code above, the Token is confirmed valid since :
https://graph.facebook.com/app?access_token=%7Byour_access_token%7D return a valid JSON
And the Facebook Tool AccessToken https://developers.facebook.com/tools/debug/accesstoken return a still valid TOKEN
What changed from user point of view:
Now, When I click on the FacebookLoginButton, I have a new dialog that ask "connection as %FacebookUserName", with 2 buttons ("Unconnect" & "Cancel")
I posted a bug report at Firebase, but I even do not know if this is Facebook or Firebase, any help, advise for exploring new issue surface or solution is welcome.
In Facebook Developper Console, switch-off the option about the "app key that is integrated in the client".
For me this changed the behavior. I will give more information as far I get from Firebase/Facebook
Here is a French Screenshot to help you setting up Facebook:

How to retrieve authData from a ParseUser?

I'm trying to retrieve the authData field from a ParseUser. With Parse 1.9.1, I used to do it like so:
ParseUser user = ParseUser.getCurrentUser();
HashMap authDataMap = (HashMap)user.get("authData");
HashMap facebookMap = (HashMap)authDataMap.get("facebook");
String facebookId = (String)facebookMap.get("id");
And this worked fine.
Something changed though. I don't know if it's because I updated to Parse 1.9.2 or if something changed on the Parse server side, but authData is no longer accessible. The line user.get("authData") returns null. Even if I re-fetch the user.
Ultimately I want to retrieve the Facebook id from the ParseUser, preferably without reaching out to Facebook. Is this no longer possible?
If you are using ParseFacebookUtils to perform login Facebook user then after successfully login from in parse try to get GraphUser using following to fetch Facebook user data-
Request.newMeRequest(ParseFacebookUtils.getSession(),
new Request.GraphUserCallback() {
#Override
public void onCompleted(
final GraphUser fbUser,
Response response) {
try {
if (fbUser != null
&& parseUser != null
&& fbUser.getName()
.length() > 0) {
// Facebook user data
String fbId = fbUser.getId();
} else {
// Facebook user not logged in
}
} catch (Exception e) {
e.printStackTrace();
stopLoading();
}
}
}).executeAsync();
Have you taken a look at Facebook Users section in the Parse.com documentation. I think authData is for internal communication, not meant to be called (any more).

Facebook SDK 3.0 - Get Facebook User ID and Access Token

I searched for past two days and was not successful in finding the method to get the user id and access token from Facebook SDK 3.0 - Native Login .
i am following facebook native login - http://developers.facebook.com/docs/tutorials/androidsdk/3.0/scrumptious/authenticate/
and i get the access token using Session.getAccessToken , i get some access token but that is not valid . what is the actual procedure ? Am i doing wrongly ?
How to get the UserId in Native Login using Facebook SDK 3.0
user id:
final Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
// If the session is open, make an API call to get user data
// and define a new callback to handle the response
Request request = Request.newMeRequest(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
// If the response is successful
if (session == Session.getActiveSession()) {
if (user != null) {
user_ID = user.getId();//user id
profileName = user.getName();//user's profile name
userNameView.setText(user.getName());
}
}
}
});
Request.executeBatchAsync(request);
}
user_ID & profileName are string.
for accessToken:
String token = session.getAccessToken();
EDITED: (13/1/2014)
for user email (i haven't check this code by running on device or emulator):
these are only my opinion or you can call it suggestion
setReadPermissions(Arrays.asList("email", ...other permission...));
//by analyzing the links bellow, i think you can set the permission in loginbutton as:
loginButton.setReadPermissions(Arrays.asList("email", ...other permission...));
user.asMap().get("email");
for more info see:
link1, link2, link3, link4,

Categories

Resources