I am new to Amazon Web Services.
I configured domain to use ElasticSearch in AWS(Amazon Web Services) console. Confirured usage of Http Requests.
Went through documantation of creating ElasticSearch client from
https://www.elastic.co/guide/en/elasticsearch/client/net-api/1.x/security.html
var response = client.RootNodeInfo(c => c
.RequestConfiguration(rc => rc
.BasicAuthentication("UserName", "Password")
));
Works fine to me (Response is 200)
But when i try to configure authentication credentials like this and pass config to client constructor i need to have "cloudId" i didnt find in at AWS where sould i search for it? or what i have to do?
My client code:
BasicAuthenticationCredentials credentials = new BasicAuthenticationCredentials("UserName", "Password");
var config = new ConnectionSettings("cloudId???", credentials);
var client = new ElasticClient(config);
var response = client.Ping();
I recently did this but a different way. I used the Nuget package AwsSignatureVersion4 and an IAM user with appropriate permissions to the ElasticSearch service.
But basically, use the ImmutableCredentials and just do what I need to do via the REST calls and the C# HttpClient. I find it easier than using the .NET ElasticSearch library. I can then copy/paste back and forth from Kibana.
var credentials = new ImmutableCredentials("access_key", "secret_key", null);
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(someObjOrQuery), Encoding.UTF8);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var resp = httpClient.PostAsync(es_url,
httpContent,
regionName: "us-east-1",
serviceName: "es",
credentials: credentials).GetAwaiter().GetResult();
if(resp.IsSuccessStatusCode)
{
//Good to go
}
else
{
//this gets what ES sent back
var content = response.Content.ReadAsStringAsync();
dynamic respJson = JObject.Parse(content.Result());
//Now you can access stuff by dot and it's dynamic respJson.something
}
Related
I would like to subscript to a Salesforce platform event. I am trying to create a client in C#/.NET for a Salesforce Pub/Sub API. There are examples in other languages but not in .NET : https://github.com/developerforce/pub-sub-api
I am using the Grpc.Net.Client nuget packages.
var topicName = "/event/SomeEvent__e";
var pubSubEndpoint = "https://api.pubsub.salesforce.com:7443";
var accessToken = "xxxx";
var organisationId = "xxxx";
var instanceUrl = "https://xxxxx.sandbox.my.salesforce.com";
var credentials = CallCredentials.FromInterceptor((c, m) =>
{
m.Add("accesstoken", accessToken);
m.Add("instanceurl", instanceUrl);
m.Add("tenantid", organisationId);
return Task.CompletedTask;
});
var options = new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
};
var channel = GrpcChannel.ForAddress(pubSubEndpoint, options);
var client = new PubSub.PubSubClient(channel);
var topicRequest = new TopicRequest()
{
TopicName = topicName
};
var topic = client.GetTopic(topicRequest);
I know my credentials are correct because I can use postman to hit the oauth2 endpoint and get a valid access token. But when I try and call a client method like client.GetTopic, then I get the following error.
Status(StatusCode="PermissionDenied", Detail="An error occurred while getting the metadata for org CORE/prod/00DN0000000c8Hk and topic /event/SomeEvent__e. Ensure the credentials and topic name are correct. rpcId: 21d854fb-17dc-4778-9524-6264bd1a920d")
Am I setting up the credentials object wrong? I cannot find any example of subscribing to a Salesforce Pub/Sub in .NET.
I'm trying to implement a C# program to connect to Sharepoint API through modern authentication (Client ID\ Client Secret).
I've registered an APP with Sharepoint overall permissions on Azure Active Directory, in order to generate Client Id and Client Secret.
Next steps should be retrieval of the Access Token from the Microsoft login page, and then construction of all following requests using the bearing token I've generated.
Retrieval of the Access Token just works fine. The problem is when I try to include the token in the authorization header on the following calls.
I always get 401 Unhautorized when building my requests from code. Debugging the response content, what I get is "x-ms-diagnostics: 3000006;reason="Token contains invalid signature"; category"invalid_client".
Instead if I try to replicate the call in Postman I get the following error "{"error_description":"Unsupported security token."}".
I provide my code below. Does anybody knows what is going on?
var b2cAuthUri = "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token";
var client = new HttpClient();
var dict = new Dictionary<string, string>();
dict.Add("Content-Type", "application/x-www-form-urlencoded");
dict.Add("grant_type", "client_credentials");
dict.Add("client_id", clientId);
dict.Add("client_secret", clientSecret);
dict.Add("scope", scope);
// Execute post method
using (var methodResp = client.PostAsync(b2cAuthUri, new FormUrlEncodedContent(dict)))
{
var callResult = methodResp.Result.Content.ReadAsStringAsync().Result;
if (!string.IsNullOrEmpty(callResult))
{
//I have my Access Token here :)
using (MemoryStream DeSerializememoryStream = new MemoryStream())
{
//initialize DataContractJsonSerializer object and pass custom token class type to it
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AccessToken));
//user stream writer to write JSON string data to memory stream
StreamWriter writer = new StreamWriter(DeSerializememoryStream);
writer.Write(callResult);
writer.Flush();
DeSerializememoryStream.Position = 0;
//get the Desrialized data in object of type Student
AccessToken SerializedObject = (AccessToken)serializer.ReadObject(DeSerializememoryStream);
var tokenBytes = System.Text.Encoding.UTF8.GetBytes(SerializedObject.access_token);
//64bit serialized token
var tokenBase64 = System.Convert.ToBase64String(tokenBytes);
//Here I try to make a call with the access token as header
var testURI = "https://myorg.sharepoint.com/sites/crmkb/_api/web/lists";
HttpWebRequest testReq = (HttpWebRequest)HttpWebRequest.Create(testURI);
testReq.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + tokenBase64);
testReq.Method = "GET";
//This fails on 401 code
HttpWebResponse response = (HttpWebResponse)testReq.GetResponse();
}
}
}
SharePoint Online has blocked the Azure AD App Client Secret, so if you want to use Azure AD App to authentication with SharePoint Rest API, it's necessary to use Certificate option:
Calling SharePoint Online APIs using Azure AD App-Only permissions and certificate auth
Another option is to use the SharePoint hosted App Id/ Secret registered in "/_layouts/15/appregnew.aspx", this way supported the Client Secret, please check the demo test in Postman:
Accessing SharePoint Data using Postman (SharePoint REST API)
I'm working on a multilanguage project for accademic purpose. I've written a simple Python Client that make requests to an API server written in ASP.NET. The server retrives spotify info about users. The server interacts with a DB filled by a Golang server that only makes scraping on API's exposed from Spotify. I'm aware that it's a misuse and there are better solutions
Clearly, Golang server, in order to make requests to Spotify API's, needs to know the access token returned from spotify Authorization Code Flow. Overlooking about spotify token expire time, the idea is: after user authentication through Identity module of ASP.NET server (using JWT token), associate the access token obtained calling https://accounts.spotify.com/api/token to user's informations. So, i expose an API in ASP.NET server like this
[AllowAnonymous]
[HttpPost("token")]
public async Task<ContentResult> getTokenAsync(string? code = null)
{
//to retrive information about who is the user that making call -> need later for associate spotifytoken
string accessToken = Request.Headers[HeaderNames.Authorization].ToString().Replace("Bearer ", "");
JwtSecurityTokenHandler t = new JwtSecurityTokenHandler();
var token = t.ReadJwtToken(accessToken);
var user = _userManager.FindByIdAsync(token.Subject).Result;
string s = "https://accounts.spotify.com/api/token";
if (code == null)
{
var qb = new QueryBuilder();
qb.Add("response_type", "code");
qb.Add("client_id", _config["SpotiSetting:clientId"]);
qb.Add("scope", "user-read-private user-read-email user-library-read");
qb.Add("redirect_uri", _config["SpotiSetting:redirectUser"]);
qb.Add("show_dialog", "true");
return new ContentResult
{
ContentType = "text/html",
Content = "https://accounts.spotify.com/authorize/" + qb.ToQueryString().ToString()
//Content = JsonConvert.SerializeObject(user.Result)
};
} else
{
//if i'm here, api is the callback designed for spotify
var qb = new QueryBuilder();
qb.Add("grant_type", "authorization_code");
qb.Add("code", code);
qb.Add("redirect_uri", "https://localhost:44345/spotify/token");
var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Post, s);
req.Content = new FormUrlEncodedContent(qb);
req.Headers.Authorization = new AuthenticationHeaderValue("Basic", "here_my_secret_encoded_CLIENTID:CLIENT_SECRET");
var response = await client.SendAsync(req);
var result = response.Content.ReadAsStringAsync().Result;
AccessToken json = JsonConvert.DeserializeObject<AccessToken>(result);
user.spotifyInformation.authToken = code;
user.spotifyInformation.accessToken = json;
var res = _userManager.UpdateAsync(user);
if (res.IsCompletedSuccessfully)
{
return Content("ok");
}
else
{
Content("Problem");
}
} return Content("");
}
The problem is that the second time that API is invoked, it's spotify that is sending the first authorization token (needed to request access_token), so I lost user information retrived in the first request. Should be better write two distinct API and separate callback from user request?
It's my first question here, so please to have mercy
I am having problems accessing SharePoint using both CSOM and the REST service from a .NET Core console application.
First I created a console application that targets .NET Framework 4.6.1, installed the Microsoft.SharePointOnline.CSOM nuget package, and added two sample methods to connect to SharePoint using hard-coded user credentials. This works.
public static void CsomCall()
{
var password = "password";
var securePassword = new SecureString();
foreach (var c in password.ToCharArray()) securePassword.AppendChar(c);
using (ClientContext context = new ClientContext("https://siteurl"))
{
context.Credentials = new SharePointOnlineCredentials("user#domain", securePassword);
Web web = context.Web;
context.Load(web);
context.ExecuteQuery();
Console.WriteLine(web.Title);
}
}
private static void RestCall()
{
var password = "password";
var securePassword = new SecureString();
foreach (var c in password.ToCharArray()) securePassword.AppendChar(c);
var credentials = new SharePointOnlineCredentials("user#domain", securePassword);
using (WebClient client = new WebClient())
{
client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
client.Credentials = credentials;
client.Headers.Add(HttpRequestHeader.ContentType, "application/json;odata=verbose");
client.Headers.Add(HttpRequestHeader.Accept, "application/json;odata=verbose");
var content = client.DownloadString("https://siteurl/_api/web/lists");
Console.WriteLine(content);
}
}
Then I created a .NET Core console application and copied across the methods above. I understand that SharePoint CSOM is not yet supported in .NET Core, so I used the workaround suggested here and manually referenced Microsoft.SharePoint.Client.Portable.dll, Microsoft.SharePoint.Client.Runtime.Portable.dll and Microsoft.SharePoint.Client.Runtime.Windows.dll.
I had to make a couple of changes to compile the code:
.ExecuteQueryAsync() instead of .ExecuteQuery()
var credentials = new SharePointOnlineCredentials("user#domain", password); Note, password is a plain string in Microsoft.SharePoint.Client.Runtime.Portable.
When running CsomCall it fails when accessing web.Title:
Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException: 'The property or field 'Title' has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.'
When running RestCall it fails with an error on client.DownloadString:
System.Net.WebException: 'The remote server returned an error: (401) Unauthorized.'
Is it possible to set up SharePointOnlineCredentials to work with .NET Core? Searches on stack overflow indicate this should be possible, but I just can't seem to make it work.
Ultimately we would like to build a Web API service using ASP.NET Core to generate documents for internal users (reading document templates from SharePoint, generating a new document and saving back to SharePoint). Using either CSOM or REST, and running on Windows OS for now.
The REST call is wrong. You have to get a token using the credentials. Also, the WebClient is mostly deprecated, use the HttpClient class instead.
Look at this example:
public const string BaseUri = "https://example.sharepoint.com";
private static HttpClient _client;
public static void Initialize()
{
SharePointOnlineCredentials currentCredentials = GetCredentialsHere();
var handler = new HttpClientHandler
{
Credentials = currentCredentials
};
_client = new HttpClient(handler);
// you are missing this line
handler.CookieContainer.SetCookies(BaseUri, currentCredentials.GetAuthenticationCookie(BaseUri));
_client.BaseAddress = BaseUri;
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client.MaxResponseContentBufferSize = 2147483647;
}
I'm playing with OneDrive SDK 1.1.15.0:
try
{
AppConfig appConfig = new AppConfig
{
MicrosoftAccountAppId = oneDriveClientID, //something like 00000000123456AB
MicrosoftAccountClientSecret = oneDriveClientSecret, //something like 3vx[...]1sJ
MicrosoftAccountReturnUrl = "https://localhost/return",
MicrosoftAccountScopes = new string[] { "wl.signin", "wl.offline_access", "onedrive.readonly" }
};
OneDriveClient oneDriveClient = new OneDriveClient(appConfig);
AccountSession accountSession = await oneDriveClient.AuthenticateAsync();
//more code
await oneDriveClient.SignOutAsync();
}
catch (Exception ex)
{
throw ex;
}
My problem is in line:
AccountSession accountSession = await oneDriveClient.AuthenticateAsync();
that throws the following exception:
Microsoft.OneDrive.Sdk.OneDriveException, AuthenticationFailure: Failed to retrieve a valid authentication token for the user.
Any ideas?
Thank you in advance!
UPDATE
After reading comment from ginach (thank you!), I update my code. Some arguments to underline:
I want to access OneDrive from an Azure worker Role, so no authentication windows or something like that.
I upload the Microsoft.OneDrive SDK to 1.1.20 version.
I already registered my application to the OneDrive dev portal.
My actual code is:
try
{
MicrosoftAccountServiceInfo serviceInfo = new MicrosoftAccountServiceInfo();
serviceInfo.AppId = oneDriveClientID; //something like: 00000000ABCDEFGH
serviceInfo.ClientSecret = oneDriveClientSecret; //something like: 3vx[...]1sJ
serviceInfo.ReturnUrl = oneDriveReturnUrl; //something like: https://localhost/return
serviceInfo.Scopes = oneDriveAccountScopes; //something like new string[] { "wl.signin", "wl.offline_access", "onedrive.readonly" }
MicrosoftAccountAuthenticationProvider authenticationProvider = new MicrosoftAccountAuthenticationProvider(serviceInfo);
OneDriveClient oneDriveClient = await OneDriveClient.GetAuthenticatedMicrosoftAccountClient(oneDriveClientID, oneDriveReturnUrl, oneDriveAccountScopes, authenticationProvider);
//more code
await oneDriveClient.SignOutAsync();
}
catch (OneDriveException odex)
{
throw odex;
}
catch (Exception ex)
{
throw ex;
}
I obtain again and again (in OneDriveClient.GetAuthenticatedMicrosoftAccountClient method) a OneDriveException stating (Error property): AuthenticationFailure - Failed to retrieve a valid authentication token for the user.
Any suggestion?
Thank you.
UPDATE 2
OK, I'm trying a new approach. Using RestSharp I try to login to OneDrive with that code:
string clientId = "00[...]00";
string scopes = "wl.signin, wl.offline_access, onedrive.readonly";
string responseType = "code";
string redirectUri = "https://login.live.com/oauth20_desktop.srf";
RestClient client = new RestClient("https://login.live.com");
RestRequest request = new RestRequest();
request.Method = Method.GET;
request.Resource = "oauth20_authorize.srf";
request.AddQueryParameter("client_id", clientId);
request.AddQueryParameter("scope", scopes);
request.AddQueryParameter("response_type", responseType);
request.AddQueryParameter("redirect_uri", redirectUri);
IRestResponse response = client.Execute(request);
string content = response.Content;
I check the request with Fiddler and what I'm sending is:
https://login.live.com/oauth20_authorize.srf?client_id=00[...]00&scope=wl.signin%20wl.offline_access%20onedrive.readonly&response_type=code&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf
But OneDrive server answers my with:
Microsoft account requires JavaScript to sign in. This web browser either does not support JavaScript, or scripts are being blocked. To find out whether your browser supports JavaScript, or to allow scripts, see the browser's online help.
So I try the request in a browser and OneDrive server redirects me to the authorization page:
Now the question is: is there any workaround to skip the manual authorization?
Thank you,
Attilio
The client requires an authentication provider to be able to retrieve authentication tokens. There are a few ways to do this depending on your current platform.
Create your own IAuthenticationProvider implementation. The authentication provider is responsible for setting the Authentication header on requests. Here's how you would create a client instance with a custom authentication provider:
var client = new OneDriveClient(appConfig, serviceInfoProvider: new
ServiceInfoProvider(new CustomAuthenticationProvider()));
Use one of the various default authentication implementations. Take a look at the SDK authentication documentation for the available options and examples.
If you have a refresh token and only want to do the silent authentication flow you can use OneDriveClient.GetSilentlyAuthenticatedMicrosoftAccountClient. Here's an example:
var client = await OneDriveClient.GetSilentlyAuthenticatedMicrosoftAccountClient(clientId, returnUrl, scopes, refreshToken);