Firstly, it's been a while since I've published a Facebook app to support Facebook Login and I'm not sure whether the status Published
is the same as Live
, can anyone confirm that?
I recently updated Facebook Login to Facebook Limited Login (Facebook SDK v.17.0.1). Prior to this update, the classic Facebook Login was working fine in dev mode.
My issue is that I can't login, because I either don't receive a AuthenticationToken
or that I receive a status cancelled
(I'm testing on iOS 17.4.1).
The flow is as follows:
I'm creating a LoginConfiguration
instance with a SHA256 nonce as below:
let rawNonce = String.randomNonceString()
let sha256Nonce = rawNonce.sha256
let config = LoginConfiguration(permissions: ["public_profile", "email"], tracking: .enabled, nonce: sha256Nonce)!
Once I have the config
I'm using it to login, and I'm accessing the token from the AuthenticationToken.current
as per the Limited Login docs here.
let loginManager = FacebookLogin.LoginManager()
loginManager.logIn(viewController: viewController, configuration: configuration) { result in
switch result {
case .success(let grantedPermissions, let declinedPermissions, let token):
let authTokenString = AuthenticationToken.current?.tokenString
// Create OAuth credential for Firebase Auth using the authTokenString and rawNonce
case .cancelled:
// User cancelled login
case .failed(let error):
print(error)
}
}
I have identified the following issues:
- With a user that has an App Role in the Facebook app, everything works great.
- With a production user that doesn't have an App Role in the Facebook app, the login fails with 2 different scenarios:
Scenario A:
If I pass tracking .enabled
on the LoginConfiguration
instance then the login function returns result .success
, but the AuthenticationToken.current
is nil
.
Scenario B:
If I pass tracking .limited
on the LoginConfiguration
instance then the login function returns result .cancelled
which makes no sense.
Other things I tried:
- I have tried enabling App Tracking Transparency prior to logging in, but the above behaviour remained the same.
- According to Facebook's Limited Login docs I understand that I shouldn't be using the
AccessToken
returned in the login's callback anymore, and I should use the globalAuthenticationToken
(and also theProfile
to directly receive user's name, email, etc). However, I have tried creating the Firebase Auth credential with theAccessToken
that's returned in the login's callback, but Firebase Auth sign in failed with the errorBad access token
. - I tried accessing the
AuthenticationToken
every 0.5 sec until it's notnil
, but this didn't work either. - I tried on both the Simulator and a real device.
UPDATE
The functions for the random nonce string and SHA256 are the following:
public extension String {
static func randomNonceString(length: Int = 32) -> String {
precondition(length > 0)
var randomBytes = [UInt8](repeating: 0, count: length)
let errorCode = SecRandomCopyBytes(kSecRandomDefault, randomBytes.count, &randomBytes)
if errorCode != errSecSuccess {
fatalError(
"Unable to generate nonce. OSStatus \(errorCode)"
)
}
let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._")
let nonce = randomBytes.map { byte in
charset[Int(byte) % charset.count]
}
return String(nonce)
}
var sha256: String {
let inputData = Data(self.utf8)
let hashedData = SHA256.hash(data: inputData)
let hashString = hashedData.compactMap { String(format: "%02x", $0) }.joined()
return hashString
}
}
Tried again today (03/07/2024) without changing anything in my codebase and it worked. So I'll assume that this was something with Facebook's BE when they originally released Limited Login. For reference, here's the issue on Github https://github.com/facebook/facebook-ios-sdk/issues/2387