MQTTnet client can't connect server certificate - c#

I'm using MQTTnet library to connect to my MQTT server that needs a server certificate. The client one is not needed.
I already installed the certificate inside my PC as i found in other post and created the .pfx file to create the certificate but the program doesn't give me any error..it simply doesn't connect to the topic.
This is my example code
//Create a new MQTT client
var factory = new MqttFactory();
var mqttClient = factory.CreateMqttClient();
var caCert = new X509Certificate(#"C:\caserverroot.pfx", "mypsw");
var url = "mymqtt.com";
var username = "user";
var psw = "user";
var port = 8885;
var options = new MqttClientOptionsBuilder()
.WithClientId(Guid.NewGuid().ToString())
.WithTcpServer(url, port)
.WithCredentials(username, psw)
.WithTls(new MqttClientOptionsBuilderTlsParameters()
{
AllowUntrustedCertificates = true,
UseTls = true,
Certificates = new List<byte[]> { new X509Certificate2(caCert).Export(X509ContentType.Cert) },
CertificateValidationCallback = delegate { return true; },
IgnoreCertificateChainErrors = false,
IgnoreCertificateRevocationErrors = false
})
.WithCleanSession()
.WithProtocolVersion(MQTTnet.Serializer.MqttProtocolVersion.V311)
.Build();
// Connecting
var result = await mqttClient.ConnectAsync(options);
// Subscribe to a topic
mqttClient.Connected += async (s, e) =>
{
Console.WriteLine("### CONNECTED WITH SERVER ###");
await mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("/mytopic").Build());
Console.WriteLine("### SUBSCRIBED ###");
};
With all the orther events that i found here: https://github.com/chkr1011/MQTTnet/wiki/Client
Any of you had experience about this library? How to debug it and find the error?
Thanks

So, I don't know why i was wrong but using the ManagedMqttClient saved my situation.
This is the code that works like a charm
//Create a new MQTT client
var mqttClient = new MqttFactory().CreateManagedMqttClient();
var caCert = new X509Certificate(#"C:\cert.pfx", "psw");
var url = "myurl.com";
var username = "user";
var psw = "user";
var port = 8885;
var options = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(30))
.WithClientOptions(new MqttClientOptionsBuilder()
.WithClientId(Guid.NewGuid().ToString())
.WithTcpServer(url, port)
.WithCredentials(username, psw)
.WithTls(new MqttClientOptionsBuilderTlsParameters()
{
AllowUntrustedCertificates = false,
UseTls = true,
Certificates = new List<byte[]> { new X509Certificate2(caCert).Export(X509ContentType.Cert) },
CertificateValidationCallback = delegate { return true; },
IgnoreCertificateChainErrors = false,
IgnoreCertificateRevocationErrors = false
})
.WithCleanSession()
.WithProtocolVersion(MQTTnet.Serializer.MqttProtocolVersion.V311)
.Build())
.Build();
// Connecting
await mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("$share:mygroup:/mytopic").Build());
await mqttClient.StartAsync(options);

Related

How to dynamically Configure different "SubscriptionProperties" for Azure ServiceSub Subscription in C#

I'm trying to configure Azure ServiceBus Topic Subscription dynamically(using C#) with all of its properties which we can set up using Azure Portal.
I have tried the below code, but it's giving me an "object reference error" for SubscriptionProperties while setting up its values.
static SubscriptionProperties subscriptionProperties;
static async Task Main(string[] args)
{
adminClient = new ServiceBusAdministrationClient(connectionString);
client = new ServiceBusClient(connectionString);
subscriptionProperties.AutoDeleteOnIdle = TimeSpan.FromDays(14);
subscriptionProperties.DefaultMessageTimeToLive = TimeSpan.FromDays(14);
subscriptionProperties.TopicName = topicName;
subscriptionProperties.SubscriptionName = subscriptionName;
subscriptionProperties.MaxDeliveryCount = 3;
subscriptionProperties.LockDuration = TimeSpan.FromSeconds(5.00);
subscriptionProperties.DeadLetteringOnMessageExpiration = true;
subscriptionProperties.EnableDeadLetteringOnFilterEvaluationExceptions = true;
Console.WriteLine($"Creating the subscription {subscriptionName} with a correlation filter");
if (!await adminClient.SubscriptionExistsAsync(topicName, subscriptionName))
{
await adminClient.CreateSubscriptionAsync(
new CreateSubscriptionOptions(subscriptionProperties),
new CreateRuleOptions(subscriptionFilterName, new CorrelationRuleFilter() { Subject = correlationFilterValue }));
}
}
Let me know if this is the correct way of setting the property values for "SubscriptionProperties" class or how can I do so?
I was able to fix this issue by following this link https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample07_CrudOperations.md#create-a-topic-and-subscription
var client = new ServiceBusAdministrationClient(connectionString);
string subscriptionName = "<subscription_name>";
var subscriptionOptions = new CreateSubscriptionOptions(topicName, subscriptionName)
{
AutoDeleteOnIdle = TimeSpan.FromDays(7),
DefaultMessageTimeToLive = TimeSpan.FromDays(2),
EnableBatchedOperations = true,
UserMetadata = "some metadata"
};
SubscriptionProperties createdSubscription = await client.CreateSubscriptionAsync(subscriptionOptions);
This might be helpful for other readers as well as having similar doubuts.

Why i can't connect websocket through proxy?

How can I connect websocket through proxy (without can)
var url = new Uri("ws://irc-ws.chat.twitch.tv:80");
var factory = new Func<ClientWebSocket>(() => new ClientWebSocket
{
Options =
{
Proxy = new System.Net.WebProxy("23.239.20.205",80),
}
});
var client = new WebsocketClient(url,factory);
client.Start();
client.Send("PASS oauth:xxx");
client.Send("NICK xxx");
client.Send("JOIN #xxx");
client.MessageReceived.Where(x =>
{
Console.WriteLine(x.Text);
return true;
}).Subscribe();
while (true)
{
client.Send("PRIVMSG #xxx :" + Console.ReadLine());
}

AndroidPublisherService - Play Developer API Client - Upload aab failes due to bad credentials

Trying to make use of the AndroidPublisherService from Play Developer API Client.
I can list active tracks and the releases in those tracks, but when I try to upload a new build there seems to be no way of attaching the authentication already made previously to read data.
I've authenticated using var googleCredentials = GoogleCredential.FromStream(keyDataStream) .CreateWithUser(serviceUsername); where serviceUsername is the email for my service account.
private static void Execute(string packageName, string aabfile, string credfile, string serviceUsername)
{
var credentialsFilename = credfile;
if (string.IsNullOrWhiteSpace(credentialsFilename))
{
// Check env. var
credentialsFilename =
Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS",
EnvironmentVariableTarget.Process);
}
Console.WriteLine($"Using credentials {credfile} with package {packageName} for aab file {aabfile}");
var keyDataStream = File.OpenRead(credentialsFilename);
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername);
var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
var service = new AndroidPublisherService();
var edit = service.Edits.Insert(new AppEdit { ExpiryTimeSeconds = "3600" }, packageName);
edit.Credential = credentials;
var activeEditSession = edit.Execute();
Console.WriteLine($"Edits started with id {activeEditSession.Id}");
var tracksList = service.Edits.Tracks.List(packageName, activeEditSession.Id);
tracksList.Credential = credentials;
var tracksResponse = tracksList.Execute();
foreach (var track in tracksResponse.Tracks)
{
Console.WriteLine($"Track: {track.TrackValue}");
Console.WriteLine("Releases: ");
foreach (var rel in track.Releases)
Console.WriteLine($"{rel.Name} version: {rel.VersionCodes.FirstOrDefault()} - Status: {rel.Status}");
}
using var fileStream = File.OpenRead(aabfile);
var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream");
var uploadProgress = upload.Upload();
if (uploadProgress == null || uploadProgress.Exception != null)
{
Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
return;
}
Console.WriteLine($"Upload {uploadProgress.Status}");
var tracksUpdate = service.Edits.Tracks.Update(new Track
{
Releases = new List<TrackRelease>(new[]
{
new TrackRelease
{
Name = "Roswell - Grenis Dev Test",
Status = "completed",
VersionCodes = new List<long?>(new[] {(long?) upload?.ResponseBody?.VersionCode})
}
})
}, packageName, activeEditSession.Id, "internal");
tracksUpdate.Credential = credentials;
var trackResult = tracksUpdate.Execute();
Console.WriteLine($"Track {trackResult?.TrackValue}");
var commitResult = service.Edits.Commit(packageName, activeEditSession.Id);
Console.WriteLine($"{commitResult.EditId} has been committed");
}
And as the code points out, all action objects such as tracksList.Credential = credentials; can be given the credentials generated from the service account.
BUT the actual upload action var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream"); does not expose a .Credential object, and it always fails with:
The service androidpublisher has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project. [401]
Errors [
Message[Login Required.] Location[Authorization - header] Reason[required] Domain[global]
]
at Google.Apis.Upload.ResumableUpload`1.InitiateSessionAsync(CancellationToken cancellationToken)
at Google.Apis.Upload.ResumableUpload.UploadAsync(CancellationToken cancellationToken)
So, how would I go about providing the actual Upload action with the given credentials here?
Managed to figure this out during the day, I was missing one call to CreateScoped() when creating the GoogleCredential object as well as a call to InitiateSession() on the upload object.
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername)
.CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
Once that was done I could then get a valid oauth token by calling
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername)
.CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
var oauthToken = credentials?.GetAccessTokenForRequestAsync(AndroidPublisherService.Scope.Androidpublisher).Result;
And I can now use that oauth token in the upload request:
upload.OauthToken = oauthToken;
_ = await upload.InitiateSessionAsync();
var uploadProgress = await upload.UploadAsync();
if (uploadProgress == null || uploadProgress.Exception != null)
{
Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
return;
}
The full code example for successfully uploading a new aab file to google play store internal test track thus looks something like this:
private async Task UploadGooglePlayRelease(string fileToUpload, string changeLogFile, string serviceUsername, string packageName)
{
var serviceAccountFile = ResolveServiceAccountCertificateInfoFile();
if (!serviceAccountFile.Exists)
throw new ApplicationException($"Failed to find the service account certificate file. {serviceAccountFile.FullName}");
var keyDataStream = File.OpenRead(serviceAccountFile.FullName);
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername)
.CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
var oauthToken = credentials?.GetAccessTokenForRequestAsync(AndroidPublisherService.Scope.Androidpublisher).Result;
var service = new AndroidPublisherService();
var edit = service.Edits.Insert(new AppEdit { ExpiryTimeSeconds = "3600" }, packageName);
edit.Credential = credentials;
var activeEditSession = await edit.ExecuteAsync();
_logger.LogInformation($"Edits started with id {activeEditSession.Id}");
var tracksList = service.Edits.Tracks.List(packageName, activeEditSession.Id);
tracksList.Credential = credentials;
var tracksResponse = await tracksList.ExecuteAsync();
foreach (var track in tracksResponse.Tracks)
{
_logger.LogInformation($"Track: {track.TrackValue}");
_logger.LogInformation("Releases: ");
foreach (var rel in track.Releases)
_logger.LogInformation($"{rel.Name} version: {rel.VersionCodes.FirstOrDefault()} - Status: {rel.Status}");
}
var fileStream = File.OpenRead(fileToUpload);
var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream");
upload.OauthToken = oauthToken;
_ = await upload.InitiateSessionAsync();
var uploadProgress = await upload.UploadAsync();
if (uploadProgress == null || uploadProgress.Exception != null)
{
Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
return;
}
_logger.LogInformation($"Upload {uploadProgress.Status}");
var releaseNotes = await File.ReadAllTextAsync(changeLogFile);
var tracksUpdate = service.Edits.Tracks.Update(new Track
{
Releases = new List<TrackRelease>(new[]
{
new TrackRelease
{
Name = $"{upload?.ResponseBody?.VersionCode}",
Status = "completed",
InAppUpdatePriority = 5,
CountryTargeting = new CountryTargeting { IncludeRestOfWorld = true },
ReleaseNotes = new List<LocalizedText>(new []{ new LocalizedText { Language = "en-US", Text = releaseNotes } }),
VersionCodes = new List<long?>(new[] {(long?) upload?.ResponseBody?.VersionCode})
}
})
}, packageName, activeEditSession.Id, "internal");
tracksUpdate.Credential = credentials;
var trackResult = await tracksUpdate.ExecuteAsync();
_logger.LogInformation($"Track {trackResult?.TrackValue}");
var commitResult = service.Edits.Commit(packageName, activeEditSession.Id);
commitResult.Credential = credentials;
await commitResult.ExecuteAsync();
_logger.LogInformation($"{commitResult.EditId} has been committed");
}

Using Azure GraphClient API how can you create a new Native Application?

It looks like the Application object in Microsoft.Azure.ActiveDirectory.GraphClient allows a Webapplication to be created. I cannot see how I can use this to create a new Native application.
thanks
Updates:
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
tcs.SetResult(accessToken);
var graphClient = new ActiveDirectoryClient(
new Uri($"{GraphApiBaseUrl}{tenantId}"),
async () => { return await tcs.Task; });
var password = Guid.NewGuid().ToString("N");
var cred = new PasswordCredential()
{
StartDate = DateTime.UtcNow,
EndDate = DateTime.UtcNow.AddYears(1),
Value = password
};
var app = await GetApplicationByUrlAsync(accessToken, tenantId, appName, identifierUrl);
if(app == null)
{
app = new Application()
{
DisplayName = appName,
Homepage = homePageUrl,
IdentifierUris = new List<string>() { identifierUrl },
LogoutUrl = logoutUrl,
ReplyUrls = new List<string>() { replyUrl },
PasswordCredentials = new List<PasswordCredential>() { cred },
};
await graphClient.Applications.AddApplicationAsync(app);
}
The fact that an app is a native client application is identified by the PublicClient boolean property on the Application object. (See client types from the OAuth 2.0 spec.)
So, you could register a native client app with the following code:
var app = new Application()
{
DisplayName = "My native client app",
ReplyUrls = new List<string>() { "urn:ietf:wg:oauth:2.0:oob" },
PublicClient = true
};
await graphClient.Applications.AddApplicationAsync(app);
Console.WriteLine("App created. AppId: {0}, ObjectId: {1}", app.AppId, app.ObjectId);
Note that the native client app does not have password credentials or key credentials (or any other secret).
Details about these and other properties of Application objects are available in the API reference documentation: https://msdn.microsoft.com/en-us/library/azure/ad/graph/api/entity-and-complex-type-reference#application-entity

Error : The security token included in the request is invalid - Windows Phone Using AWS SNS

I am using below code to register the device(Windows Phone) in AWS SNS as an endpoint in the application
CognitoAWSCredentials cognitoProvider = new CognitoAWSCredentials(UserId,
IdentitypoolID,
UnAuthRoleARN,
AuthRoleARN,
Region);
AmazonSimpleNotificationServiceClient sns = new AmazonSimpleNotificationServiceClient(cognitoProvider.GetCredentials().AccessKey.ToString(),
cognitoProvider.GetCredentials().SecretKey.ToString(), REgion); //provide credentials here
var channelOperation = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
CreatePlatformEndpointRequest epReq = new CreatePlatformEndpointRequest();
epReq.PlatformApplicationArn = ApplicationArn;
epReq.Token = channelOperation.Uri.ToString();
CreatePlatformEndpointResponse epRes = await sns.CreatePlatformEndpointAsync(epReq);
CreateTopicRequest tpReq = new CreateTopicRequest();
SubscribeResponse subsResp = await sns.SubscribeAsync(new SubscribeRequest()
{
TopicArn = TopicArn,
Protocol = "application",
Endpoint = epRes.EndpointArn
});
While create an endpoint it throws an error The security token included in the request is invalid while execute below code
CreatePlatformEndpointResponse epRes = await sns.CreatePlatformEndpointAsync(epReq);
Please help me to achieve this. Thanks in advance
Use the below code to register a windows phone device in AWS SNS Application. I can create endpoint using the below code.
private async void Push()
{
CognitoAWSCredentials cognitoProvider = new CognitoAWSCredentials(UserId,
IdentitypoolID,
UnAuthRoleARN,
AuthRoleARN,
Region);
using (var sns = new AmazonSimpleNotificationServiceClient(credentials, RegionEndpoint.USEast1))
{
var channelOperation = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
CreatePlatformEndpointRequest epReq = new CreatePlatformEndpointRequest();
epReq.PlatformApplicationArn = "PlatformApplicationARN";
epReq.Token = channelOperation.Uri.ToString();
CreatePlatformEndpointResponse epRes = await sns.CreatePlatformEndpointAsync(epReq);
CreateTopicRequest tpReq = new CreateTopicRequest();
SubscribeResponse subsResp = await sns.SubscribeAsync(new SubscribeRequest()
{
TopicArn = "TopicARN",
Protocol = "application",
Endpoint = epRes.EndpointArn
});
channelOperation.PushNotificationReceived += ChannelOperation_PushNotificationReceived;
}
}

Categories