firebase / firebase-ios-sdk

Firebase SDK for Apple App Development
https://firebase.google.com
Apache License 2.0
5.6k stars 1.47k forks source link

Firebase Auth with Microsoft (Azure AD) - Login not possible - "Unable to process request due to missing initial state" #7153

Open SKuhlemann opened 3 years ago

SKuhlemann commented 3 years ago

[REQUIRED] Step 1: Describe your environment

[REQUIRED] Step 2: Describe the problem

Steps to reproduce:

When logging in to Firebase with Microsofts Azure AD as an authentication service by using provider.getCredentialWith(_: nil) I am able to open the Microsoft login page. After entering the correct email + password then the following error appears inside the In-App-Browser: "Unable to process request due to missing initial state. This may happen if browser sessionStorage is inaccessible or accidentally cleared."

What did work for me as a workaround: In my completion handler of provider.getCredentialWith(_: nil) I call the same function with a delay of 1second again if an error was thrown. On the second run it always succeeds and gives me the credentials back.

Relevant Code:

                        provider.getCredentialWith(_: nil){credential, error in
                            if error != nil {
                                self.errorText = "Error"
                                return
                            }
                            if let credential = credential {
                                firebaseSignIn(credential: credential)
                            }
                        }
rahulkumarsingh73690 commented 3 years ago

Same issue :(

hicreate commented 3 years ago

Same issue

atrimn commented 3 years ago

same issue

Raphaelinyang commented 3 years ago

same issue for google sign in on web

AppKidd commented 3 years ago

Same issue. Please fix, we want to use Firebase for auth but this is making it very difficult 🥵

nagaperla commented 3 years ago

Same issue.

sam-gc commented 3 years ago

Hi folks, this is potentially related to https://github.com/firebase/firebase-js-sdk/issues/4256. Unfortunately we've repeatedly struck out trying to reproduce it.

mortenbekditlevsen commented 3 years ago

I got the Firebase Auth SDK for iOS to work with a custom auth domain by swizzling (until we get proper support for custom auth domains in the iOS SDK).

I have not verified yet if this makes the sign in more stable.

USE AT YOUR OWN RISK:

@objc class MyFIRAuthWebUtils: NSObject {
    @objc class func supportedAuthDomains() -> NSArray {
        return ["mydomain.dk"]
    }
}

// Ensure that swizzling only happens once by letting it be a lazy
// global init
private let swizzleSupportedAuthDomains: Void = {
    guard let aClass: AnyClass = NSClassFromString("FIRAuthWebUtils") else { return }
    // The class name of the selector doesn't actually matter. But using this annotation rather than a
    // String silences Xcode warnings.
    guard let originalMethod = class_getClassMethod(aClass, #selector(MyFIRAuthWebUtils.supportedAuthDomains)) else { return }

    guard let swizzledMethod = class_getClassMethod(MyFIRAuthWebUtils.self, #selector(MyFIRAuthWebUtils.supportedAuthDomains)) else { return }

    // switch implementation..
    method_exchangeImplementations(originalMethod, swizzledMethod)
}()

Make sure to call _ = swizzleSupportedAuthDomains somewhere before attempting to sign in.

The auth domain of course needs to be configured in firebase auth. Note that the firebase sdk code that looks through the supportedAuthDomains state that the order of the domains in the array matters. That is not true - the authorizedDomains from the web response is looped through in the outer loop, so the first authorized domain that matches a domain in the supportedAuthDomains 'wins'. In other words - it doesn't help putting ["mydomain.dk", "firebaseapp.com", "web.app"] in the list - this will cause it to choose "firebaseapp.com" in my experimentation, since this comes before my custom auth domain in the firebase auth configuration.

I will return with my findings on this.

mortenbekditlevsen commented 3 years ago

TL;DR: Disable 'Prevent Cross-Site Tracking' on the user's device appears to make the issue go away.

I now have some findings: Using the custom auth domain did not have any effect for me (I'll still keep it though, as it's nice to see our own domains while logging in).

But I did manage to find something that immediately fixed the issue! I experienced the issue in the iPad simulator. I went into Settings -> Safari and disabled 'Prevent Cross-Site Tracking'. Going back to our app this allowed me to sign in.

I had a colleague verify this behavior on an actual device - and I was also able to verify on an actual iPhone.

My conclusion: When 'Prevent Cross-Site Tracking' is enabled I experienced that I could some times log in, but other times I got the "Unable to process request due to missing initial state..." With the setting disabled I have not yet experienced the issue.

@samhorlbeck do you think that this information is of use for you in order to find a way to fix the issue without requiring the users to disable cross site tracking prevention?

MauriceS commented 3 years ago

I can confirm the solution that @mortenbekditlevsen described. I had no problems with logging in with Azure AD until today when I received the above error message (almost) all the time. 9 out of 10 times I was not able to login, but sometimes it just went through fine. Disabling "Prevent Cross-Site Tracking" however fixed the issue, and I'm able to login every single time. I hope a solution will be found that does not require the user to change this cross-site tracking option for Safari.

k90armstrong commented 2 years ago

Any update on this issue?

iamswain25 commented 2 years ago

I tried all of the methods listed in the link but didn't work. interesting thing is, when I signInWithPopup it works fine, but when I access the app from microsoft azure ad myapp list, it fails at the https://******/__/auth/handler. trying to implement SSO-SAML here.

kbot commented 2 years ago

This may be partially unrelated as I'm using FirebaseAuthUI, but just in case this helps anyone else that ends up here this is what worked for me.

  1. Use the firebase provided Web Redirect URL in the Authentication section of your Azure App.
  2. Add your REVERSED_CLIENT_ID from your GoogleServices-Info.plist to your apps CFBundleURLTypes (best done through your Target -> Info view at the bottom )
  3. Handle the callback URL with FIRAuth in addition to AuthUI in application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options (sorry for the Obj-C, my app is old)
    urlWasHandled = [[FUIAuth defaultAuthUI] handleOpenURL:url sourceApplication:sourceApplication];
    if (!urlWasHandled) {
    urlWasHandled = [[FIRAuth auth] canHandleURL:url];
    }

Lastly, I noticed my iOS app was not handling FIRAuthErrorCodeAccountExistsWithDifferentCredential correctly. It wasn't even getting a callback for the error. This was caused by me not enabling email authentication (we only use social). Some bad code in FUIAuth assuming a non-null emailAuthProvider was swallowing the error. To fix this, I created a strong reference to an FUIEmailAuth* which resolved that assumption and now properly handles pushing the user to another provider if the email matches and links the account (shows both provider icons in the Authentication view in firebase).

@property (nonatomic, strong) FUIEmailAuth* emailAuthProvider;
@end
@implementation LandingPageViewController
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.emailAuthProvider = [[FUIEmailAuth alloc] init];
    }
    return self;
}

After those steps, I was properly authenticating and no longer landing on aboutblank or "missing initial state"

nayooti commented 2 years ago

@kbot 's solution worked for us. Thank you!

Here is the Swift-version for apps that take use of sceneDelegate (step 3):

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard
        let url = URLContexts.first?.url.absoluteURL,
        let sourceApplication = URLContexts.first?.options.sourceApplication,
        let authUI = FUIAuth.defaultAuthUI()
    else { return }
    let handle = authUI.handleOpen(url, sourceApplication: sourceApplication)
    if !handle {
        Auth.auth().canHandle(url)
    }
}
MauriceS commented 2 years ago

I have been implementing the above workarounds, but there are still users reporting that they receive the "Unable to process request due to missing initial state. This may happen if browser sessionStorage is inaccessible or accidentally cleared." error while signing in with Microsoft. It happens on random devices and random user accounts.

I have not been able to reproduce it myself which makes this hard to debug. Does someone know where this error message is originating from? Is it the in-app web browser, or the google firebase web service?

prameshj commented 2 years ago

I have been implementing the above workarounds, but there are still users reporting that they receive the "Unable to process request due to missing initial state. This may happen if browser sessionStorage is inaccessible or accidentally cleared." error while signing in with Microsoft. It happens on random devices and random user accounts.

I have not been able to reproduce it myself which makes this hard to debug. Does someone know where this error message is originating from? Is it the in-app web browser, or the google firebase web service?

Hi,

This error message is thrown by the firebase auth libraries that complete the OAuth flow. This library stores a bunch of state (apiKey, redirect uri, session identifier and more) in browser session storage, which it needs to access upon completion of the OAuth flow, before redirecting to the app. If it cannot access session storage for any reason, this error message is thrown. It is somewhat of a generic error message, because we do not have additional context on what exactly went wrong when accessing storage.

iamswain25 commented 2 years ago

I tried all of the methods listed in the link but didn't work. interesting thing is, when I signInWithPopup it works fine, but when I access the app from microsoft azure ad myapp list, it fails at the https://******/__/auth/handler. trying to implement SSO-SAML here.

my problem is solved. firebase sdk doesn't support idp initiated SAML flow. that's why it was showing the error page. it could have been better if it shows the exact error msg: "idp initiated SAML flow not supported."

bw-flagship commented 1 year ago

Just commenting to mention that this is still an existing important problem.

cedricboidin commented 1 year ago

Hi, I encountered the same issue when trying to use the OauthProvider for an OpenID connector configured for a Google workspace.

I found a workaround by forking FirebaseAuth and using an ASWebAuthenticationSession instead of the SFSafariViewController to open the authentication URL. You can find the implementation here : https://github.com/kraaft-co/firebase-ios-sdk/commit/3b47b1928eda255ab37525ce91711ef448b6f148

There are some side effects :

If this proposition seems promising, I would be happy to help building a PR based on this.

paulb777 commented 1 year ago

@cedricboidin Thanks for the offer. We don't have a lot of bandwidth to help with a PR on this right now, but hopefully that will change later this year.

k-armstrong commented 1 year ago

Any update on this? Would love a fix for this :)

joe-squint commented 3 weeks ago

Any update on this? Our Microsoft users have been running into this sporadically for months now.

paulb777 commented 3 weeks ago

Is the issue still occurring with Firebase 11.x? A self-contained reproducible example would help an investigation.

joe-squint commented 3 weeks ago

We're still using a Firebase 10.x version, we'll need to do some updates and testing to confirm that 11.x fixes this.

We haven't been able to come up with a reproducible scenario for this. The issue only occurs with Microsoft auth and often times if the user retries moments later it works.