Adding Authentication with Facebook and Google in Flutter app without Firebase - facebook-graph-api

I am working on a Flutter app and need to include the Facebook and Google login options in our app login page. I am not using Firebase and working on the MySQL database for storing and retrieving user's data.
I am looking for Adding the FB and Google authentication in my flutter app without the Firebase. I was not able to find any article for this. Everywhere it is always using the Firebase.
After following a tutorial, I have registered my app in FB Developer console, but I am not sure what will be put in the 'OAuth redirect URL' field there.
Currently, I am using xampp server and nodeJS for server side handling. Below is the code which I am calling on my button click. I am using plugin for Facebook authentication(Please let me know if this plugin is specifically for Firebase).
void initiateFacebookLogin() async {
var facebookLogin = FacebookLogin();
facebookLogin.loginBehavior = FacebookLoginBehavior.webViewOnly;
print("Inside fb login");
var facebookLoginResult = await facebookLogin
.logInWithReadPermissions(['email', 'public_profile']);
switch (facebookLoginResult.status) {
case FacebookLoginStatus.error:
print("Error");
onLoginStatusChanged(false);
break;
case FacebookLoginStatus.cancelledByUser:
print("CancelledByUser");
onLoginStatusChanged(false);
break;
case FacebookLoginStatus.loggedIn:
print("LoggedIn");
var graphResponse = await http.get(
'https://graph.facebook.com/v2.12/me?fields=name,first_name,last_name,email,picture.height(200)&access_token=${facebookLoginResult.accessToken.token}');
var profile = json.decode(graphResponse.body);
print(profile.toString());
onLoginStatusChanged(true, profileData: profile);
break;
}
}

As mentioned in the comments, both Facebook and Google Sign in can work without Firebase. There's a sample code for Flutter google_sign_in package that you can try here.

Related

Mail code works in localhost but not on the URL website afterwards

I made a web application on visual studio 2017 for ASP.NET core. It has a contact option where users send me an email. It works perfectly in localhost as I receive the feedback. When I build/release using Azure DevOps onto azure app services in the portal my website at its URL loses the functionality of the email option. I wrote the email code using MailKit, if you guys have a better option that works let me know! Thank you.
var message = new MimeMessage();
message.From.Add(new MailboxAddress(inputEmail));
message.To.Add(new MailboxAddress("myemail"));
message.Subject = "Message from: " + inputName;
message.Body = new TextPart("plain")
{
Text = inputMessage
};
using (var client = new SmtpClient())
{
client.Connect("smtp.gmail.com", 587, false);
client.Authenticate("email", "password");
client.Send(message);
client.Disconnect(true);
};
return RedirectToAction("Index");
mywebsite.azurewebsites.net is currently unable to handle this request.
The problem is that you are using gmail. GMail only allows you to authenticate using SMTP/IMAP/POP3 after you've authenticated via the web from a particular device.

How to get Facebook page feed and Filter its fields as Json using Google App script

I am trying to get a Facebook page feed through Google app script.
As of now I tried different scripts but I am getting only app token with the request and if i change it with a usertoken from graph api I got messages but no images and titles
How to get the user token and get the correct fields for as a json ,
var url = 'https://graph.facebook.com'
+ '/love.to.traavel/feed'
+ '?access_token='+ encodeURIComponent(getToken());
// + '?access_token=' + service.getAccessToken();
var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true});
var json = response.getContentText();
var jsondata = JSON.parse(json);
Logger.log(jsondata); //check this and adjust following for loop and ht
var posts = {};
for (var i in jsondata) {
posts[i] = {"post":jsondata[i].message};
}
return posts;
You should use a Page Token, not a User Token
You need to ask for fields you want to get, with the fields parameter: https://graph.facebook.com/love.to.traavel/feed?fields=field1,field2,...&access_token=xxx
You get a user token by authorizing your App: https://developers.facebook.com/docs/facebook-login/platforms
Be aware that extended user tokens are valid for 60 days only, so you have to refresh it once in a while. There is no user token that is valid forever. You cannot authorize through code only, it needs user interaction. The easiest way is to just generate a user token by selecting your App in the API Explorer and authorize it, like you did already. Then hardcode it in the script code.
Alternatively, you can try implementing this with the manual login flow, check out the docs for that. You can try adding the functionality using this for a custom interface where you go through the login process: https://developers.google.com/apps-script/guides/html/
Since you donĀ“t own the page, you should read this too: https://developers.facebook.com/docs/apps/review/feature/#reference-PAGES_ACCESS

Identity Server 3 Facebook Login Get Email

Identity server is implemented and working well. Google login is working and is returning several claims including email.
Facebook login is working, and my app is live and requests email permissions when a new user logs in.
The problem is that I can't get the email back from the oauth endpoint and I can't seem to find the access_token to manually request user information. All I have is a "code" returned from the facebook login endpoint.
Here's the IdentityServer setup.
var fb = new FacebookAuthenticationOptions
{
AuthenticationType = "Facebook",
SignInAsAuthenticationType = signInAsType,
AppId = ConfigurationManager.AppSettings["Facebook:AppId"],
AppSecret = ConfigurationManager.AppSettings["Facebook:AppSecret"]
};
fb.Scope.Add("email");
app.UseFacebookAuthentication(fb);
Then of course I've customized the AuthenticateLocalAsync method, but the claims I'm receiving only include name. No email claim.
Digging through the source code for identity server, I realized that there are some claims things happening to transform facebook claims, so I extended that class to debug into it and see if it was stripping out any claims, which it's not.
I also watched the http calls with fiddler, and I only see the following (apologies as code formatting doesn't work very good on urls. I tried to format the querystring params one their own lines but it didn't take)
(facebook.com)
/dialog/oauth
?response_type=code
&client_id=xxx
&redirect_uri=https%3A%2F%2Fidentity.[site].com%2Fid%2Fsignin-facebook
&scope=email
&state=xxx
(facebook.com)
/login.php
?skip_api_login=1
&api_key=xxx
&signed_next=1
&next=https%3A%2F%2Fwww.facebook.com%2Fv2.7%2Fdialog%2Foauth%3Fredirect_uri%3Dhttps%253A%252F%252Fidentity.[site].com%252Fid%252Fsignin-facebook%26state%3Dxxx%26scope%3Demail%26response_type%3Dcode%26client_id%3Dxxx%26ret%3Dlogin%26logger_id%3Dxxx&cancel_url=https%3A%2F%2Fidentity.[site].com%2Fid%2Fsignin-facebook%3Ferror%3Daccess_denied%26error_code%3D200%26error_description%3DPermissions%2Berror%26error_reason%3Duser_denied%26state%3Dxxx%23_%3D_
&display=page
&locale=en_US
&logger_id=xxx
(facebook.com)
POST /cookie/consent/?pv=1&dpr=1 HTTP/1.1
(facebook.com)
/login.php
?login_attempt=1
&next=https%3A%2F%2Fwww.facebook.com%2Fv2.7%2Fdialog%2Foauth%3Fredirect_uri%3Dhttps%253A%252F%252Fidentity.[site].com%252Fid%252Fsignin-facebook%26state%3Dxxx%26scope%3Demail%26response_type%3Dcode%26client_id%3Dxxx%26ret%3Dlogin%26logger_id%3Dxxx
&lwv=100
(facebook.com)
/v2.7/dialog/oauth
?redirect_uri=https%3A%2F%2Fidentity.[site].com%2Fid%2Fsignin-facebook
&state=xxx
&scope=email
&response_type=code
&client_id=xxx
&ret=login
&logger_id=xxx
&hash=xxx
(identity server)
/id/signin-facebook
?code=xxx
&state=xxx
I saw the code parameter on that last call and thought that maybe I could use the code there to get the access_token from the facebook API https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow
However when I tried that I get a message from the API telling me the code has already been used.
I also tried to change the UserInformationEndpoint to the FacebookAuthenticationOptions to force it to ask for the email by appending ?fields=email to the end of the default endpoint location, but that causes identity server to spit out the error "There was an error logging into the external provider. The error message is: access_denied".
I might be able to fix this all if I can change the middleware to send the request with response_type=id_token but I can't figure out how to do that or how to extract that access token when it gets returned in the first place to be able to use the Facebook C# sdk.
So I guess any help or direction at all would be awesome. I've spent countless hours researching and trying to solve the problem. All I need to do is get the email address of the logged-in user via IdentityServer3. Doesn't sound so hard and yet I'm stuck.
I finally figured this out. The answer has something to do with Mitra's comments although neither of those answers quite seemed to fit the bill, so I'm putting another one here. First, you need to request the access_token, not code (authorization code) from Facebook's Authentication endpoint. To do that, set it up like this
var fb = new FacebookAuthenticationOptions
{
AuthenticationType = "Facebook",
SignInAsAuthenticationType = signInAsType,
AppId = ConfigurationManager.AppSettings["Facebook:AppId"],
AppSecret = ConfigurationManager.AppSettings["Facebook:AppSecret"],
Provider = new FacebookAuthenticationProvider()
{
OnAuthenticated = (context) =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, ClaimValueTypes.String, "Facebook"));
return Task.FromResult(0);
}
}
};
fb.Scope.Add("email");
app.UseFacebookAuthentication(fb);
Then, you need to catch the response once it's logged in. I'm using the following file from the IdentityServer3 Samples Repository, which overrides (read, provides functionality) for the methods necessary to log a user in from external sites. From this response, I'm using the C# Facebook SDK with the newly returned access_token claim in the ExternalAuthenticationContext to request the fields I need and add them to the list of claims. Then I can use that information to create/log in the user.
public override async Task AuthenticateExternalAsync(ExternalAuthenticationContext ctx)
{
var externalUser = ctx.ExternalIdentity;
var claimsList = ctx.ExternalIdentity.Claims.ToList();
if (externalUser.Provider == "Facebook")
{
var extraClaims = GetAdditionalFacebookClaims(externalUser.Claims.First(claim => claim.Type == "urn:facebook:access_token"));
claimsList.Add(new Claim("email", extraClaims.First(k => k.Key == "email").Value.ToString()));
claimsList.Add(new Claim("given_name", extraClaims.First(k => k.Key == "first_name").Value.ToString()));
claimsList.Add(new Claim("family_name", extraClaims.First(k => k.Key == "last_name").Value.ToString()));
}
if (externalUser == null)
{
throw new ArgumentNullException("externalUser");
}
var user = await userManager.FindAsync(new Microsoft.AspNet.Identity.UserLoginInfo(externalUser.Provider, externalUser.ProviderId));
if (user == null)
{
ctx.AuthenticateResult = await ProcessNewExternalAccountAsync(externalUser.Provider, externalUser.ProviderId, claimsList);
}
else
{
ctx.AuthenticateResult = await ProcessExistingExternalAccountAsync(user.Id, externalUser.Provider, externalUser.ProviderId, claimsList);
}
}
And that's it! If you have any suggestions for simplifying this process, please let me know. I was going to modify this code to do perform the call to the API from FacebookAuthenticationOptions, but the Events property no longer exists apparently.
Edit: the GetAdditionalFacebookClaims method is simply a method that creates a new FacebookClient given the access token that was pulled out and queries the Facebook API for the other user claims you need. For example, my method looks like this:
protected static JsonObject GetAdditionalFacebookClaims(Claim accessToken)
{
var fb = new FacebookClient(accessToken.Value);
return fb.Get("me", new {fields = new[] {"email", "first_name", "last_name"}}) as JsonObject;
}

How to login into a third-party website using google app script and manage data on login?

I am interested in creating a google app script that on run would login into a specific website (third-party) and complete certain functions within the website (pressing buttons/copying text).
After browsing the stackoverflow and other forums I have created a script that allows me to login into my website (source1 source2).
However, I am having difficulties staying logged in and managing the data.
//The current code is just testing if I can get data from within the website.
//The results are displayed in a google app.
function doGet() {
var app = UiApp.createApplication();
app.add(app.createLabel(display_basic_data()));
return app;
}
//logins into website and displays data
function display_basic_data() {
var data;
var url = "http://www.website.bla/users/sign_in";
var payload = {"user[username]":"usr","user[password]":"ps"};
var opt ={"method":"post","payload":payload, "followRedirects" : false};
var response = UrlFetchApp.fetch(url,opt);
data = response;
return data;
}
Currently, the data returned from display_basic_data() is
"<html><body>You are being redirected.</body></html>".
If I try to change my script so that "followRedirects" is true, the data is equivalent to the HTML of the login page.
I understand I have to play around with cookies in order to 'stay' logged in but I have no idea what to do as the examples online provided to be fruitless for me.
Any help would be much appreciated!!!
You may want to do something like this:
var cookie = response.getAllHeaders()['Set-Cookie'];
//maybe parse cookies here, depends on what cookie is
var headers = {'Cookie':cookie};
var opt2 = {"headers":headers};
var pagedata = UrlFetchApp.fetch("http://www.website.bla/home",opt2);

Accessing signed Facebook JSON using Play 2.0.1 and RestFB

I'm writing an Play 2.0.1 application that will be deployed within a canvas page on Facebook. I'm using restFB for the Facebook API.
By manually creating an Access Token at https://developers.facebook.com/tools/explorer?method=GET I can get my application to access the Facebook user's name and render it in the Canvas page iFrame on Facebook.
So, my app controller receives the POST and renders a page like this:
public static Result handle_fb_post() {
return redirect(routes.canvas.fb_render_profile_page());
}
public static Result fb_render_profile_page() {
String accessToken = "<access token copied from facebook graph explorer>";
DefaultFacebookClient().getExtendedAccessToken(application_id, application_secret);
FacebookClient facebookClient = new DefaultFacebookClient(accessToken);
User fbUser = facebookClient.fetchObject("me", com.restfb.types.User.class);
return ok(views.html.fbuser.render(fbUser));
}
My routes are set up as:
POST /fbcanvas/ controllers.FBCanvas.handle_fb_post()
GET /fbcanvas/profile controllers.FBCanvas.fb_render_profile_page()
However, how can I get access to the signed JSON that Facebook sends me in the POST? I believe that this also contains the access token from the user (assuming that they have authorised my app) as described here:
https://developers.facebook.com/docs/samples/canvas/ (See section on "signed_request Parameter").
There are a number of examples out there for Java, PHP, Javascript and Python, but I can't find any that describe how to do this in Play 2 or using RestFB. I have tried a number of different approaches, but cannot work out how to access the signed request in Play 2.
Can anyone help and explain how this can be done?
If the token is sent as Json in the POST request, you can grab it via
def handle_post() = Action { implicit request =>
val jsonBody = request.body.asJson
//process it
}