I'm trying to create a valid RestRequest for taking advantage of the GET statuses/user_timeline.json provided by the Twitter API.
I have a dev account and my Consumer Key/Secret and AccessToken/TokenSecret
_restClient.Timeout = 60000;
_restClient.BaseUrl = "http://api.twitter.com/1.1"
_restClient.Authenticator = OAuth1Authenticator.ForProtectedResource(cKey, cSecret, aT, aTSecret)
var request = new RestRequest("statuses/user_timeline.json?screen_name=default", Method.GET)
var response = _restClient.Execute(request)
To this request I receive the response
{"errors":[{"message":"Could not authenticate you","code":32}]}
I suspect that I'm missing a step, since many resources I've found reach out to the BaseUrl of "api.twitter.com" first in order to make an TokenRequest, but I already have my token, so I'm not sure why that step would be necessary.
Thanks!
SOLUTION:
I've solved the problem simply by using the c# package TweetSharp
var service = new TwitterService(_twitterConfiguration.ConsumerKey, _twitterConfiguration.ConsumerSecret);
service.AuthenticateWith(_twitterConfiguration.AccessToken, _twitterConfiguration.AccessTokenSecret);
The above is everything you need to get connected to the twitter-api-1.1 service (as well as you're relevant tokens)
Related
I've tried different ways to connect the Microsoft sign in function which open a webpage so you can use things like sign in with MFA. I manage to get this to work in Postman and now im trying it in C# particularly in .NET MVC 5.
HomeController:
public ActionResult TestAuth()
{
HttpClient client = new HttpClient();
var bodyParams = new Dictionary<string, string>();
bodyParams.Add("client_id", "{my_client_id}");
bodyParams.Add("client_secret", "{my_client_secret}");
bodyParams.Add("scope", "openid");
bodyParams.Add("redirect_uri", "https://localhost");
bodyParams.Add("grant_type", "authorization_code");
var response = client.PostAsync("https://login.microsoftonline.com/{my_tenant_id}/oauth2/v2.0/authorize", new FormUrlEncodedContent(bodyParams)).Result;
return View("TestAuth", new { response.Content.ReadAsStringAsync().Result });
}
View TestAuth.cshtml:
#model dynamic
#Html.Raw(Model)
If i sign in with my email on that domain, or any text at all really, i get this message. I cannot see why this issue occurs it gives me zero information what to do next more than just trying until you make it basically :). I've looked at tons of different Microsoft documentations, Stack posts, forums etc but with no success.
The postman call example:
Is it possible I'm doing something wrong in the request in the c# code or am i missing something important like configurations in Azure AD etc?
I'm up for anything that will work that i can sign into a Microsoft account that use MFA, then i can use their login to fetch data from Microsoft Graph based on their permissions basically.
P.S. I also can fetch data with the access token generated from postman so it's working as expected. I only need to "convert the postman call to c#" to make it work esentially. Any help is appreciated :)
You’re trying to do an oauth2 request from the controller. The request you’re sending is incorrect.
Microsoft made a great sample on how to use the Microsoft identity platform in a dotnet application https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/1-WebApp-OIDC
In a nutshell you redirect the user to the endpoint (so not a get/post from the controller, but actually a redirect 302 response to the token url).
The user then has to login and is redirected to the webapplication.
Your webapplication will get an authorization code that is has to exchange for an access token by a post request.
Postman does this for you, but in order to do it in dotnet core, just follow the sample.
I didn't find a soultion to this specific problem what i did find was another guide which led me to this github project https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect
Which had similar code in the Startup.cs file but actually had some examples like SendMail and ReadMail etc which was fetched from ms graph api. This gave me some idea of how this project was structured compared to mine. So one thing that was missing was this part I couldnt figure out:
IConfidentialClientApplication app = await MsalAppBuilder.BuildConfidentialClientApplication();
var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId());
So the Msal app builder which is a custom made thingy i needed to get the current user etc which i needed. This works fine and after that i can start doing requests to the graph api like adding scopes etc and make http request.
Example see groups:
[Authorize]
[HttpGet]
public async Task<ActionResult> GetGroups()
{
IConfidentialClientApplication app = await MsalAppBuilder.BuildConfidentialClientApplication();
var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId());
string[] scopes = { "GroupMember.Read.All", "Group.Read.All", "Group.ReadWrite.All", "Directory.Read.All", "Directory.AccessAsUser.All", "Directory.ReadWrite.All" };
AuthenticationResult result = null;
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/groups");
try
{
//Get acccess token before sending request
result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false);
if (result != null)
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
//Request to get groups
HttpResponseMessage response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
ViewBag.Groups= response.Content.ReadAsStringAsync().Result;
return View("MyView");
}
}
}
catch (Exception ex)
{
Response.Write($"Error occured:{System.Environment.NewLine}{ex}");
}
return View();
}
I just knew about the RestSharp and started exploring it.
I could find how to "Log-in" using a user already created doing this:
var client = new RestClient("http://example.com");
client.Authenticator = new SimpleAuthenticator("username", "foo", "password", "bar");
var request = new RestRequest("resource", Method.GET);
client.Execute(request);
But is there a way of actually creating a user in the firebase using the Restshart? Equivilant to this using the Firebase object in JAVA
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.createUser({email:"bobtony#firebase.com",password:"correcthorsebatterystaple"});
I know it is possible to create a node for emails/passwords and manage them manually, but I would like to use the Firebase users auths.
Since the library is called RestSharp, it likely builds on top of the Firebase Legacy REST API. That API does not have functionality to create users.
I'm trying to use the Google Admin Settings API with a Service Account with no success from a C# Console application.
From what I've understood, I first have to get an OAuth token. I've tried 2 methods successfully for this: using Google.Apis.Auth.OAuth2.ServiceAccountCredentials or by creating manually the JWT assertion.
But when I call an Admin Settings API with the OAuth token (maximumNumberOfUsers for instance), I always get a 403 error with " You are not authorized to perform operations on the domain xxx" message.
I downloaded GAM as the author calls this API too so that I can compose the same HTTP requests. Like explained in GAM wiki, I followed all the steps to create a new Service Account and a new OAuth Client ID so that I can be sure it's not a scope issue. I also activated the debug mode like proposed by Jay Lee in this thread. Like explained in the thread comments, it still doesn't work with my OAuth token but the call to the API succeeds with GAM OAuth token.
So it seems it's related to the OAuth token itself. An issue I get while creating the OAuth token is that I can't specify the "sub" property (or User for ServiceAccountCredentials). If I add it, I get a 403 Forbidden response with "Requested client not authorized." as error_description while generating the token i.e. before calling the API. So maybe it is the issue but I don't see how to fix it as I use an Admin email.
Another possibility is that this API needs the OAuth Client credentials as GAM requires 2 different types of credentials, Service Account and OAuth Client. As I only can use Service Account credentials in my project, I'm afraid I will be stuck if it is the case...
I don't see other options and I'm stuck with both, so any help appreciated. Thanks!
My code:
public static string GetEnterpriseUsersCount()
{
string domain = MYDOMAIN;
string certPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
certPath = certPath.Substring(0, certPath.LastIndexOf("\\") + 1) + "GAMCreds.p12";
var certData = File.ReadAllBytes(certPath);
X509Certificate2 privateCertificate = new X509Certificate2(certData, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(SERVICE_ACCOUNT_EMAIL)
{
Scopes = new[] { "https://apps-apis.google.com/a/feeds/domain/" },
User = ADMIN_EMAIL
}.FromCertificate(privateCertificate));
Task<bool> oAuthRequest = credential.RequestAccessTokenAsync(new CancellationToken());
oAuthRequest.Wait();
string uri = string.Format("https://apps-apis.google.com/a/feeds/domain/2.0/{0}/general/maximumNumberOfUsers", domain);
HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
if (request != null)
{
request.Method = "GET";
request.Headers.Add("Authorization", string.Format("Bearer {0}", credential.Token.AccessToken));
// Return the response
using (WebResponse response = request.GetResponse())
{
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
return sr.ReadToEnd();
}
}
}
return null;
}
Edit: I focused on scopes like advised by Jay Lee below and it appears that the missing scope was 'https://www.googleapis.com/auth/admin.directory.domain'. However, nowhere is this written in Admin Settings API documentation page. At least, I didn't find it. 'https://apps-apis.google.com/a/feeds/domain/' is necessary too but I already added it to the list of allowed scopes. Thanks Jay!
Edit 2: I also updated the source code so that it can help in the future.
You need to grant your service account's client ID access to the scopes for admins settings API. Follow the Drive domain wide delegation instructions except sub in the correct correct scope. Then you can set sub= without an error.
I am trying to use box api in an asp.net web application.
Based on the search there are two options to access box account;
By downloading the Box.V2 package using below link containing the required dlls and use that in our application
By using Box SDK containing code and reference that inside our application. Using this approach we can debug the Box.V2 code by adding the project to our solution.
Correct me if I am wrong.
So, I am trying to implement the second approach. Can someone help me move forward by specifying the steps to be taken, minimum .net framework requirement, etc.
Good question, GitHub samples does not mention about the Web (Asp.Net).
It's possible and it looks pretty easy to do once you figure out the the way,
I have seen some answers for Windows apps trying to manually build the authorization URLs etc, but there is an easier way to do it.
Here's how to do it with OAuth,
Install nuget
PM> Install-Package Box.V2
Get the Authcode (this is what's been missing in most examples)
public async Task<ActionResult> Connect()
{
var clientId = "xxxxx";
var clientSecret = "xxxxxx";
var redirectUri = new Uri("http://localhost:xxxx/Home/AuthCallBackAsync");//Your call back URL
var config = new BoxConfig(clientId, clientSecret, redirectUri);
return Redirect(config.AuthCodeUri.ToString());
}
Interesting thing is that the "config" object generates the AuthCodeUri.
This will redirect the user to Consent screen and ask the user to sign in. Once the user "Grants Access" you will get the "Authcode" for your call back URL which can be used to generate accesstoken.
Handle the Auth Callback response
public async Task<ActionResult> AuthCallbackAsync()
{
NameValueCollection parms = Request.QueryString;
var authCode = parms["code"]
//Get "config" - you can store this in session or in a cache.
var config = new BoxConfig(clientId, clientSecret, redirectUri);
var client = new BoxClient(config);
await client.Auth.AuthenticateAsync(authCode);
//Now you will get the accesstoken and refresh token
var accessToken = client.Auth.Session.AccessToken;
var refreshToken = client.Auth.Session.RefreshToken;
//Ready to consume the API
var user = await client.UsersManager.GetCurrentUserInformationAsync();
-------More Api Calls---
}
I have the fallowing code.
var ctx = new XrmContext(new Uri(serviceUrl));
ctx.Credentials = new NetworkCredential("username", "password", "domain");
ctx.AccountSet.First();
Silverlight version is (In fiddler we have here the same result)
var ctx = new AdzzContext(new Uri(serviceUri));
ctx.HttpStack = System.Data.Services.Client.HttpStack.ClientHttp;
ctx.UseDefaultCredentials = false;
ctx.Credentials = new NetworkCredential("username", "password", "admin");
var query = ctx.AccountSet;
var async = new DataServiceCollection<Account>();
async.LoadCompleted += async_LoadCompleted;
async.LoadAsync(query);
What give me the falling error.
The response payload is a not a valid response payload. Please make
sure that the top level element is a valid Atom element or belongs to
'http://schemas.microsoft.com/ado/2007/08/dataservices' namespace.
When I look at fiddler I see a redirect to the adfs server
I saw this link, but it is for CRM 4, And in the context of the OData I can't put a token.
My target is so,
To make a Silverlight library for business logic (BL) purpose - So I can debug it easily in my computer - and it will run perfectly in the CRM environment,
How can I do it?
you need to generate the early bound classes (using crmsvcutil.exe) and specify the ServiceContextName parameter.
Assuming your context is XrmContext, you need to instantiate in this way:
var context = new XrmContext(service);
where service is the IOrganizationService web service.
You don't need to specify the credentials because the connection credentials are handled when you instantiate the OrganizationServiceProxy
Sample code: http://nishantrana.wordpress.com/2010/11/03/sample-code-for-using-iorganizationservice-in-crm-2011/