Unable to connect to Firebase Emulator with iOS device - ios

I am trying to connect with an iOS device to the Firebase Auth and RealTime Database Emulator.
The thing is, I can connect and use emulator through Firebase Admin using NodeJS on local machine (trough http://localhost:9000?ns=my-project).
Also I am able to connect with an iOS device to the remote Firebase server... But locally it doesn't work. It throws bunch of random errors, like this (when I try to complete registration/authentication):
Error Domain=NSURLErrorDomain Code=-1004 "Could not connect to the
server." NSLocalizedDescription=Could not connect to the server.,
NSErrorFailingURLStringKey=http://192.168.1.3:9099/www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=myKeyGoesHere
and
Optional(Error Domain=com.firebase.core Code=1 "Unable to get latest
value for query FQuerySpec (path: /news, params: { }), client offline
with no active listeners and no matching disk cache entries"
Here is firebase.json:
{
"database": {
"rules": "database.rules.json"
},
"emulators": {
"auth": {
"port": 9099
},
"database": {
"port": 9000
},
"ui": {
"enabled": true
}
}
}
I changed rules just in case:
{
"rules": {
".read": true,
".write": true
}
}
but its not that.
and here is how I try to connect to database in my iOS application(my FirebaseManager class):
init(){
Auth.auth().useEmulator(withHost:"192.168.1.3", port:9099)
}
private lazy var newsNodeRef:DatabaseReference? = {
guard let urlString = getBaseURL() else {return nil}
let node = LocalConstants.kNewsRef // this has value of 'news'
return Database.database(url: urlString).reference(withPath: node)
}()
private func getBaseURL()->String?{
let environment = Environment()
guard let connectionProtocol = environment.configuration(PlistKey.firebaseConnectionProtocol), let baseURL = environment.configuration(PlistKey.firebaseDatabaseURL) else {return nil}
let urlString = "\(connectionProtocol)://\(baseURL)"
return urlString // this produces something like 'http://192.168.1.3:9000?ns=my-project' (its fetched from Configuration Settings file based on selected environment)
}
the thing is, the exact same setup works on remote server, if I just change the environment(which automatically changes base url).
I have also allowed insecure http loads in info.plist, just to be sure if it is not that, but still doesn't work.
This is what I get in console when I run emulators:
What is the problem here?

I replied a little late 😊.
I saw the solution you found. It didn't work for me but I'm sure it has worked for a lot of people.
I found a solution too.
Actually, I couldn't see a problem for iOS 15. My problem was that it didn't work on iOS 14 and earlier.
Solution;
First, you need the MacBook's IP address.
To find the IP address;
You can access it right under System preferences -> Network -> Status.
Then we need to make some changes in the firebase.json file.
Adding “host” : “IP” for each part.
Overwrite the “host” part with the “port” part.
"emulators": {
"auth": {
"host": "192.168.1.11”,
"port": 9100
},
"functions": {
"host": "192.168.1.11”,
"port": 5002
},
"firestore": {
"host": "192.168.1.11”,
"port": 8081
},
"database": {
"host": "192.168.1.11",
"port": 9001
},
"storage": {
"host": "192.168.1.11",
"port": 9200
},
"ui": {
"enabled": true
}
Then we need to add in swift codes.
We need to write the IP address in the host part.
More precisely, we will replace the parts that say localhost with the IP address.
let settings = Firestore.firestore().settings
settings.host = "192.168.1.11:8081"
settings.isPersistenceEnabled = false
settings.isSSLEnabled = false
Firestore.firestore().settings = settings
Storage.storage().useEmulator(withHost:"192.168.1.11", port:9200)
Auth.auth().useEmulator(withHost:"192.168.1.11", port:9100)
let db = Database.database(url:"http://192.168.1.11:9001?ns=firebaseappname")
Functions.functions().useFunctionsEmulator(origin: "http://192.168.1.11:5002")
I think this solution will work in JS, android and other languages.
I would appreciate it if you tried this solution and let me know if it works.
It worked for me.

I actually solved it. The solution/problem, I don't even know how to declare it, was with Local Network Access prompt & permissions and its buggy behaviour (as well how I was trying to access my Mac by ip).
At first I didn't even see a prompt shows every time, but I guess it was related to a wrong setup of a port, host etc.
But when I correctly set local computer's ip and reverted firebase.json to it's default settings (which is what worked for me), the prompt started to jump out every time.
The thing is, prompt's behaviour seems broken, because instead of jumping before you try to access devices in a local network, it pops out after that action is made. Quite fast, but still after Auth system responded, which doesn't make sense.
Here, it can be confusing, cause error that is returned from a Firebase Auth system in the case when you didn't allow Local Network Access usage, doesn't really tell you much about real cause. See my ( original question) above to see the errors.
After that terrible flow, I allowed access trough the prompt. Once I did that, on every next 'api' call towards Emulator was successful. Worked like a charm.
The real problem here is Local Network Access prompt. Cause we don't have at all control over it, so we can't that easily trigger it, or easily get info what user have selected/chosen at the moment / or before. It's triggered by the system in certain conditions.
Luckily this is just for development :) but I hope it will be fixed/improved soon, cause it should.
I found a lot about this topic and its considered as a bug Local Network Access Prompt problems on Dev portal:

I was also faced the same problem while using the firebase auth in iOS simulator
then i change my code little bit
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
if (Platform.isAndroid) {
await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
}
runApp(const MyApp());
}
I have made a check for only android and it works for me
Inside this method you can see it only works for android.

Related

connect from web to iot core using a custom authorizer

I'm trying to use a custom authorizer to authenticate a web client.
I have succesfully created a dedicated lambda and a custom authorizer. If I launch aws iot describe-authorizer --authorizer-name <authorizer-name> I can see
{
"authorizerDescription": {
"authorizerName": "<authorizer-name>",
"authorizerArn": "...",
"authorizerFunctionArn": "...",
"tokenKeyName": "<token-key-name>",
"tokenSigningPublicKeys": {
"<public-key-name>": "-----BEGIN PUBLIC KEY-----\n<public-key-content>\n-----END PUBLIC KEY-----"
},
"status": "ACTIVE",
"creationDate": "...",
"lastModifiedDate": "...",
"signingDisabled": false,
"enableCachingForHttp": false
}
}
Moreover I can test it succesfully:
$ aws iot test-invoke-authorizer --authorizer-name '<authorizer-name>' --token '<public-key-name>' --token-signature '<private-key-content>'
{
"isAuthenticated": true,
"principalId": "...",
"policyDocuments": [ "..." ],
"refreshAfterInSeconds": 600,
"disconnectAfterInSeconds": 3600
}
$
But I cannot connect using the browser.
I'm using aws-iot-device-sdk and according the SDK documentation I should set customAuthHeaders and/or customAuthQueryString (my understanding is that the latter should be used in web environment due to a limitation of the browsers) with the headers / queryparams X-Amz-CustomAuthorizer-Name, X-Amz-CustomAuthorizer-Signature and TestAuthorizerToken but no matter what combination I set for these values the iot endpoint always close the connection (I see a 1000 / 1005 code for the closed connection)
What I've written so far is
const CUSTOM_AUTHORIZER_NAME = '<authorizer-name>';
const CUSTOM_AUTHORIZER_SIGNATURE = '<private-key-content>';
const TOKEN_KEY_NAME = 'TestAuthorizerToken';
const TEST_AUTHORIZER_TOKEN = '<public-key-name>';
function f(k: string, v?: string, p: string = '&'): string {
if (!v)
return '';
return `${p}${encodeURIComponent(k)}=${encodeURIComponent(v)}`;
}
const client = new device({
region: '...',
clientId: '...',
protocol: 'wss-custom-auth' as any,
host: '...',
debug: true,
// customAuthHeaders: {
// 'X-Amz-CustomAuthorizer-Name': CUSTOM_AUTHORIZER_NAME,
// 'X-Amz-CustomAuthorizer-Signature': CUSTOM_AUTHORIZER_SIGNATURE,
// [TOKEN_KEY_NAME]: TEST_AUTHORIZER_TOKEN
// },
customAuthQueryString: `${f('X-Amz-CustomAuthorizer-Name', CUSTOM_AUTHORIZER_NAME, '?')}${f('X-Amz-CustomAuthorizer-Signature', CUSTOM_AUTHORIZER_SIGNATURE)}${f(TOKEN_KEY_NAME, TEST_AUTHORIZER_TOKEN)}`,
} as any);
As you can see I started having also doubts about the headers names!
After running my code I see that the client tries to do a GET to the host with the querystring that I wrote.
I also see that IoT core responds with a 101 Switching Protocols, and then that my client send the CONNECT command to IoT via websocket and then another packet from my browser to the backend system.
Then the connection is closed by IoT.
Looking at cloudwatch I cannot see any interaction with the lambda, it's like the request is blocked.
my doubts are:
first of all, is it possible to connect via mqtt+wss using only a custom auth, without cognito/certificates? keep in mind that I am able to use a cognito identity pool without errors, but I need to remove it.
is it correct that I just need to set up the customAuthQueryString parameter? my understanding is that this should be used on the web.
what are the values I should set up for the various headers/queryparams? X-Amz-CustomAuthorizer-Name is self explanatory, but I'm not sure about X-Amz-CustomAuthorizer-Signature (it's correct to fill it with the content of my private key?). moreover I'm not sure about the TestAuthorizerToken. Is it the correct key to set up?
I've also tried to run the custom_authorizer_connect of the sdk v2 but it's still not working, and I run out of ideas.
turns out the problem was in the permissions set on the backend systems.

ApolloServer: "Could not connect to websocket endpoint ws://localhost:4000/subscriptions. Please check if the endpoint url is correct."

I can't implement any subscriptions because it suddenly disconnects from it when I try to listen to some endpoint with GraphQL Playground:
{"error": "Could not connect to websocket endpoint wss://localhost:4000/graphql. Please check if the endpoint url is correct."}
I'm using ApolloServer alone, no express or anything else. It is containerized with Docker using node14 image, the port is properly fowarded, queries and mutations works properly.
This is the configuration snippet:
const server = new ApolloServer({
typeDefs: mergedTypeDefs,
resolvers: mergedResolvers,
playground: {
subscriptionEndpoint: 'ws://localhost:4000/graphql'
},
subscriptions: {
keepAlive: 9000,
onConnect: (connParams, webSocket, context) => {
console.log('CLIENT CONNECTED');
},
onDisconnect: (webSocket, context) => {
console.log('CLIENT DISCONNECTED')
}
},
context: {
models
}
});
I tried everything, from using 'wss' instead of 'ws' to change the path. I checked for typos and didn't find one. What bothers me is that the paths are the same so It should at least try to notify me by the onConnect or onDisconnect but it doesn't.
This is the message through Chrome's dev tools:
WebSocket connection to 'wss://localhost:4000/graphql' failed: WebSocket is closed before the connection is established.
I tested subscriptions with a 'tutorial' project outside the container and it works fine.
Sometimes, the only function of subscriptions that works is onDisconnect but after 2-5 seconds after receiving the error message on PlayGround, and Still it doesn't gives me any insight on the problem.
Any help or suggestion is appreciated.
wss will definitely not work locally without certificate, so use ws as a protocol.
If it works without Docker, then everything should be fine code-wise.
You should also make sure that you've mapped ports correctly, i.e. exposed port 4000 https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port--p---expose

How fix "Invalid host header" error in vue 3 project?

I'm tring to deploy a simple test app on cloud with digital ocean.
I created a new app with the vue cli (VUE3).
After i dockerized the app and exposed to 8080.
I configured the nginx so that it route traffic from port :80 to :8080 on the container.
Everything is ok, but when i try to visit the page i got this error "Invalid host header".
I searched on google and everybody suggest to create a vue.config.js file with this code:
module.exports = {
devServer: {
disableHostCheck: true
} }
I tried this solution but nothing is changed. How can i fix this error?
I also read that this kind of solution create vulnerabilities, is there a way to fix without this solution?
Thank you in advance for the response
In your vue.config.js file you can try this settings
const { defineConfig } = require('#vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
allowedHosts: "all"
}
})
Found the solution!
The mentioned solutions above does not work for me.
I am not sure when the property allowedHosts was changed.
currently, we supposed to provide an array to the allowedHosts property.
devServer: {
allowedHosts: [
'yourdomain.com'
]
}
Just look for the file vue.config.js, then replace: yourdomain.com with your own personal domain.
An alternative to Oren Hahiashvili's answer when you don't know ahead of time what hosts will be accessing the devServer (e.g., when testing on multiple environments) is to set devServer.diableHostCheck in vue.config.js. For example,
module.exports = {
devServer: {
disableHostCheck: true
}
};
Note this is less secure than Oren Hahiashvili's answer, so only use this when you don't know the hosts, and you still need to serve using devServer.

SendGrid not working in Azure App Service

I'm creating a MVC Core app and deploying it to an Azure App Service. I'm trying to send emails using SendGrid from the application which seems to be working fine in my local environment but does not work in production. I'm using free subscriptions for anything Azure.
I've followed this pretty much to the tee.
This type of question has popped up on stack overflow and github (here and here, etc), but after going through about 50 such posts nothing seems to be working for me. Reading through the documentation in SendGrid doesn't help a lot either because all the examples provided looks like my own code. I don't get any exceptions, and like I mentioned it works just fine locally.
Please help
Code
string sendGridApiKey = _configuration["SENDGRID_API_KEY"];
var client = new SendGridClient(sendGridApiKey);
var msg = new SendGridMessage();
msg.SetFrom(new EmailAddress(email: "management#enr.com",
name: "ENR Management"));
msg.AddTo(new EmailAddress(email: user.Email, name: user.FriendlyName));
msg.SetSubject("Reset Password");
msg.AddContent(MimeType.Html, $"Please reset your password by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'> clicking here </a>.");
msg.AddContent(MimeType.Text, "Please reset your password by clicking the link");
var response = await client.SendEmailAsync(msg).ConfigureAwait(false);
Being called by
_emailService.SendResetPasswordEmail(
user: user,
callbackUrl: callbackUrl).Wait();
appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "XXX",
"ENRModelsDB": "XXX"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"SENDGRID_API_KEY": "SG.XXX",
"AllowedHosts": "*"
}
I also have the same key/value in my App Service in Azure under Configuration -> Application setting for what it's worth.
Could it be that your App Service has the configuration setup with different value?
Another suggestion to you is you to debug your app running in the App Service to see what exactly is happening.
Introduction to Remote Debugging on Azure Web Sites
*it is old but it will give you the idea.
I finally found the issue and I feel so stupid.
I only send 1 email from my app, the password reset email. On my live environment, it would fail at this step in ForgotPassword.cshtml.cs (the scaffolded page)
if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
{
// Don't reveal that the user does not exist or is not confirmed
return RedirectToPage("./ForgotPasswordConfirmation");
}
because when I seeded the user I did not set email confirmed to be true.
Could not have done it without the remote debug suggestion. It never even got to the part where it is supposed to send the email, and no errors reports because there was none.
Found some newer articles (here and here) to help with the remote debugging which came with its own rabbit holes.
Thanx for the suggestion #KodiaMx

Ignore Checks Based on Dependencies on Uchiwa using Sensu

I'm currently using sensu and Uchiwa in an attempt to get rid of Zabbix, the problem is some checks persist even though they're dependent on other check.
For example:
I have a check that checks if the vpn process is active:
"vpn-process": {
"command": "check-process.rb -f /var/run/openvpn/client.pid",
"subscribers": [
"uni"
],
"interval": 60,
"dependencies": [
"http-url1",
"http-url2",
"http-url3"
]
},
And I also have a check for http response, but this shouldn't work if the vpn is down.
"http-url1": {
"command": "python /etc/sensu/plugins/check-http.py https://url",
"subscribers": [
"uni"
],
"interval": 60
},
Still, Uchiwa warns about the VPN check and the HTTP checks.
Uchiwa showing VPN and HTTP checks
I read about the dependency check filters, but as far as I could understand, it only works for handlers and Uchiwa is not a handler?
It seems you can't use Uchiwa as a handler (I checked with the maintainers), I had to write my own in python to call the API everytime the VPN is down and silence the checks I don't want to be shown in the dashboard. This way I created my own dependency.
Uchiwa displays the current state of events in the system -- it is a passive view of checks/events, whereas handlers are active. The HTTP check will execute on-schedule even if VPN is down, and it will be considered CRITICAL regardless of whether you have a dependency filter.
The only way to have the HTTP check not result in a CRITICAL value if VPN is down is if you're somehow able to check for that case within the HTTP check and return a different value instead of CRITICAL. However, VPN being down might look very similar to other network-related issues, so it's probably best to avoid this scenario.
Maybe try making the VPN and HTTP checks into a check aggregate?

Resources