Missing initial state in WebAuthenticator login attempt - firebase

working on a .NET MAUI app and am trying to implement Firebase Authentication with the help of WebAuthenticator in MAUI. I get to the login form in a browser, but after logging in get the error
Unable to process request due to missing initial state. This may happen if browser sessionStorage is inaccessible or accidentally cleared.
This is the code that calls the authenticator
await client.SignInWithRedirectAsync(FirebaseProviderType.Google, async uri =>
{
var options = new WebAuthenticatorOptions
{
Url = new Uri(uri),
CallbackUrl = new Uri("com.companyname.myappname://callback/"),
PrefersEphemeralWebBrowserSession= true
};
var res = await WebAuthenticator.Default.AuthenticateAsync(options);
});
I think the problem could be the callback URL, but I'm not sure how to write it differently since I'm not using a backend API. Does anyone have any suggestions?
Thanks!
P.S. This happens with bost Firebase Google auth and Facebook login

You can try to clear the chrome browser data and reload the page to see if it works. This is a known problem of firebase. You can continue to follow up this github iissue: Unableto process request due to missing initial state.

Related

How to troubleshoot oAuth authentication in asp.net core Blazor App

I am trying to set up Strava authentication (which is plain oAuth2) in Asp.Net Core Blazor App.
I am rather new to Blazor & Web dev (more of a backend background), and I don't seem to find out how to troubleshoot the reason why the Authentication does not work.
When I click the oAuth login button on the Login page in the (default) Blazor Server App, I get redirected to the correct oAuth login screen (of Strava in my case), but after I successfully enter the credentials for that App, the login page shows an error Error loading external login information.
While I would obviously appreciate any help or tips that could point out what is wrong in my code, I'm mostly searching for a way to get better error information and troubleshooting capabilities here. Setting a breakpoint in the EventHandler delegates does not show much.
This is the Startup.cs extract where I have configured the authentication setup :
services.AddAuthentication().AddOAuth("Strava",
oAuthOptions =>
{
oAuthOptions.ClientId = "myappid";
oAuthOptions.ClientSecret = "myclientsecret";
oAuthOptions.Scope.Clear();
oAuthOptions.Scope.Add("read");
oAuthOptions.CallbackPath = "/profile";
oAuthOptions.AuthorizationEndpoint = "https://www.strava.com/oauth/authorize";
oAuthOptions.TokenEndpoint = "https://www.strava.com/api/v3/oauth/token";
oAuthOptions.SignInScheme = IdentityConstants.ExternalScheme;
oAuthOptions.Events = new OAuthEvents()
{
OnRemoteFailure = loginFailureHandler =>
{
Console.WriteLine("Remote Error");
Console.WriteLine(loginFailureHandler.Failure.Message);
return Task.FromResult(0);
},
OnAccessDenied = handler =>
{
Console.WriteLine(handler.Response.StatusCode);
return Task.FromResult(0);
}
};
});
An update that made things work for me, so maybe it can help other people.
I performed the following actions, in order to gain more control on the entire authentication process.
I scaffolded two pages, in which I then could debug & step through (and obviously also update and change things). More information was found in this post:
Account.Login, which enables the customization of the actual login page dotnet aspnet-codegenerator identity -dc CotacolApp.Data.ApplicationDbContext --files "Account.Login"
Account.ExternalLogin, which enables the customization of the actual strava page dotnet aspnet-codegenerator identity -dc CotacolApp.Data.ApplicationDbContext --files "Account.ExternalLogin"
I then found out that the var info = await _signInManager.GetExternalLoginInfoAsync(); always resulted in a null value. And that was because I had to set the IdentityScheme to external. ```
And after that, I had to run some custom logic to do the claim mapping. Most of those details were written down in this stackoverflow post by #Morgeh.
Hope this can help people in the future.

REST API Getting 401 UnAuthorized

I am using .NET Core Web API to make call and getting back
401, unauthorized ? I am using a REST API key.
var ApiKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var _Http = new HttpClient();
var response = await _Http.GetAsync($"https://geocode.search.hereapi.com/v1/geocode?q={address},{city},{state},{postalCode},{country}&apikey={ApiKey}");
What am I missing ?
I am getting the key from the following section
UPDATE: this problem has vanished today. It appears to have been a bug on the Here side.
Yesterday: My JS API code, which has been working fine, is throwing 401s today as well, with no changes. I could kill the project and create a new one with a new API key, but I'm not sure that would fix it. I did find that it was "disabled" (due to a billing issue, I think), and I "enabled" it and it still throws 404s.
Did you confirm your email address (by clicking the link in the email they send)?
If you have not confirmed your email address, then the API Key is only valid for 30 minutes.

Firebase signInWithPopup gives auth/popup-blocked when used via built-in browser in mobile device

Problem: When used via 3rd-party app built-in browser (e.g. LINE, Twitter or Facebook messenger), the signInWithPopup returns auth/popup-blocked. The explanation by Firebase docs is:
auth/popup-blocked: Thrown if the popup was blocked by the browser, typically when this operation is triggered outside of a click handler.
Typical sequence triggering this error is: Link of my web app is sent to LINE, Twitter or Facebook messenger. When user uses mobile device and opens that link in those apps, their built-in browser is opened. Calling signInWithPopup then returns the error. The behavior is slightly different in iOS and Android but at least iOS/LINE combination results the error.
I am using Angular and building a web app. The error message is Unable to establish a connection with the popup. It may have been blocked by the browser. which comes from the firebase.js - not my own text.
When used in a normal browser, the signup works just fine.
Any ideas why the built-in browsers and signInWithPopup do not work together?
Firebase authentication should start with some user interaction, such as click on button. This solved the problem for me.
Many in-app embedded browsers block popups. I ran into the issue on instagram. Try using signInWithRedirect instead of signInWithPopup when kicking off the Oauth call.
Firebase documentation on usage of both methods can be found here - https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithPopup
signInWithPopup() is for the browser, however, if you're running iOS or Andriod emulator or device, you need to call signInWithCredential.
signInWithFacebook() {
if (this.platform.is('cordova')) {
return this.fb.login(['email', 'public_profile']).then(res => {
const facebookCredential = firebase.auth.FacebookAuthProvider.credential(res.authResponse.accessToken);
return firebase.auth().signInWithCredential(facebookCredential);
})
}
else {
return this.afAuth.auth
.signInWithPopup(new firebase.auth.FacebookAuthProvider())
.then(res => console.log(res));
}
}
If you're using Ionic + Firebase, you can find more info here
I have the same issue, with my web app on facebook ads campaign. I change my code from popup to redirect.
googleAuth() {
firebase
.auth()
.getRedirectResult()
.then(function(result) {
this.showLoading = true;
if (result.credential) {
var token = result.credential.accessToken;
console.log(token);
}
var user = result.user;
console.log(user);
});
this.showLoading = true;
const provider = new firebase.auth.GoogleAuthProvider();
provider.addScope("profile");
provider.addScope("email");
firebase.auth().signInWithRedirect(provider);
}
}
The problem now is save my utms from campaigns, because with redirect you lose them.

Firebase authWithOAuthRedirect() woes

I'm trying to update my angularjs app to support Firebase 1.1 (I was stick with Firebase 1.0.x).
It deprecates firebasesimplelogin, including authentication inside Firebase core.
I have been able to successfully implement authentication using
authWithOAuthPopup("<provider>", function(error, authData) { ... });
It accepts a callback, which is passed authentication data in authData.
On the contrary, I can't undersand how to use
authWithOAuthRedirect("<provider>", function(error) { ... });
Firebase Authentication docs page is very concise... :-(. This is all what is said:
Alternatively [instead of authWithOAuthPopup], you may prompt the user to login with a full browser redirect, and Firebase will automatically restore the session when you return to the originating page
How do I get authData, when Firebase - after redirection - returns to my page?
The authData is available by registering a listener directly on the ref (so before calling authWithOAuthRedirect).
ref.onAuth(function(authData) {
...
}
ref.authWithOAuthRedirect("google", function(error) { ... });
See https://www.firebase.com/docs/web/guide/user-auth.html#section-monitoring-authentication
I think I'm running into the same issue as you. I'm trying to do Facebook authentication.
First, I'd like to clarify the reproduction steps for my issue.
My app is loaded on the client.
User clicks login with Facebook.
ref.authWithOAuthRedirect('facebook', ...) is called.
Client is redirected to Facebook and Facebook redirects client back to Firebase app
Despite successful authentication with Facebook, the callback passed to onAuth() is invoked (only once) with authData === null.
The callback passed to onAuth() is not invoked a second time with correct authData.
However, reloading the app causes the callback passed to onAuth to be invoked with correct authData. The reasons for this are not known to me but I suspect race condition.
Here's my workaround.
Before calling ref.authWithOAuthRedirect('facebook', ...) set yourself a flag in sessionStorage.
sessionStorage.reload = true;
ref.authWithOAuthRedirect('facebook', ...)
When the client is redirected to your app back from Facebook, you should be able to check for this flag and reload the page if necessary.
if (sessionStorage.reload) {
delete sessionStorage.reload;
setTimeout(function() {
location.reload();
}, 1000)
}
setTimeout(function() { ... }, 1000) helps fight the assumed race condition. I found 500 ms is insufficient time for the race condition to be resolved.
And one small gotcha: if you reload the page too soon, then authData remains null no matter how many times you reload the page.

The Access Token is Valid but We get OAuthException: An active access token error

We've been working on an application for about 2 months, and everything was going perfectly.
we were using PHP SDK and offline mode in permissions for login
But since some days ago after recent changes in Facebook api and removing offline mode we started facing the problem of "Uncaught OAuthException: An active access token must be used to query information about the current user."
The main problem is that it does happen after a while working in our app (about 10 mins) but at the same time when we check the validity of the token via this link
we see that the token is still valid on the other hand the cookie does still exist and it doesn't expire but we get this error :
"Uncaught OAuthException: An active access token must be used to query information about the current user"
I've already visited this link
and I downloaded the latest version but it didn't help could anyone help us please where might be making mistake?
Thanks for responses, I think same as yacon
it seems there's a bug when accessing facebook->api(/me) at the moment we are handling
some parts of the app with javascript which is a real headache to use javascript sdk
and PhP sdk alongside with each other
You can solve this simply store accesstoken to session variable after getLoginUrl
$facebook->getLoginUrl(...)
then whenever you initialize facebook
$facebook = new Facebook(array(
'appId' => Yii::app()->params['facebook_appId'],
'secret' => Yii::app()->params['facebook_appSecret'],
));
get the accesstoken from session and set it using setAccessToken
$facebook->setAccessToken(Yii::app()->session['access_token']);
I handle this situation in this way
1.i get the access token for 1 hour validity
2.extend the token to 60 days validity
3.save that token to session and use it for all project queries.
try{
$facebook_uid = $facebook->getUser();
$facebook->setExtendedAccessToken();
$accessToken = $facebook->getAccessToken();
$fbuser = $facebook->api('/me');
$session['api_me'] = $fbuser;
$session['tokenValue'] = $accessToken;
}catch (Exception $e) {
facebook_uid =null;
}
I think there is a bug in the api. When I use $facebook->api('/'.$facebook_uid) instead of ->api('/me') it works.

Resources