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:
- Maintain your Facebook connection as is;
- 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;
- Configure
custom-fb
with the same scopes being requested by the built-ind FB connection;
- Configure
custom-fb
in a way that every request processed through this connection always triggers consent in Facebook (more on this later);
- 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;
- 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.
- 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.