When using Microsoft as a provider in Firebase Auth, after signing in UIApplication:open:url is called with the redirection. But there is nothing in the documentation (https://firebase.google.com/docs/auth/ios/microsoft-oauth) about how to handle it and to get the sign in page to close.
For GoogleAuthProvider you would call GIDSignIn.sharedInstance().handle(url...) in UIApplication:open:url to handle the redirection, which closes the WebView and works great.
Can not find anything out there on how to handle the redirect.
var provider: OAuthProvider?
#IBAction func buttonTapped(_ sender: Any) {
provider = OAuthProvider(providerID: "microsoft.com")
provider?.customParameters = [
"prompt": "consent",
"login_hint": "",
]
provider?.getCredentialWith(nil ) { credential, error in
if error != nil {
// Handle error.
}
print(credential?.provider)
if let credential = credential {
Auth.auth().signInAndRetrieveData(with: credential)
{ (authResult, error) in
print(authResult?.additionalUserInfo?.profile)
print(authResult?.user.providerID)
}
} else {
}
}
}
I would expect after the user has signed in, the Microsoft SignIn page would close and getCredentialWith completion would be called.
Related
I am currently working on the signup/login of my app using Firebase Authentication.
I have custom buttons for Facebook Signup/Login and Google Signup/Login.
For example, the code for the Facebook Signup/Login button is
#objc private func performFacebookLogin(_ sender: UIButton) {
let fbLoginManager : LoginManager = LoginManager()
fbLoginManager.logIn(permissions: ["email"], from: self) { (result, error) -> Void in
if let error = error {
print(error)
} else {
if result == nil {
print("no result!")
return
}
if AccessToken.current == nil {
print("no token")
return
}
DispatchQueue.main.async {
ThirdPartySignupViewController.push(fromVC: self, method: .facebook)
}
}
}
}
This will take the user to another view controller to add additional information to their account if they have not yet created an account in the app using this Facebook account.
However, I can not find any way to determine whether or not the Facebook account has previously used for an account in the app, in which case I want to just log the user in and take them to the main screen. Is there a way to do this?
I have tried the signIn(with:) method, hoping that it would return an error if there is no account in the app with the credentials of this Facebook account, but this will not work because this will end up creating a new account if the Facebook account hasn't been used previously to create an account.
let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)
Auth.auth().signIn(with: credential) { (authResult, error) in
//check if I get an error if the Facebook account has not been used
}
(EDIT) The desired flow is 1.Sign in with Facebook/Google → 2.Enter additional info → 3.Create account on Firebase Authentication.
When authenticating with Firebase - the Auth object returns isNewUser through additionalUserInfo. Therefore you can see the status of a new or existing user.
let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)
Auth.auth().signIn(with: credential) { (authResult, error) in
//authResult?.additionalUserInfo?.isNewUser
if let auth = authResult{
if auth.additionalUserInfo?.isNewUser {
// User has not been authenticated before. Do what you need
} else {
// User has been authenticated before
}
}
}
I'm fairly new to Swift and Firebase and I'm trying to get the Microsoft OAuth provider working as described here:
https://firebase.google.com/docs/auth/ios/microsoft-oauth?authuser=0
My App is stable when run, but the MSLoginTapped button does nothing and when debugging I'm only able to see that provider.getCredentialWith doesn't appear to run because I do not receive my print statement.
There seemed to be multiple errors in the documentation, so I doctored it up as best possible and submitted a request for review of the documentation.
Firebase Documentation snippet:
provider.getCredentialWithUIDelegate(nil) { credential, error in
if error != nil {
// Handle error.
}
if credential != nil {
Auth().signInAndRetrieveData(with: credential) { authResult, error in
if error != nil {
// Handle error.
}
// User is signed in.
// IdP data available in authResult.additionalUserInfo.profile.
// OAuth access token can also be retrieved:
// credential.accessToken
}
}
}
Problem 1: provider.getCredentialWithUIDelegate is not recognized.
Problem 2: Auth().signInAndRetrieveData is not recognized.
========== ========== ========== ========== ==========
Here's what I'm working with (that's NOT working):
class LoginViewController: UIViewController {
var ref : DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func MSLoginTapped(_ sender: UIButton) {
let provider = OAuthProvider(providerID: "microsoft.com")
provider.getCredentialWith(nil) { (credential, error) in
if error != nil {
// Handle error.
print("Failed to retreive credential.")
return
}
if credential != nil {
Auth.auth().signInAndRetrieveData(with: credential!) { authResult, error in
if error != nil {
// Handle error.
}
// User is signed in.
// IdP data available in authResult.additionalUserInfo.profile.
// OAuth access token can also be retrieved:
// credential.accessToken
}
} else {
print("Credential is nil.")
}
}
}
}
Ran into the same problem.
let provider = OAuthProvider(providerID: "microsoft.com")
provider is a local variable, getCredentialWith is async and ARC will get rid of provider. Make it global scope.
Firebase does not show up sign page for microsoft.com in Swift / iOS
So firebase recently supported phone auth, but the problem is that the documentation is in objective-c. And I have never done push notifications before. this is a link to the objc phone auth docs: https://firebase.google.com/docs/auth/ios/phone-auth
You can see an example in the official sample repo: https://github.com/firebase/quickstart-ios/blob/master/authentication/AuthenticationExampleSwift/MainViewController.swift#L161
The core process is like this:
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber) { (verificationID, error) in
if let error = error {
// TODO: show error
return
}
guard let verificationID = verificationID else { return }
verificationCode = // TODO: get SMS verification code from user.
if let verificationCode = verificationCode {
let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID, verificationCode: verificationCode)
Auth.auth().signIn(with: credential) { (user, error) in
// TODO: handle sign in
}
} else {
// Verification code was empty
}
}
}
You'll need to plug in UI to prompt the user (thats in the sample), or take advantage of FirebaseUI to handle it all for you: https://github.com/firebase/FirebaseUI-iOS
Question: How do I get the google sign-in page every time user signs-in after signing out?
Issue: Once user signs in for the first time (google sign in pops up) and once the user signs in for the second time. (the google sign in page doesn't pop up) and signs in the user w/o signing in again with their user Google credentials (eg. email, password)
Google Sign-out Button Function
// Sign user out of main application
#IBAction func signOutButtonDidTouch(_ sender: Any) {
// Firebase user authentication fuction
let firebaseAuth = FIRAuth.auth()
if firebaseAuth?.currentUser != nil {
// If there is a user signed-in
do {
try firebaseAuth?.signOut()
print("[Google] signing out successful")
if firebaseAuth?.currentUser == nil {
// Performs current view controller transition to SignInViewController
performSegue(withIdentifier: "signOutSegue", sender: self)
}
}catch let signOutError as NSError {
print("Error signing out: %#", signOutError)
print("[Google] signing out error")
}
}
You sign out of Firebase Auth, but you're still signed in with Google (there is a token in the keychain on the device). If you sign out of the Google account as well, that should address it:
GIDSignIn.sharedInstance().signOut()
Firebase Auth treats Google as just another identity provider, as with Facebook or Twitter, so it doesn't tweak the state of that when the Firebase Auth state changes.
I have same problem. Firstly I can login with email and password.
Then I can signing with google successfully.
After that, I tried to logout from Google again.
When I re-authenticaite with email and password, this message is returned: "The password is invalid or the user does not have a password."
On Firebase console, the users account symbol change from mail to Google.
I couldn't solve this problem. What is my wrong?
In AppDelegate.swift:
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let error = error {
log.debug("Error Google Sign-in: \(error)")
return
}
guard let authentication = user.authentication else { return }
let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
accessToken: authentication.accessToken)
Auth.auth().signInAndRetrieveData(with: credential) { (authResult, error) in
if let error = error {
log.error(error)
return
}
// User is signed in
}
}
This is the logout button action:
#IBAction func logout_TouchUpInside(_ sender: Any) {
do {
try Auth.auth().signOut()
GIDSignIn.sharedInstance().signOut()
} catch let error {
self.writeReport(string: error.localizedDescription)
log.error(error.localizedDescription)
self.showAlert(title: "Error", message: error.localizedDescription)
}
log.info("After logout current user: \(String(describing: Auth.auth().currentUser))")
}
I'm using Firebase Auth to allow users to sign up using Facebook. I have taken all the steps from here to implement sign up including adding GoogleService-Info.plist to my project.
I get the Facebook permission screen all fine but when the app hits
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in
this error is returned: An invalid API Key was supplied in the request.
Can anyone help me with this please?
Thanks
Here is my function code to log in using Facebook.
#IBAction func signUpWithFacebook() {
let fbLogin = FBSDKLoginManager()
fbLogin.logInWithReadPermissions(["email"], fromViewController:self, handler: {
(result, error) -> Void in
if ((error) != nil) {
print("Process error")
} else if (result.isCancelled) {
print("Cancelled");
} else {
print("Logged in");
let accessToken = FBSDKAccessToken.currentAccessToken().tokenString
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)
print(FBSDKAccessToken.currentAccessToken().tokenString)
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in
// ...
if let user = user{
print(user.displayName)
}
else{
if let error = error {
print(error.localizedDescription)
}
}
}
}
})
}
Solved it, for anyone that needs the solution in the future.
Sometimes API_KEY is missing from the GoogleService-Info.plist, this needs to be added.
The API Key can be found from Google API Console https://console.developers.google.com/
You can solve this by Downloading again the "GoogleService-Info.plist" file, under the Project Setting section on Firebase Console.
Ensure that the API_KEY is set on the new "GoogleService-Info.plist".