facebook-sdk-for-unity icon indicating copy to clipboard operation
facebook-sdk-for-unity copied to clipboard

With Apple ATT refused by user, Facebook classic login fallback in a limited login and returns a non valid authentication token

Open Jaeger87 opened this issue 1 year ago • 15 comments

Checklist

Environment

Describe your dev environment here, giving as many details as possible. If you have them, make sure to include:

  • Unity Editor Version: 2022.3.20
  • Unity SDK Version: 17.0.2
  • Installation Platform & Version: [iOS] version 17.4.1

Goals

To know if a user is authenticated with classic or limited login.

Expected Results

If facebook classic login fallback to limit login, I expect access_token to be null and not populated with a no valid access_token

Actual Results

When the sdk fallback to limited login, access_token is populated with a non valid token.

Steps to Reproduce

Refuse or not accept ATT, then login with FB.LogInWithReadPermissions(permissions, resultHandler)

Jaeger87 avatar May 06 '24 16:05 Jaeger87

I have the same issue and i think facebook couldn't fix this issue, and i can't fixed this. Facebook is regret.

@Jaeger87 if you find a solution please let me know.

saltlevent avatar May 16 '24 11:05 saltlevent

Currently facing the same issue, and it was not happening before we upgraded to 17.0.2. If you guys find a workaround, please share it 🙏

PierrePlayrion avatar Jun 17 '24 09:06 PierrePlayrion

Currently facing the same issue, and it was not happening before we upgraded to 17.0.2. If you guys find a workaround, please share it 🙏

I found a solution. Actually it's the only solution i found. You have to downgrade the facebook sdk version. I chose 16.0.2 and it worked. After downgrading the version, sdk works properly and had no problem so far.

saltlevent avatar Jun 18 '24 14:06 saltlevent

I found a solution. Actually it's the only solution i found. You have to downgrade the facebook sdk version. I chose 16.0.2 and it worked. After downgrading the version, sdk works properly and had no problem so far.

But I assume that you would have difficulties submitting any build through the app store without the privacy manifest required by Apple (and added in 17.0.0), unless you're adding this yourself (In that case, that could be a solution).

I found that in case of ATT begin opt out, we need to use the Limited Login. I wasn't able to test it to confirm it works.

Maybe someone can confirm this 😄

PierrePlayrion avatar Jun 19 '24 13:06 PierrePlayrion

I added my privacy policy by myself via my own website. In 17.0.0 version, facebook login redirecting to the limited.facebook domain. Now its working correctly and app is now on the store (iOS and android)

saltlevent avatar Jun 20 '24 06:06 saltlevent

I added my privacy policy by myself via my own website. In 17.0.0 version, facebook login redirecting to the limited.facebook domain. Now its working correctly and app is now on the store (iOS and android)

Can you please tell me what your login method looks like now? Is it still through FB.LogInWithReadPermissions or now through FB.Mobile.LoginWithTrackingPreference? We also have SDK version 17.0.0, but att reject still blocks the user from logging in. It is not very clear whether the login code needs to be changed.

JimboA avatar Jun 20 '24 10:06 JimboA

My login methot is this:

public void LoginFacebook() { var perms = new List() { "public_profile", "email" }; FB.LogInWithReadPermissions(perms, AuthCallback); }

saltlevent avatar Jun 20 '24 10:06 saltlevent

My login methot is this:

public void LoginFacebook() { var perms = new List() { "public_profile", "email" }; FB.LogInWithReadPermissions(perms, AuthCallback); }

Thank you!) And it's working even if user refuse att? With sdk version 17.0.0 am I understanding correctly? If so it's strange because in our case it's not working( Did you do any additional things?

JimboA avatar Jun 20 '24 11:06 JimboA

All i did was downgrading the version of the facebook sdk to 16. Maybe you can check the keystore sha. facebook sdk cant encyript the sha with editor tool sometimes. Use keytool and openssl to generate the keystore hash by yourself.

saltlevent avatar Jun 23 '24 00:06 saltlevent

We are struggling the same issue. And downgrading to 16.0.2 is not an option. Any other suggestions?

mtemnikov avatar Jul 30 '24 18:07 mtemnikov

We are struggling the same issue. And downgrading to 16.0.2 is not an option. Any other suggestions?

Problems still persist, they seem to have abandoned the SDK completely. This is a direct result of a large number of employees being laid off.

kiyakkoray avatar Aug 01 '24 08:08 kiyakkoray

@Jaeger87 I tried implement that with unity 2021 and SDK latest version (17.0.1) and I really didn't understand how they expects my application login flow should run. In case the user logged in via the classic method and then switch ATT after a few sessions. How I can "downgrade" the user to the limited without actually asking for a new login process ?

MrLijan avatar Aug 04 '24 13:08 MrLijan

Hello, we changed old login route to limit login route and it worked fine. Be aware that backend validation has also been changed.

mtemnikov avatar Aug 09 '24 09:08 mtemnikov

Hello, we changed old login route to limit login route and it worked fine. Be aware that backend validation has also been changed.

How do you switch between them? How does your code runs when user logged in with limited and then allowing tracking? Or the opposite way

MrLijan avatar Aug 09 '24 11:08 MrLijan

Hello, we changed old login route to limit login route and it worked fine. Be aware that backend validation has also been changed.

How do you switch between them? How does your code runs when user logged in with limited and then allowing tracking? Or the opposite way

We are switching between them on different platforms: using old login on android and new on ios.

Here is the code for ios part:

        private void Authorize()
        {
            if (FB.IsLoggedIn)
            {
                try
                {
                    AuthenticationToken currentToken = FB.Mobile.CurrentAuthenticationToken();
                    if (currentToken != null)
                    {
                        DateTime expirationDateTimeUTC = GetExpirationDateTime(currentToken.TokenString);
                        if (expirationDateTimeUTC > DateTime.UtcNow)
                        {
                            Logger.Log($"[FB] Using received early token");
                            TryHandleToken(currentToken);
                            return;
                        }
                    }
                }
                catch (Exception e) 
                {
                    Debug.LogException(e);
                }
            }
            List<string> permissions = new List<string>()
            {
                "public_profile"
            };
            if (_requirements.RequestEmail)
            {
                permissions.Add("email");
            }
            FB.Mobile.LoginWithTrackingPreference(LoginTracking.LIMITED, permissions, "nonce_stub", HandleAuthorized);
        }

        private void HandleAuthorized(ILoginResult result)
        {
            if (result == null)
            {
                Debug.LogError($"[FB] Received null result. Trying to use old token");
                AuthenticationToken oldToken = FB.Mobile.CurrentAuthenticationToken();
                TryHandleToken(oldToken);
                return;
            }
            Logger.Log($"[FB] Raw result {result.RawResult}");
            if (!string.IsNullOrEmpty(result.Error))
            {
                HandleError(result.Error, result.RawResult);
                return;
            }
            if (result.Cancelled)
            {
                PlatformAuthorizationResult authResult = new PlatformAuthorizationResult(AuthorizationModule.Facebook, Result.Canceled, string.Empty, null);
                HandleResult(authResult);
                return;
            }
            TryHandleToken(result.AuthenticationToken);
        }

        private void TryHandleToken(AuthenticationToken token)
        {
            Profile profile = FB.Mobile.CurrentProfile();
            if (profile == null) 
            {
                HandleError($"No fb profile", string.Empty);
                return;
            }
            FacebookCredentials credentials = ProvideCredentials(token, profile);
            PlatformAuthorizationResult authResult = new(AuthorizationModule.Facebook, Result.Success, string.Empty, credentials);
            HandleResult(authResult);
        }

        private DateTime GetExpirationDateTime(string token)
        {
           
            string[] parts = token.Split('.');
            if (parts.Length != 3)
            {
                throw new ArgumentException("Invalid token format");
            }

            string payload = parts[1];
            byte[] jsonBytes = Convert.FromBase64String(DecodeBase64Url(payload));
            string json = Encoding.UTF8.GetString(jsonBytes);
            
            JObject jObject = JObject.Parse(json);
            
            if (jObject.TryGetValue("exp", out var expToken))
            {
                long expUnixTime = expToken.ToObject<long>();
                DateTime expirationDate = DateTimeOffset.FromUnixTimeSeconds(expUnixTime).UtcDateTime;
                return expirationDate;
            }
            throw new InvalidOperationException($"Unable to find exp field at JWT payload");
        }
        private string DecodeBase64Url(string base64Url)
        {
            return base64Url.Replace('-', '+').Replace('_', '/') + new string('=', (4 - base64Url.Length % 4) % 4);
        }

mtemnikov avatar Aug 13 '24 05:08 mtemnikov