Add information to user/app metadata after a social login using actions

Hi, I’m trying to add information to the user (and/or app) metadata after a social login (taking that information from a legacy system) using Actions.

I have tried this and works ok (set user and app metadata):

exports.onExecutePostLogin = async (event, api) => {

  api.user.setUserMetadata("favorite_color", "blue");

//const remoteUser = await axios.get("https://my-api.exampleco.com/users", { params: { email: event.user.email }});
  const remoteUser = {id: 123} ;

  if (remoteUser) {
    api.user.setAppMetadata("my-api-user-id", remoteUser.id);
  }

};

But when I take the information from the legacy system it doesn’t get added to the app metada (the field favorite_color and my-api-user-id gets added as in the previous example but the field apellido doesn’t get added to the metadata. I think it is because that is done in an asynchronous callback but I’m not finding a way to update the metadata with the information of the legacy system.

Any help will be greatly appreciated.

The onExecutePostLogin code is:

const request = require('request');

exports.onExecutePostLogin = async (event, api) => {

  const options = {
    url: 'http://...', // <<< URL of legacy service
    method: 'POST',
    headers: {
      'content-type' : 'application/x-www-form-urlencoded'
    },
    body: '...&email=' + event.user.email // <<< Other data for the legacy service
  } ;

  request(options, function(err, res, body) {

    api.user.setUserMetadata("apellido", 'One') ; // >>> This is NOT added to the metadata
    
    if (err) return ;
    if (res.statusCode === 401) return ;
    if (res.statusCode === 403) return ;
    const paseRespuesta = JSON.parse(body);
    console.log(paseRespuesta.estado);
    console.log(paseRespuesta.usuario);

//    api.user.setUserMetadata("apellido", paseRespuesta.usuario.apellido) ; // >>> This is NOT added to the metadata
    api.user.setUserMetadata("apellido", 'Two') ; // >>> This is NOT added to the metadata

  }) ;

  api.user.setUserMetadata("favorite_color", "blue"); // >>> This IS added to the metadata

  //const remoteUser = await axios.get("https://my-api.exampleco.com/users", { params: { email: event.user.email }});
  const remoteUser = {id: 123} ;

  console.log(api.user) ;
  
  if (remoteUser) {
    api.user.setAppMetadata("my-api-user-id", remoteUser.id);  // >>> This IS added to the metadata
  }

};

Just in case it is useful I simplfied even more the action code

const request = require('request');

exports.onExecutePostLogin = async (event, api) => {

  const options = {
    url: 'http://...',
    method: 'POST',
    headers: {
      'content-type' : 'application/x-www-form-urlencoded'
    },
    body: '...&email=' + event.user.email
  } ;

  api.user.setUserMetadata("favorite_team", "boca"); // >>> Added to the metadata

  request(options, function(err, res, body) {
    api.user.setUserMetadata("apellido", 'Anders') ; // >>> NOT Added to the metadata
  }) ;

  api.user.setUserMetadata("favorite_color", "blue"); // >>> Added to the metadata

  const remoteUser = {id: 123} ;
  if (remoteUser) {
    api.user.setAppMetadata("my-api-user-id", remoteUser.id); // >>> Added to the metadata
  }

};

Regards

Hi guys, not sure if this is the better option but I managed to make it work with the following code.

Please let me know if you think that a better approach is possible.

const http = require('http');

function getPromise(mail) {
	return new Promise((resolve, reject) => {

    var out_text = '...&email=' + mail ;

    var options = {
	    host: '...',
      port: 80,
	    path: '...',
	    method: 'POST',
	    headers: {
		    'Content-Type': 'application/x-www-form-urlencoded',
		    'Content-Length': out_text.length,
		    'User-Agent': '',
		    'Referer': '...'
	    }
    };

    var request = http.request(options, (response) => {
      let chunks_of_data = [];
      response.on('data', (fragments) => {
       chunks_of_data.push(fragments);
      });
      response.on('end', () => {
        let response_body = Buffer.concat(chunks_of_data);
        resolve(response_body.toString());
      });
      response.on('error', (error) => {
        reject(error);
      });
    });
    //write data to server
    request.write(out_text);
    request.end();
  });
  
}

// async function to make http request
async function makeSynchronousRequest(email, user) {
  try {
    let http_promise = getPromise(email);
    let response_body = await http_promise;

    user.setUserMetadata("response_body", response_body);

    const paseRespuesta = JSON.parse(response_body);
    user.setUserMetadata("apellido", paseRespuesta.estado) ;

	} catch(error) {
    // Promise rejected
    console.log(error);
  }
}

/**
 * Handler that will be called during the execution of a PostLogin flow.
 *
 * @param {Event} event - Details about the user and the context in which they are logging in.
 * @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
 */
exports.onExecutePostLogin = async (event, api) => {

  await makeSynchronousRequest(event.user.email, api.user);
	
  api.user.setUserMetadata("favorite_color", "blue");

};
1 Like

Thanks for sharing it with the rest of community!