I'm trying to authenticate an EWS application by using OAuth. Unfortunatelly, I get a NullReferenceException when calling FindFolders() (code below). But, what is interensting - not always, just sametimes. Is anyone facing this issue too and can help me with this?
This is code you should be interested in:
var cca = ConfidentialClientApplicationBuilder
.Create("hidden")
.WithClientSecret("hidden")
.WithTenantId("hidden")
.WithRedirectUri("http://localhost")
.Build();
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };
try
{
var authResult = await cca.AcquireTokenForClient(ewsScopes)
.ExecuteAsync();
// Configure the ExchangeService with the access token
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
ewsClient.ImpersonatedUserId =
new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "mail");
//Include x-anchormailbox header
ewsClient.HttpHeaders.Add("X-AnchorMailbox", "mail");
// Make an EWS call
var folders = ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(15));
foreach (var folder in folders)
{
Console.WriteLine(folder.DisplayName);
}
}
catch (MsalException ex)
{
Console.WriteLine($"Error acquiring access token: {ex}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex}");
}
What I've already tried is cloning this repository https://github.com/pawelFelcyn/ews-managed-api instead of installing nuget package. And it helped, as I could find where the exception is being thrown. It's in ServiceRequestBase.WrapStream(), becuase contentEncoding is null (you can see this on github - the file is in folder Core/Requests). I've just added a simple nullcheck like this:
if (contentEncoding is null)
{
return responseStream;
}
But this brings some other problems. As I understood, version of this library on github does not support somethig connected with Xml, what I need. Can anyone help me, please?
Related
Before I begin, allow me to say that I have scoured MSFTs docs, everything seems to imply that I need to manually handroll the GET request? Which seems wrong, given that the SDK handles that for us.
What I am experiencing from my Xamarin app is the following 403 error when I try to run my code to get a list of blobs.
<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of the Authorization header is formed correctly including the signature.</Message></Error>
The way my workflow goes is as follows:
App Makes request to API to get Azure SAS token
API Responds using the following code to return the SAS token (blobServiceClient is defined using the default emulator storage connection string):
try
{
var client = blobServiceClient.GetBlobContainerClient(request.VenueId);
var permissions = BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List;
var sas = client.GenerateSasUri(permissions, DateTimeOffset.Now.AddHours(1));
var containerUri = "";
#if DEBUG
var temp = sas.AbsoluteUri;
var replaced = temp.Replace("http://127.0.0.1:10000/", "http://myngrokproxy.ngrok.io/");
containerUri = replaced;
#else
containerUri = sas.AbsoluteUri;
#endif
//var sas = containerUri + container.GetSharedAccessSignature(accessPolicy);
return new AzureSASResponse
{
SAS = containerUri
};
} catch (Exception e)
{
return null;
}
As you can see, the replace is there since localhost URL is meaningless for the emulator.
App side I try to consume it as follows:
try
{
var uri = new Uri(SAS);
var containerClient = new BlobContainerClient(uri);
var blobs = containerClient.GetBlobs().AsPages();
foreach(var blob in blobs)
{
Console.WriteLine(blob);
}
} catch (Exception e)
{
Console.WriteLine(e);
}
My resulting SAS token looks like so: "http://myngrokproxy.ngrok.io/devstoreaccount1/8dc9e4831d634629b386680ad7c9a324?sv=2020-08-04&se=2021-10-21T21%3A43%3A16Z&sr=c&sp=rl&sig=oncjUlSLMsOS3WbxUWqjXDp28WACYxxVqUElrK%2BYNlY%3D"
How can I go about A) setting the auth header on it, even the GET request that fails is the .GetBlobs method in the Xamarin app?
After much trial and error my ways to fix it were as follows:
Use latest version of azurite from Microsoft, I used the original old one (Arafuto/azurite)
change code to look as follows;
var sasBuilder = new BlobSasBuilder()
{
BlobContainerName = containerClient.Name,
Resource = "c",
StartsOn = DateTimeOffset.UtcNow.AddMinutes(-15),
ExpiresOn = DateTimeOffset.UtcNow.AddDays(7)
};
sasBuilder.SetPermissions(BlobSasPermissions.Read | BlobSasPermissions.List);
var client = blobServiceClient.GetBlobContainerClient(request.VenueId);
var permissions = BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List;
var sas = client.GenerateSasUri(sasBuilder);
var containerUri = "";
#if DEBUG
var temp = sas.AbsoluteUri;
var replaced = temp.Replace("http://127.0.0.1:10000/", "http://myngrokproxy.ngrok.io/");
containerUri = replaced;
#else
containerUri = sas.AbsoluteUri;
#endif
return new AzureSASResponse
{
SAS = containerUri
};
The inspiration for the BlobSasBuilder came from this document: https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-user-delegation-sas-create-dotnet#get-a-user-delegation-sas-for-a-container
I am getting while setting meta data in azure data lake file using azure fileclient, it's throwing the exception like "Specified value has invalid HTTP Header characters. Parameter name: name in azure data lake"
I am using the Dictionary to set metadata.
PathHttpHeaders path = new PathHttpHeaders();
path.ContentType = "application/octet-stream";
fileClient.SetHttpHeaders(path);
var metaDataProperties = await GetMetaDataProperties(entityData);
await fileClient.SetMetadataAsync(metaDataProperties);
The above issue has been resolved, the issue was coming due to the FileClient instance, I was using the same FileClient instance which I have used to store the file into the Azure data lake. For resolving the issue I have created a new FileClient Instance and that worked for me. Below is my code.
private async Task SetMetaDataProps(MessageWrapper wrapper, Uri uri, string filename)
{
try
{
var entityData = JObject.Parse(wrapper.Payload);
entityData["FileName"] = filename;
var storageCredentials = new StorageSharedKeyCredential("accountName", "accountKey");
var fileclient = new DataLakeFileClient(uri, storageCredentials);
var metaDataProps = await GetMetaDataProperties(entityData);
var ss = fileclient.SetMetadataAsync(metaDataProps);
}
catch(Exception ex)
{
throw ex;
}
}
I'd like to get result of azure vm deployment using Azure Resource Manager(ARM) with .NET C# to recognize its success or fail.
I found following sample.
https://learn.microsoft.com/en-us/azure/virtual-machines/virtual-machines-windows-csharp-template
In this article, when deploing, "return await" statement is used.
public static async Task<DeploymentExtended> CreateTemplateDeploymentAsync(
TokenCredentials credential,
string groupName,
string deploymentName,
string subscriptionId){
Console.WriteLine("Creating the template deployment...");
var deployment = new Deployment();
deployment.Properties = new DeploymentProperties
{
Mode = DeploymentMode.Incremental,
Template = File.ReadAllText("..\\..\\VirtualMachineTemplate.json"),
Parameters = File.ReadAllText("..\\..\\Parameters.json")
};
var resourceManagementClient = new ResourceManagementClient(credential)
{ SubscriptionId = subscriptionId };
return await resourceManagementClient.Deployments.CreateOrUpdateAsync(
groupName,
deploymentName,
deployment);
}
How can I handle the result?
I want to devide program according to the result.
We can get the deployment status using the Properties.ProvisioningState. But when it deploy VM failed, may throw exception, so we need to catch the exception with code.
1.Code demo :
var token = GetAccessTokenAsync();
var credential = new TokenCredentials(token.Result.AccessToken);
string provisoningStatus = "Failed";
try
{
var result =CreateTemplateDeploymentAsync(credential, "tom", "MyWindowsVM", "you subscription Id")
.Result;
provisoningStatus = result.Properties.ProvisioningState;
}
catch (Exception)
{
//ToDo
}
if (provisoningStatus.Equals("Failed"))
{
//TODo
}
}
Create a VM successfully
Check from the Azure Portal
If it is failed without catching exception
I'm trying to retrieve a (paged) list of all users in the directory, with the manager property expanded. When I run the following HTTP query it works as I want:
https://graph.windows.net/DOMAIN/users/?$expand=manager&api-version=2013-11-08
However I don't seem to grasp how to make the same query with the Azure AD Graph client. This is what I'm trying:
var userResult = _activeDirectoryClient.Users.Expand(x => x.Manager).ExecuteAsync().Result;
I adapted the following from the example at https://github.com/AzureADSamples/ConsoleApp-GraphAPI-DotNet/blob/master/GraphConsoleAppV3/Program.cs, please give it a shot:
List<IUser> usersList = null;
IPagedCollection<IUser> searchResults = null;
try
{
IUserCollection userCollection = activeDirectoryClient.Users;
userResult = userCollection.ExecuteAsync().Result;
usersList = searchResults.CurrentPage.ToList();
}
catch (Exception e)
{
Console.WriteLine("\nError getting User {0} {1}", e.Message,
e.InnerException != null ? e.InnerException.Message : "");
}
if (usersList != null && usersList.Count > 0)
{
do
{
usersList = searchResults.CurrentPage.ToList();
foreach (IUser user in usersList)
{
Console.WriteLine("User DisplayName: {0} UPN: {1} Manager: {2}",
user.DisplayName, user.UserPrincipalName, user.Manager);
}
searchResults = searchResults.GetNextPageAsync().Result;
} while (searchResults != null);
}
else
{
Console.WriteLine("No users found");
}
The GraphClient does not implement all of the features in the Graph API just yet.
New features are being added to the GraphClient over time and will be announced on the AAD team blog:
http://blogs.msdn.com/b/aadgraphteam/
And updates will be available in the nuget package ( Microsoft Azure Active Directory Graph Client Library ).
You can make what you need by making Http calls to the url you have in the question and get the response back as Json like this:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://graph.windows.net/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("DOMAIN/users/?$expand=manager&api-version=2013-11-08");
if (response.IsSuccessStatusCode)
{
// TODO: Deserialize the response here...
}
}
I'm trying to delete one or more videos using a simple C# app (I intend to use a Windows Service later) and I'm getting this error:
Google.Apis.Auth.OAuth2.Responses.TokenResponseException: Error:"unauthorized_client", Description:"Unauthorized client or scope in request.", Uri:""
at Google.Apis.Requests.ClientServiceRequest`1.Execute() in c:\code\google.com\google-api-dotnet-client\default\Tools\Google.Apis.Release\bin\Debug\test\default\Src\GoogleApis\Apis\Requests\ClientServiceRequest.cs:line 93
Uploading videos works perfectly. For both operations, I use the same initialization method:
private static YouTubeService AuthorizeYoutubeService()
{
string serviceAccountEmail = "...#developer.gserviceaccount.com";
string keyFilePath = "Warehouse<...>.p12";
string userAccountEmail = "login#gmail.com";
if (!File.Exists(keyFilePath))
{
System.Windows.Forms.MessageBox.Show("Secret file not found!");
return null;
}
var scope = new string[] { YouTubeService.Scope.Youtube };
var cert = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
try
{
ServiceAccountCredential credential = new ServiceAccountCredential
(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scope,
User = userAccountEmail
}.FromCertificate(cert));
var service = new YouTubeService(new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = "warehouse"
});
return service;
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
return null;
}
}
The difference compared to simply uploading videos, is the defined Scope: YouTubeService.Scope.YoutubeUpload. When I try to delete a video using it, I get an insufficientPermissions (403) error.
So after looking in the documentation I've changed it to YouTubeService.Scope.Youtube.
Here's the code I'm trying to use:
var youtubeService = AuthorizeYoutubeService();
foreach (string id in deleteIds)
{
var videoDeleteRequest = youtubeService.Videos.Delete(id);
var result = videoDeleteRequest.Execute();
}
Where deleteIds is a list of 11 character strings containing IDs of existing videos.
I have YouTube Data API enabled in the developers console.
I've installed the API via NuGet, I don't think there's anything wrong with the packages.
I'm quite new to Google development, and all similar questions were about the calendar API.
I appreciate any help.
What I ended up doing is reseting the list of apps connected to the Google account and setting it up again from scratch. My app was added 2 times for some reason.