Calling Hook for Social Login

I would like to be able to call the pre registration hook when a user is authenticated using the social login. We currently have a hook in place for regular login where it will call our API gateway and create a user account, and update the user’s app meta data with the GUID. Is it possible to have a hook fire like for a database option, or should I create a rule like posted in this thread : Post Registration Hook not firing for social connection user.

Please let me know,

Thanks in advanced,
Jyoti

Hey there @jguin, welcome to the Auth0 Community!

Are we talking a Custom Database here? What data exactly are you looking to grab and pass? Thanks in advance!

1 Like

@James.Morrison This is for the social login. I was able to call our API and get the newly generated user’s guid and set that as the user’s app_metadata using a rule. Now I am having an issue where I’ve added a new claim to the access token in the same rule, but this does not propagate into the token when it’s sent to the app.

@James.Morrison Now I see the new claim in the access token however only on the 2nd log in attempt. When the user logs in for the first time, using the social login, it runs through the rule and a additional claim is added but it is not part of the access token. When the user logs in the 2nd time, the claim is part of the access token. I’m not sure if this is a limitation of the rules, but I don’t face this issue when using hooks instead of rule.

@jguin Unlike database user, for social user there is no registration as the social accounts alreadty exists at the social IdP.

Can you post your rule code here for us to take a look?

1 Like

Thanks for quick response @ashish

function (user, context, callback) {
if (context.connection === 'facebook' || context.connection === 'google-oauth2') {

user.user_metadata = user.user_metadata || {};
const userManagementSecret = configuration.userManagementSecretValue;

const options = {
  method: 'POST',
  uri: 'url to api',
  body: {
    email: user.email,
  },
  json: true,
  headers: {
    'UserManagement': userManagementSecret
  }
};

request(options, function (error, res, body) {
  if(error){
    callback(`An error occurred during account creation. ({error})`);
  }else{
    if(res.statusCode === 200)
    {
       user.app_metadata = user.app_metadata || {};
      user.app_metadata.subscriberGuid = body.subscriberGuid;
      context.accessToken['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'] = body.subscriberGuid;
      auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
        .then(function(){
          callback(null, user, context);
        })
        .catch(function(err){
          callback(err);
        });
    }else if(res.statusCode === 400)
    {
      callback('The new user request was invalid.');
    }else if(res.statusCode === 401)
    {
      callback('Unauthorized request.');
    }
    else if(res.statusCode === 409){
      callback('A user with that email already exists.');
    }
    else{
      callback('An unknown error occurred during account creation.');
    }
  }
});

}
callback(null, user, context);
}
1 Like

Looks good to me.
Question, what scope are you requesting? It should be http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier when initiating login.

Also I noticed you are calling the url to api on successful login. Is that intended? does the guuid change for every login? You might want to add a flag in app_metadata firstLoginCompleted to true after initial call to this api so subsequent logins do not make the call again. and in your rule only call your api when firstLoginCompleted is false or doesn’t exists.

1 Like

The scope I am using is http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier. I put a placeholder for the API url so I don’t get in trouble :yum: This is meant for only first time log in, and yes I was planning on adding a flag to app_metadata. I just for the life of me figure out why the access token does not contain the claim on the first sign in.

1 Like

I just tested with similar rule on my tenant and it does given me back the scope value in my first login. I would try few things to debug this on your end

  1. change the scope namespace to something else
  2. just add a random guuid to the claim without calling your external api

Narrow it down where the issue is.

I believe this is a bug with Auth0. I tried the sample Rule ‘Custom webhook with ASP NET WebApi2’ by replacing a few lines. I added logging and verified that the the api endpoint is responding with a value, and that it is getting set to the user.app_metadata and context.accessToken. The real time webtask log shows that it succeeded without and issues. I checked the user account and see that the uuid is set in the app_metadata. I also tried different namespaces but that didn’t make any dfifference.

The reason it worked the 2nd time is because there is a separate rule that takes the uuid from app_metadata and sets it to accessToken. It only works the 2nd time because uuid does not exist in the app_metadata until the first login. When I disabled this rule, the custom claim never makes it to the accessToken.

I did get it work if I hard coded the UUID and did not make any API calls. This is the reason it makes me believe this is a bug because there is no issue with the API calls, it succeeds as shown by the logs.

Below is the snippet of the modified version sample rule ‘Custom webhook with ASP NET WebApi2’’ from Auth0 that I’ve been trying with:

  function (user, context, callback) {
    user.app_metadata = user.app_metadata || {};
    if (user.app_metadata.subscriberGuid) {
      console.log('Found ID!');
      return callback(null, user, context);
    }

    // You should make your requests over SSL to protect your app secrets.
    request.post({
      url: 'Api Endpoint',
      json: {
        email: user.email
      },
      headers: {
        'UserManagement': configuration.userManagementSecretValue
      },
      timeout: 15000
    }, (err, response, body) => {
      if (err) return callback(new Error(err));

      user.app_metadata.customId = body.subscriberGuid;
      context.accessToken['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'] = body.subscriberGuid;
      auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
        .then(function(){
          callback(null, user, context);
        })
        .catch(function(err){
          callback(err);
        });
    });
  }

Thanks in advance,
Jyoti