Auth0 Home Blog Docs

FB issue: how to re-prompt for permissions

social-connections
permissions
facebook-login
prompt

#1

In our clients, users authenticating via a social provider (e.g. FB) should not be allowed to login if they decline authorization permissions. Declining individual authorization permissions is possible when logging in via Facebook. Google on the other hand, does not appear to allow this (you either accept or deny what the client is requesting.)

To elaborate: a user who is ‘signing up’ to our services via one of our clients that allows social logins, and who has chosen FB as their social provider, can ‘de-select’ the sharing of just their email address when FB prompts the user for their consent. If and when a user does this, the authentication succeeds (if we do not intervene with a custom rule) and the user is actually ‘added to Auth0’, without an email address. This is not what we want to occur.

Ideally if/when a user takes the above action while login via Facebook:

  1. The client will receive an error message explaining that (all) permissions are required

  2. And then, when the user makes a subsequent attempt to login (via FB) they are re-prompted for permissions

Our initial idea was to create a ‘pre-registration Hook’ that would prevent the user from being added to Auth0 in the first place. We discovered however that Hooks can only be used for DB connections (not social). So, we have instead created a very simple rule that throws an UnauthorizedError if/when the user account does not have an email address. All by itself this rule is useful, but the user is then stuck in FB purgatory so to speak unless and until they figure out how to change their FB permissions for our application - a daunting task.

So, to force a re-prompt, we have tried setting the prompt=consent parameter for /authorize (per the following doc https://auth0.com/docs/connections/social/reprompt-permissions.)

Facebook re-prompts (good), however the third-party consent dialog also displays (not desireable).
https://auth0.com/docs/api-auth/user-consent

Is it possible to get FB to re-prompt w/o the third-party consent dialog displaying?

If not, does anyone have any alternate ideas for handling the above declined social / authorization permissions?


#2

I don’t think that’s possible at this time as the act of requesting consent by the client application as the side-effect of requesting consent not just at Facebook, but also at Auth0. I’m not providing this as an answer because I’m trying to know for sure if there are no alternatives where consent would only be triggered in Facebook; will keep you posted when I have additional information.


#3

I did some further research after my initial comment and at this time I could not find a way to do this with the Facebook connection; there is a functionality that is going to be available in the future (it’s not final nor documented yet) that could technically allow for this, but with a big disclaimer that it would be a sort of hack. In conclusion, this does not seem possible with what’s available/documented for the Facebook built-in connection.

In terms of handling this I would maybe consider a redirect rule that would redirect the end-user to a specific URL that would let them know that by removing the email permission they cannot continue to your application. This redirect could either give them the option to reconfigure their FB permissions (although you say that may be complex so even with some instructions this may not make sense) or just manually provide an email that would be associated only in the Auth0 user profile and that your application could use to interact with the user in terms of email. The second option would imply storing this email as part of metadata instead of reading it from the root user profile where it would be available if coming from the IdP so this may or may not be acceptable.


UPDATE (workaround using an additional custom OAuth 2.0 connection):

You could consider taking the following steps:

  1. Maintain your Facebook connection as is;
  2. Create an additional OAuth 2.0 custom connection, named custom-fb, that targets Facebook and uses the same client identifier and secret that you provided for the built-in FB connection;
  3. Configure custom-fb with the same scopes being requested by the built-ind FB connection;
  4. Configure custom-fb in a way that every request processed through this connection always triggers consent in Facebook (more on this later);
  5. Associate custom-fb to a new client application FB Consent that will be used only to show a simple page https://example.com/fb/email-required telling the user he can’t deny the email permission and will have to repeat the FB consent screen;
  6. When your application detects a FB user without email it redirects them to https://example.com/fb/email-required which explains the situation to them and presents a button REPEAT CONSENT. This button does nothing more then to trigger an authentication request using client application FB Consent and the custom-fb connection.
  7. If the response now contains an email then FB Consent can redirect back to the original client application which should trigger again an authentication request now using its own client identifier and the built-in FB connection (since the user already has a session in Facebook and there’s no consent, this completes automatically and the email will now also be returned).

The above is complex, but has the following benefits:

  • you continue to use FB built-in connection for almost everything as you only rely on the custom connection for a very small set of users.
  • by associating custom connection to a new client application you keep this hack contained and isolated in a way that if a solution appears for the FB built-in connection you can just delete the custom connection and relevant client application.

Here’s the custom OAuth 2.0 connection I used to quickly test part of this flow (it’s in YAML because I use a custom tool to initialize my test tenant, but you can convert it to JSON and use it almost directly against Management API):

name: custom-facebook
options:
  client_id: {your_fb_client_id}
  client_secret: {your_fb_client_secret}
  scripts:
    fetchUserProfile: |
      function(accessToken, ctx, cb) {
        var url = `https://graph.facebook.com/v2.6/me?access_token=${accessToken}&fields=id,about,age_range,birthday,context,cover,devices,updated_time,education,email,favorite_athletes,favorite_teams,first_name,gender,hometown,inspirational_people,installed,is_verified,languages,last_name,link,locale,picture.width(999999).as(picture_large),picture,location,middle_name,name,name_format,political,quotes,relationship_status,religion,significant_other,timezone,third_party_id,verified,website,work`;

        request.get(url, {}, function(e, r, b) {
          if (e) return cb(e);

          if (r.statusCode !== 200) return cb(new Error('StatusCode|' + r.statusCode));

          cb(null, JSON.parse(b));
        });
      }
  authorizationURL: "https://www.facebook.com/v2.11/dialog/oauth"
  tokenURL: https://graph.facebook.com/v2.11/oauth/access_token
  scope: "email,user_birthday,user_hometown,user_location"
  authParams:
    auth_type: "rerequest"
strategy: oauth2

Important: the fetchUserProfile script was the bare minimal to test it and was copy pasted from another custom connection I had so that would be something you may want to revise and make more robust. In addition, the scopes would also need to be updated to match yours.


#4

Thanks @jmangelo. The really bad thing about this is that even if we manually/automated delete the user in Auth0 so that they have to signup again, that doesn’t help.

Another Auth0 employee suggested to research: https://auth0.com/docs/extensions/custom-social-extensions What do you think of that as a solution? The idea is, either our clients, or our HLP, needs to take action on behalf of this user (who is easy to identify because they’re one of the few poor souls in our Auth0 tenant without an email). One or the other (client or HLP) needs to force FB to re-prompt the user.


#5

Thanks @jmangelo. The really bad thing about this is that even if we manually/automated delete the user in Auth0 so that they have to signup again, that doesn’t help.

Another Auth0 employee suggested to research: https://auth0.com/docs/extensions/custom-social-extensions What do you think of that as a solution? The idea is, either our clients, or our HLP, needs to take action on behalf of this user (who is easy to identify because they’re one of the few poor souls in our Auth0 tenant without an email). One or the other (client or HLP) needs to force FB to re-prompt the user.


#6

I can think of an hack that would address this through an additional custom OAuth 2.0 connection; I can’t say for sure if that was the solution my colleague was hinting to when he mentioned that link, but it would work. Like I said it falls under the category of hacks and would require you to have an additional connection besides the Facebook built-in one; it would also imply that at least temporarily there would be duplicate users in your tenant.

If you think those side-effects are manageable let me know and I can revise my answer to include the necessary steps to do this.


#7

I just realized that a reply posting can only include 600 chars, so I can’t share what the other Auth0 employee provided. Let me know if there is another way I can share this (it’s short ~ 1,000 chars). Yes, I’m interested in the steps to creating our own FB connection. I probably don’t yet have a proper understanding of what Im asking for, but we are interested in the potential of using a custom social connection if it is straightforward. It appears there is no solution to this problem (vis-a-vis Auth0) without either punting on it (making the user fix it), or using some form of ‘hack’.


#8

Yes, comments do have that limit; the idea would be to have short discussions in comments and big stuff which would be relevant is either included in a question update or answer update. I’ll revise my answer with the approach I thought of; in relation to the info you have been given if you think it’s relevant just include it in a question update (if the reply contains information very specific to your case case that you don’t want to make public then feel free to send it to joao[d0t]angelo[at]auth0[d0t]com).


#9

I have now updated my answer.


#10

We’re looking at the same problem: we allow fb sign ups, but need to disallow null email fields. My concern with the re-consent solution is that some fb users don’t have email addresses at all-- fb allows phone number-only sign ups. Because of this we’re looking at the metadata solution you mentioned above: redirecting to a page that manually requires an email address, then storing it in user metadata. It ain’t as pretty as having it in the core auth0 data, but it’ll work for our purposes. I just wish there were a way to keep the manual email UI within lock, for continuity.


#11