Login to Meteor.js using Facebook with the added feature of 'apple-mobile-web-app-capable' functionality

Currently, I am tackling a personal project that involves allowing users to log in with Facebook using Meteor.js' {{loginButtons}} feature. However, the dilemma arises when running the application in full screen mode with apple-mobile-web-app-capable, as there is no popup dialog prompting for permission - instead, the screen simply turns blank.

Notably, I do not incorporate Facebook's SDK whatsoever.

While the functionality operates smoothly on mobile Safari, deploying it on Meteor for final testing reveals that the issue is not tied to localhost.

Is there a way to achieve this without resorting to creating my own user authentication system, server-side integration, or employing Facebook's SDK? Additionally, I envision integrating Twitter and Google into the mix down the line.

Side note: I am still utilizing iOS 6.1 at the moment.

Answer №1

UPDATE: Check out my updated answer for a more enhanced example.

After spending an hour exploring various options, I decided to forego Meteor's default account system. Instead, I opted for 'oauth.io' in conjunction with 'meteor router' to manage user accounts through Meteor's Accounts.createUser() function. The beauty of this setup is its seamless functionality on both localhost and mobile devices like my iPhone, eliminating the need for constant deployments for testing purposes.

Meteor.startup(function () {
    OAuth.initialize('my key');
});

Here's how I configured my route:

Meteor.Router.add({
    '/oauth': function() {
      console.log('authenticated via OAuth');
        OAuth.callback('facebook', function(err, result) {
            var token = result.access_token;
            var url = 'https://graph.facebook.com/me?access_token='+token;

            $.get(url, function(data) {
                alert(data.email);
                console.log(data);
            });
        });
    }
});

Additionally, a simple anchor tag was included:

$('#loginfb').on('click', function() {
    OAuth.redirect('facebook', "/oauth");
});

Although I've made significant progress, there are a few remaining steps to implement authentication and user creation using retrieved email data from Facebook:

Accounts.createUser({
    email: data.email, 
    password: data.id //assuming Facebook ID remains constant
});

The next challenge involves checking if the user already exists before logging them in:

Meteor.loginWithPassword(data.email, data.id);

Adjustments were made to incorporate Backbone Router due to unexpected page refresh issues with Meteor Router. Additionally, a server-side function was introduced to generate passwords:

Meteor.methods({
  generatePass: function (data) {
    // perform necessary operations
    var pass = method to generate a secure password based on input data;
    return pass;
  }
});

Currently, the setup only supports Facebook login and requires further testing and feedback for optimal performance. Any advice or suggestions would be greatly appreciated as I continue refining this solution.

Answer №2

The main issue appears to be related to the use of window.open by the oauth packages to launch a popup window. While I have no previous experience with apple-mobile-web-app-capable, research indicates that window.open may not be compatible with it. A potential solution involves checking if the client is using a fullscreen app, which can be done using

window.navigator.standalone

as mentioned in https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html

Unfortunately, the oauth login process assumes a popup has been opened, leading to some complications. It's unclear where to conduct this test and whether a login or user creation will proceed after entering credentials in the new window.

Initially, I attempted changing window.open to window.location in accounts-oauth-helper/oauth_client.js. Although the window did open, I encountered issues with my redirect_uri, likely due to testing on a localhost project from my phone. This raises uncertainty about the continuation of the login process post-authentication.

This issue could potentially impact all login providers when utilizing apple-mobile-web-app-capable, indicating a possible bug that requires resolution. I plan to set up a dedicated project later for further investigation and will provide updates on the progress.

Answer №3

Discovering a more efficient method to accomplish this without relying on accounts-facebook or Facebook's own SDK. Instead, leveraging Meteor's accounts and accounts-ui for convenience.

Client-Side Event Handler:

Template.header.events({
  'click #loginFB': function(e) {
    e.preventDefault();
   OAuth.redirect('facebook', "/oauthlink");
 //or 
    var url = 'https://www.facebook.com/dialog/oauth?client_id=' +client_id+'&response_type=token&redirect_uri='+redirect;
window.location = url;
  }
});

Utilizing Iron Router to handle the OAuth result:

this.route('oauthLink', {
path: '/oauthlink',
action: function() {
  OAuth.callback('facebook', function(err, result) {
    Meteor.call('fblogin', result, function(error, result) {
      Meteor.loginWithToken(result.token, function(err) {
        if(err) {
          Meteor._debug("Error logging in with token: " + err);
        }
      })
    });
  });
}

});

Alternatively, omitting oauth.io:

this.route('oauthLink', {
path: '/oauthlink',
action: function() {
  var str = window.location.hash;
  str = str.split('&');
  var accessToken = str[0];
  var expiresIn = str[1];
  accessToken = accessToken.split('=');
  expiresIn = expiresIn.split('=');
  var result = {
    access_token : accessToken[1],
    expires_in : expiresIn[1]
  };
  Meteor.call('fblogin', result, function(error, result) {
    console.log(result)
    Meteor.loginWithToken(result.token, function(err) {
      if(err) {
        Meteor._debug("Error logging in with token: " + err);
      }
    })
  });
}

});

Though unsure about the correct use of 'Action' (as I'm new to iron-router), it functions as intended.

Server-Side Implementation:

Meteor.methods({
  fblogin: function(response) {
    var identity = Meteor.call('$getIdentity', response.access_token);
    
    var serviceData = {
      accessToken: response.access_token,
      expiresAt: (+new Date) + (1000 * response.expires_in)
    };

    var whitelisted = ['id', 'email', 'name', 'first_name',
        'last_name', 'link', 'username', 'gender', 'locale', 'age_range'];

    var fields = _.pick(identity, whitelisted);
    _.extend(serviceData, fields);

    var stuff = {
        serviceName : 'facebook',
        serviceData: serviceData,
        options: {profile: {name: identity.name}}
      };
      
      var userData = Accounts.updateOrCreateUserFromExternalService(stuff.serviceName, stuff.serviceData, stuff.options);

      var x = DDP._CurrentInvocation.get();

      var token = Accounts._generateStampedLoginToken();
      Accounts._insertLoginToken(userData.userId, token);
      Accounts._setLoginToken(userData.userId, x.connection, Accounts._hashLoginToken(token.token))
      x.setUserId(userData.userId)

      return {
        id: userData.userId,
        token: token.token,
        tokenExpires: Accounts._tokenExpiration(token.when)
      };

  },
  $getIdentity: function(accessToken) {
    try {
      return HTTP.get("https://graph.facebook.com/me", {
        params: {access_token: accessToken}}).data;
    } catch (err) {
        throw _.extend(new Error("Failed to fetch identity from Facebook. " + err.message),
               {response: err.response});
        }
    }
});

Enhancing functionality inherited from accounts-facebook package while introducing modifications tailored to specific requirements. Additionally, copying the `$getIdentity` function directly from there.

'var stuff' encapsulates Facebook data alongside meteor account data, seamlessly integrating into Accounts.updateorcreateuserfromexternalservice, thereby streamlining the process. The 'fblogin()' function yields userData, obtained through Accounts.updateorcreate...., consequently acquiring the essential token utilized for login via Metoer.loginWithToken.

Executing operations sans the need to launch additional windows or tabs as would be the case with accounts-facebook has resolved primary concerns, yielding equivalent functionality. Eliminating the necessity to ascertain user existence before generating passwords, simplifying the entire procedure.

Potential expansion across alternative OAuth APIs devoid of dependency on oauth.io is entirely feasible. Personal laziness was the only deterrent in exploring further possibilities.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Looking to utilize JQuery to select checkboxes based on list or array retrieved from database

When using SQL 2008 Server and the latest JQuery, how can I mark checkboxes as 'checked' in each checkbox group when querying a column from the database to get a list/array? For example, if I have lists for categories '1,7,20' (Jquery s ...

Tips for changing ng-init variable within angular js template

I am trying to dynamically concatenate text on my AngularJS page. My goal is to display the ids of all users in the title. I declared a variable 't' using ng-init and tried to update the variable 't' in an ng-repeat loop to display it a ...

Unresponsive Radio Buttons in HTML

Have you ever encountered the issue where you can't seem to select radio buttons despite them having a confirmed name attribute? Here is an example of the HTML code: <div id="surveys-list" class="inline col-xs-12"><div> <div class="i ...

Click the button to send the form without including any hidden HTML element array value

My main goal is to create a dynamic dropdown menu for users when they click a button. Each click triggers a new dropdown to appear. To achieve this, I have been cloning a hidden div each time the button is clicked. Here's an example of how I am accom ...

In what way does this closure cause componentDidUpdate to mimic the behavior of useEffect?

Recently, I came across an insightful article by Dan Abramov titled: A Complete Guide to useEffect. In the section that discusses how Each Render Has Its Own… Everything, two examples were provided. The first example demonstrates the usage of useEffect a ...

Learning how to manipulate images by rotating, resizing, and zooming from the corners on a canvas

Currently I am in the process of creating a collage application and I'm hoping to incorporate a specific visual effect into my images. Click here for an example. My goal is to be able to rotate and resize the image from a specific point when clickin ...

The functionality of loading JSON is not working properly in ePub3

Currently, I am working on a project involving the creation of an ePub3 eBook. One of the exciting features I have successfully integrated is three.js to showcase some models. My next goal is to develop 'hotspot' elements (small cubes that users ...

Expanding mongoDB database by utilizing a Java endpoint using JavaScript

It would be quite impressive if you could provide an answer to my current dilemma. Currently, I am developing a full stack web application that comprises of three main components: A collection of Articles stored in MongoDB A backend developed in Java 8 A ...

A step-by-step guide on executing a callback function once the animation has finished with frame-motion

I'm facing an issue with my component called AnimatedText. After the animation is complete, I want the words filled in the underlineLines prop to be underlined. How can I achieve this? I attempted using the onAnimationEnd function, but it didn't ...

Updating a table without the need for a button in PHP and AJAX with an Excel-inspired approach

I'm facing a scenario where I need to dynamically update the contents of a table row. To achieve this, I want the cell to transform into a text box when clicked. Here's how I implemented it: <td contenteditable></td> After making ch ...

Struggling to customize checkbox design using HTML and CSS

Why am I unable to style HTML checkboxes with CSS? No matter what I try, the appearance of the checkboxes remains unchanged: Here is the HTML code: <input type="checkbox" id="checkbox-1-1" class="regular-checkbox" /> <nput type="checkbox" id ...

Remove markers from Google Maps when there are no markers present

I am working on a mobile web app that features a mapping page where users can toggle different POI's, such as Gas Stations. The issue I am facing is when the google.maps.places.PlacesService does not find any Gas Stations within my specified radius, I ...

Retrieve 10000 sets of coordinates in real time with the help of Google Maps

I am trying to retrieve coordinates for 10,000 lines of data using the Google Maps geocoding API and display each line on the browser. My strategy involves looping through each line (which contains an address), passing it to the Google Maps URL, parsi ...

What is the proper way to extract a JSON value?

I have a JSON array that looks like this: var currencyformats = {"USD":[ {'symbol':'$', 'left':true} ], "UAH":[ {'symbol':'₴', 'left':true} ], "EUR":[ {'sym ...

Having trouble verifying a phone number using the awesome-phonenumber npm package?

I recently developed some JavaScript using the awesome-phonenumber npm package. index.js const yargs = require('yargs'); var PhoneNumber = require( 'awesome-phonenumber' ); const argv = yargs .usage('Usage: $0 -n [num]' ...

Access the values stored in a Key/Value variable within a JavaScript environment

Let's dive into this situation: Imagine I have a Key/Value pair like this: var dict = {"78": "X", "12": "G", "18": "R", "67": "U", "68": "O", "30": "P"} Now, suppose I have a string and I ...

Express: Implementing Middleware Only on Specified Routes in a Router Object - A Comprehensive Guide

Looking to organize my routes by stacking router objects for better modularity. An issue arises when trying to add a middleware call exclusively to every route in a specific router without having to insert it into each route individually due to the size o ...

Navigate horizontally through columns by scrolling when clicking on Prev/Next buttons in Bootstrap 5

I have implemented 2 buttons that scroll the DIV left and right, but it scrolls a fixed width instead of scrolling each column in Bootstrap 5 on clicking Prev/Next. Can someone assist me with this? Thank you. DEMO JSFiddle: https://jsfiddle.net/hsmx2f5z/ ...

Ways to combine attributes in an array of objects using a designated property

I am attempting to combine related objects within an array of objects based on matching properties in a specific object key "name". Although I have implemented the following code, unfortunately it did not yield the desired results: const students = []; ...

Pressing the up arrow in Javascript to retrieve the most recent inputs

Is there a way to retrieve the most recent inputs I entered in a specific order? For example: I have an array with 20 elements, and every time I enter something, I remove the first element from the array and add the new input at the end. So, when I press ...