Custom Claim missing on new Google Social Connection Signup

Hello everyone!

TLDR; One of my rules that adds a custom claim to access tokens won’t work with a new Google signup, but works fine for regular Auth0 DB new signups.

I have a statistics website with a React FE and a .NET Core BE. So far, users have been creating new accounts/logging in as Auth0 DB users. Everything works fine - these signups use a combination of pre-registration hooks and a rule (see # 2 below) to handle custom claims/creating new users in my BE API.

I’ve recently setup the Google social connection so that users can signup/login w/ Google on my website. Two rules handle new Google Social Connection users

  1. Add new social user to my API - Check if a user is logging in for the first time and is from a social connection. If so, create the new user in my BE API and add my backend’s custom API ID to the user’s app_metadata.
  2. Add a custom claim to my Google user’s access token - Takes the custom API ID from the user’s app_metadata and adds it to the Google user’s access token

The first rule works fine. The second rule does not work the first time a user signs up/logs in with Social (Google). The claim does not get added to the token. If the user logs out and logs back in, the claim is added just fine.

Would appreciate any insight on this issue.

Update @ 01/01/2021 Still haven’t resolved this issue, bumping

Thanks!

If it helps, here is the rule code below:

function addMyBackendAppIdToAccessToken(user, context, callback) {
  var namespace = 'https://myapp.com/';
  context.accessToken[namespace + 'myBackendAppId'] = user.app_metadata.myBackendAppId;
  callback(null, user, context);
}

Also, I installed the Real-time Webtask Logs so I could watch what was happening in real time. The ID is definitely coming back from my backend and the rule is running after the new user signs up with Google. The token that the user receives does not have the myBackendAppId claim though (the first time they log in/are redirected back to my site after sign up).

If they log out and then log back in, the new token DOES have the myBackendAppId claim. But I need it to be there when they first sign up (for obvious reasons).

Any help would be appreciated.

Thanks again!

I have the same issue. Just started using custom claims, did you get this working?

Heya @bpliska , I did! I think my JavaScript was wrong. If you DM me I can share my code with you to get this working.

Hey there @seth2!

Would you be able to share it here in the thread as well for the benefit of others?

@konrad.sopala @bpliska Here we go…it’s been a long time since I messed with any of this, so please excuse the brevity. I’m just going to list the rules I have added for my user “sign up” flow.

  1. This first rule adds a “signedUp” attribute to a new user’s app_metadata that gets used during step 2, when I create the user and profile. This is how I handle first time social user signups…see the last bit of step 2 in the comments where I explain.
function signedUpAttribute(user, context, callback) {
  user.app_metadata = user.app_metadata || {};
  // short-circuit if the user signed up already
  if (user.app_metadata.signedUp !== undefined) return callback(null, user, context);
  // first time login/signup
  user.app_metadata.signedUp = false;
  auth0.users
    .updateAppMetadata(user.user_id, user.app_metadata)
    .then(function () {
      callback(null, user, context);
    })
    .catch(function (err) {
      callback(err);
    });
}
  1. This second rule creates a backend user and profile in myApp’s DB that will represent the user in auth0:
function createMyAppUserForSocial(user, context, callback) {
  var clientCreds = '';
  var profileId = 0;
  var axios = require('axios');
  var namespace = 'https://myapp.com/';
  user.app_metadata = user.app_metadata || {};

  function saveUser() {
    console.log('######### Begin Saving MyApp User #########');
    axios.put('https://api.myapp.com/api/user/save',
      {
        username: user.username,
        email: user.email,
        profileId: profileId
      },
      {
        headers:
          {
            'Authorization': `Bearer ${clientCreds}`
          }
      })
      .then(res => {

        user.app_metadata.myAppId = res.data.id;
        user.app_metadata.signedUp = true;
        context.accessToken['https://www.myapp.com/myAppId'] = res.data.id;
      
       try {
        	auth0.users.updateAppMetadata(user.user_id, user.app_metadata);
      	} catch (auth0Error) {
        	console.error('Error updating the user app_metadata: ' + auth0Error.message);
        	return callback(null, user, context);
      	}

        console.log('######### Complete Saving MyApp User #########');
        callback(null, user, context);
      })
      .catch(error => console.log(error));
  }

  function createProfile() {
    console.log('######### Begin Creating MyApp Profile #########');
    axios.put('https://api.myapp.com/api/profile/save',
      {
        description: 'Enter a few words to describe yourself.',
        profileInfo: [
          {
            'address': '1234 Main Street',
            'city': 'Dallas'
          }]
      },
      {
        headers:
          {
            'Authorization': `Bearer ${clientCreds}`
          }
      })
      .then(res => {
        profileId = res.data.id;

        saveUser();
      })
      .catch(error => console.log(error));
  }

  if (user.app_metadata.signedUp === false) {
    axios
      .post('https://myapp.eu.auth0.com/oauth/token',
        {
          client_id: 'clientIdHere',
          client_secret: 'clientSecretHere',
          audience: 'https://myapp.com/',
          grant_type: 'client_credentials'
        })
      .then(res => {

        clientCreds = res.data.access_token;

        createProfile();

        console.log('##### User & Profile created #####');
      })
      .catch(error => console.log(error));
  } else if (user.app_metadata.signedUp === true) {
    // must use an elseif here...otherwise, if we just add the custom claim below 
    // (outside the if statement, there will be no
    // myAppId to add and the accessToken will be returned w/o any custom claims for first time
    // social signups
   	context.accessToken['https://www.myapp.com/myAppId'] = user.app_metadata.myAppId;
		callback(null, user, context);
  }
}
  1. This third rule adds the backend user ID to my auth0 user metadata:
function addMyAppIdToAccessToken(user, context, callback) {
  // This rule adds the authenticated user's myAppId to the access token.
  var namespace = 'https://myapp.com/';
  context.accessToken[namespace + 'myAppId'] = user.app_metadata.myAppId;
  callback(null, user, context);
}

Hope this helps, again sorry if any of this is unclear, it has been a long time since I set all this up. Best of luck to you!

No problem! Thanks for sharing all that!