Flutter setup MQTT with .p12 file - flutter

I am currently rebuilding an App using Flutter, in the old iOS and Android app, both would fetch the .p12 file from backend to setup the MQTT socket connection.
But the Flutter package I'm trying to use mqtt_client seems to require useCertificateChain, usePrivateKey and setClientAuthorities
three files like this:
SecurityContext context = new SecurityContext()
..useCertificateChain('path/to/my_cert.pem')
..usePrivateKey('path/to/my_key.pem', password: 'key_password')
..setClientAuthorities('path/to/client.crt', password: 'password');
client.secure = true;
client.securityContext = context;
Code from: https://emqx.medium.com/using-mqtt-in-the-flutter-project-6a5d90179c8b
I keep studying the mqtt_client package, but the examples and documents they provide don't seem to have the option to use .p12 file to establish socket connection.
If I have to download the .p12 file to mobile then extract and resave three files again, it would not make sense to use Flutter.
Is there any way I can use .p12 file in the mqtt_client package, or is there any other option or package can achieve this?
Thanks for helping!

I figured it out that I could insert the p12 file using client.connect, but the package document never said anything about this. This suppose to be a very common way to build MQTT connection.
_client = MqttServerClient.withPort(_host!, _identifier, _port);
_client?.keepAlivePeriod = 60;
_client?.logging(on: true);
_client?.setProtocolV311();
_client?.secure = true;
final securityContext = SecurityContext.defaultContext;
securityContext.setClientAuthorities('$_certPath/ios.p12', password: '');
securityContext.useCertificateChain('$_certPath/ios.p12', password: '');
securityContext.usePrivateKey('$_certPath/ios.p12', password: '');
_client?.securityContext = securityContext;

Related

Hosting a web server in a local enviroment using only Flutter

Is it possible to host a Flutter web app on a local environment using a Flutter desktop-based app?
The google-search for a solution like this can be difficult, since it involves many keywords that lead to similar situations (online hosting when you need a local solution, command-line only solution, and so on).
After some digging, I ended up using the shelf package to deploy my own Flutter web app on a local network. I developed this for Windows only, so I can't guarantee it will work on other platforms.
First thing to do is obviously adding the shelf package in your pubspec.yaml: after that, this is how my main method looks like
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf_router/shelf_router.dart' as shelf_router;
[...]
void main() async{
[...]
var secureContext = SecurityContext();
try {
//privKey and cert are the String names of the two files for the SSL connection,
//placed in the root directory of the flutter project or along with the .exe file (when released)
secureContext.usePrivateKey(privKey);
secureContext.useCertificateChain(cert);
} catch (error) {
logger.e("Error on init SecurityContext");
}
try {
//this is the handler that deploys the files contained in 'webAppFolder': I just simply pasted the result of
//the flutter webapp building inside (the index.html file is the default one for flutter web)
//and put the folder in the root of the flutter project (or, again, in the same folder with the .exe file when released)
final _staticHandler = createStaticHandler("webAppFolder", defaultDocument: 'index.html');
//this I kept just for a reminder on how to deploy a static page, if needed
final _router = shelf_router.Router()
..get(
'/time',
(request) => shelf.Response.ok(DateTime.now().toUtc().toIso8601String()),
);
final cascade = shelf.Cascade()
.add(_staticHandler)
.add(_router);
try {
var server = await shelf_io.serve(
cascade.handler,
InternetAddress.anyIPv4,
mainPort, //this is the number of the port on which the webapp is deployed (I load this from a .ini file beforehand
securityContext: secureContext,
);
// Enable content compression
server.autoCompress = true;
logger.i("Serving at https://${server.address.host}:${server.port}");
} catch (err) {
logger.e("Error while serving");
logger.e(err.toString());
}
} catch (err) {
logger.e("Error while creating handler");
logger.e(err.toString());
}
runApp(MaterialApp(
[...]
This is the part related to the deploy of a web app: since the flutter desktop app already provides a GUI, I used that to add some maintenance and testing utilities to check if everything is working fine.
For more details regarding shelf, refer to their API on their pub.dev page.

Does build pipeline requires internate connection to run

I am using Onprimise AzureDevOps. I am having intranet within the server but no access to internet.
Does the Use Nugget and Nugget installer requires internet to get it success.
If you look here you will find this code:
async function getLatestMatchVersionInfo(versionSpec: string): Promise<INuGetVersionInfo> {
taskLib.debug('Querying versions list');
let versionsUrl = 'https://dist.nuget.org/tools.json';
let proxyRequestOptions = {
proxy: taskLib.getHttpProxyConfiguration(versionsUrl)
};
let rest: restm.RestClient = new restm.RestClient('vsts-tasks/NuGetToolInstaller', undefined, undefined, proxyRequestOptions);
let nugetVersions: INuGetVersionInfo[] = (await rest.get<INuGetVersionInfo[]>(versionsUrl, GetRestClientOptions())).result;
// x.stage is the string representation of the enum, NuGetReleaseStage.Value = number, NuGetReleaseStage[NuGetReleaseStage.Value] = string, NuGetReleaseStage[x.stage] = number
let releasedVersions: INuGetVersionInfo[] = nugetVersions.filter(x => x.stage.toString() !== NuGetReleaseStage[NuGetReleaseStage.EarlyAccessPreview]);
let versionStringsFromDist: string[] = releasedVersions.map(x => x.version);
let version: string = toolLib.evaluateVersions(versionStringsFromDist, versionSpec);
if (!version)
{
taskLib.error(taskLib.loc("Error_NoVersionWasFoundWhichMatches", versionSpec));
taskLib.error(taskLib.loc("Info_AvailableVersions", releasedVersions.map(x => x.version).join("; ")));
throw new Error(taskLib.loc("Error_NuGetToolInstallerFailer", NUGET_TOOL_NAME));
}
return releasedVersions.find(x => x.version === version);
}
And it basically looks for nuget version if it will not find it on local machine. I assume that all this REST calls will not work without internet. So if you do not want to provide access to internet you should use only those versions installed on agents.
Agree with Krzysztof Madej, I think it is feasible to run build pipeline without internet connection. From the description of NuGet tool installer task we can know :
Acquires a specific version of NuGet from the internet or the tools
cache and adds it to the PATH.
So you need to make sure that the nuget version you need is installed on the local machine.
If you don't use upstream packages from the feed in your DevOps server, then your DevOps server machine could just in intranet network.
However, your build agent machine requires internet access, if you to do something that requires to access internet, such as Use Nuget task.

Issues with Flutter and Phoenix Channels

We're having some issues with our Flutter App and Pheonix Web Sockets. We know that the Backend is working properly, since the JavaScript client is fully functional. But with the Flutter app we can't connect to the server.
final socket = PhoenixSocket("ws://###.##/socket");
connectSocket() async {
await widget.socket.connect();
_channel = widget.socket.channel("test:lobby")
_channel.on("say", _say);
_channel.join();
}
One of the errors were gettig:
I/flutter ( 4227): WebSocket connection to ws://###.##:8080/socket?vsn=2.0.0 failed!: WebSocketException: Connection to 'http://###.##:8080/socket?vsn=2.0.0#' was not upgraded to websocket
On the client side we're using Phoenix Wings, the port and URL are correct.
Why does this keep happening?
Are there any other libraries for Flutter with Phoenix Interactions?
Is there a better documentation for phoenix_wings or for any other packages?
I had it working as
final socket = PhoenixSocket("ws://####.###/socket/websocket");
hth.

Unable to download embedded MongoDB, behind proxy, using automatic configuration script

I have a Spring Boot project, built using Maven, where I intend to use embedded mongo db. I am using Eclipse on Windows 7.
I am behind a proxy that uses automatic configuration script, as I have observed in the Connection tab of Internet Options.
I am getting the following exception when I try to run the application.
java.io.IOException: Could not open inputStream for https://downloads.mongodb.org/win32/mongodb-win32-i386-3.2.2.zip
at de.flapdoodle.embed.process.store.Downloader.downloadInputStream(Downloader.java:131) ~[de.flapdoodle.embed.process-2.0.1.jar:na]
at de.flapdoodle.embed.process.store.Downloader.download(Downloader.java:69) ~[de.flapdoodle.embed.process-2.0.1.jar:na]
....
MongoDB gets downloaded just fine, when I hit the following URL in my web browser:
https://downloads.mongodb.org/win32/mongodb-win32-i386-3.2.2.zip
This leads me to believe that probably I'm missing some configuration in my Eclipse or may be the maven project itself.
Please help me to find the right configuration.
What worked for me on a windows machine:
Download the zip file (https://downloads.mongodb.org/win32/mongodb-win32-i386-3.2.2.zip)
manually and put it (not unpack) into this folder:
C:\Users\<Username>\.embedmongo\win32\
Indeed the problem is about your proxy (a corporate one I guess).
If the proxy do not require authentication, you can solve your problem easily just by adding the appropriate -Dhttp.proxyHost=... and -Dhttp.proxyPort=... (or/and the same with "https.[...]") as JVM arguments in your eclipse junit Runner, as suggested here : https://github.com/learning-spring-boot/learning-spring-boot-2nd-edition-code/issues/2
One solution to your problem is to do the following.
Download MongoDB and place it on a ftp server which is inside your corporate network (for which you would not need proxy).
Then write a configuration in your project like this
#Bean
#ConditionalOnProperty("mongo.proxy")
public IRuntimeConfig embeddedMongoRuntimeConfig() {
final Command command = Command.MongoD;
final IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder()
.defaults(command)
.artifactStore(new ExtractedArtifactStoreBuilder()
.defaults(command)
.download(new DownloadConfigBuilder()
.defaultsForCommand(command)
.downloadPath("your-ftp-path")
.build())
.build())
.build();
return runtimeConfig;
}
With the property mongo.proxy you can control whether Spring Boot downloads MongoDB from your ftp server or from outside. If it is set to true then it downloads from the ftp server. If not then it tries to download from the internet.
The easiest way seems to me to customize the default configuration:
#Bean
DownloadConfigBuilderCustomizer mongoProxyCustomizer() {
return configBuilder -> {
configBuilder.proxyFactory(new HttpProxyFactory(host, port));
};
}
Got the same issue (with Spring Boot 2.6.1 the spring.mongodb.embedded.version property is mandatory).
To configure the proxy, I've added the configuration bean by myself:
#Value("${spring.mongodb.embedded.proxy.domain}")
private String proxyDomain;
#Value("${spring.mongodb.embedded.proxy.port}")
private Integer proxyPort;
#Bean
RuntimeConfig embeddedMongoRuntimeConfig(ObjectProvider<DownloadConfigBuilderCustomizer> downloadConfigBuilderCustomizers) {
Logger logger = LoggerFactory.getLogger(this.getClass().getPackage().getName() + ".EmbeddedMongo");
ProcessOutput processOutput = new ProcessOutput(Processors.logTo(logger, Slf4jLevel.INFO), Processors.logTo(logger, Slf4jLevel.ERROR), Processors.named("[console>]", Processors.logTo(logger, Slf4jLevel.DEBUG)));
return Defaults.runtimeConfigFor(Command.MongoD, logger).processOutput(processOutput).artifactStore(this.getArtifactStore(logger, downloadConfigBuilderCustomizers.orderedStream())).isDaemonProcess(false).build();
}
private ExtractedArtifactStore getArtifactStore(Logger logger, Stream<DownloadConfigBuilderCustomizer> downloadConfigBuilderCustomizers) {
de.flapdoodle.embed.process.config.store.ImmutableDownloadConfig.Builder downloadConfigBuilder = Defaults.downloadConfigFor(Command.MongoD);
downloadConfigBuilder.progressListener(new Slf4jProgressListener(logger));
downloadConfigBuilderCustomizers.forEach((customizer) -> {
customizer.customize(downloadConfigBuilder);
});
DownloadConfig downloadConfig = downloadConfigBuilder
.proxyFactory(new HttpProxyFactory(proxyDomain, proxyPort)) // <--- HERE
.build();
return Defaults.extractedArtifactStoreFor(Command.MongoD).withDownloadConfig(downloadConfig);
}
In my case, I had to add the HTTPS corporate proxy to Intellij Run Configuration.
Https because it was trying to download:
https://downloads.mongodb.org/win32/mongodb-win32-x86_64-4.0.2.zip
application.properties:
spring.data.mongodb.database=test
spring.data.mongodb.port=27017
spring.mongodb.embedded.version=4.0.2
Please keep in mind this is a (DEV) setup.

Replacing files with WebClient

I'm testing the following code for replacing files on a https site via C# code, but it has no effect and
generates no exception. (Downloading files works fine).
try
{
using (System.Net.WebClient client = new System.Net.WebClient())
{
client.Credentials = new System.Net.NetworkCredential(username, password);
//www.testsite.com is just an example - testing is done with an actual site:
client.UploadFile("https://www.testsite.com/testfolder/testpage.html", #"C:\testuploads\testpage.html");
//same effect using the 3-param version - no effect + no exception:
//client.UploadFile("https://www.testsite.com/testfolder/testpage.html", System.Net.WebRequestMethods.Ftp.UploadFile, #"C:\testuploads\testpage.html");
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString());
}
This post mentioned the need for server-side code:
WebClient UploadFile Does Not Work
But how does an FTP client tool such as FileZilla Client accomplish this? Surely it doesn't install server-side
code. (FileZilla Client replaces the file without issue).