Authenticate twitter bot with static secrets? - c#

My plan:
I am writing a bot, that will send some tweets every now and then using the library tweetinvi (https://github.com/linvi/tweetinvi).
The bot is currently using the access token and secret I generated in my developer console.
The issue:
The bot will send the tweets using my personal account now. That's why I created a new secondary account, that should be used for the tweets in the future.
But how can I authenticate the bot now?
The new account is not a developer account and I don't see any option to generate an access token and secret in the account settings.
Further more I don't think the usual oauth "click on the twitter icon and login to twitter" sign in is the right choice for my bot, because I don't have a website or browser session, just a program that runs wherever.
Can't I just create a some static sort of access token and a secret for my secondary account?
What would you suggest me to do, if that is not possible?

Yes, you can create an access token and secret for your secondary account. The standard way to do this would be to implement sign-in with Twitter in an app, which would require a web backend.
There are a couple of alternative options:
You can use twurl, which is a Twitter-provided command line tool. You’ll need to have Ruby installed, and then install twurl. Using twurl you can run
twurl authorize --consumer-key [your API token] --consumer-secret [your API secret]
This will then provide a URL you should open in your browser. Authenticate this to your secondary account and type the PIN into your terminal. The account token and secret will be placed in a hidden file called .twurlrc in your home directory, and you can use them for your bot in the same way you’re currently using your main account tokens.
You can use another utility called tw-oob-oauth-cli to do the same thing. This is a bit easier as you don’t need to install Ruby, and can just download a Windows binary. You’ll want to rename the binary with a .exe extension.
tw-oob-oauth.exe --key [your API token] --secret [your API secret]
This will output the account token and secret on the terminal after you’ve been through the web flow.

To authenticate via Tweetinvi you can follow the guide here : https://linvi.github.io/tweetinvi/dist/authentication/authentication.html
var appClient = new TwitterClient("CONSUMER_KEY", "CONSUMER_SECRET");
// Start the authentication process
var authenticationRequest = await appClient.Auth.RequestAuthenticationUrlAsync();
// Go to the URL so that Twitter authenticates the user and gives him a PIN code.
Process.Start(new ProcessStartInfo(authenticationRequest.AuthorizationURL)
{
UseShellExecute = true
});
// Ask the user to enter the pin code given by Twitter
Console.WriteLine("Please enter the code and press enter.");
var pinCode = Console.ReadLine();
// With this pin code it is now possible to get the credentials back from Twitter
var userCredentials = await appClient.Auth.RequestCredentialsFromVerifierCodeAsync(pinCode, authenticationRequest);
// You can now save those credentials or use them as followed
var userClient = new TwitterClient(userCredentials);
var user = await userClient.Users.GetAuthenticatedUserAsync();
Console.WriteLine("Congratulation you have authenticated the user: " + user);

Related

Getting claims using MSAL

I am using Microsoft.Identity.Claim library to conenct to azure and authenticate user.
My first idea was to use AcquireTokenByIntegratedWindowsAuth method but that requires few days until network administrator people investigate how to enable single sign-in option and change that user are now "federated" and not "managed. So I now switched to AcquireTokenInteractive method because chances are that ure will be logged in, so he will just need to choose account from automatically opened browser and that's it. No big deal.
And this works:
string clientId = "xxx";
var tenantId = "yyy";
string[] scopes = new string[] { "User.Read", "User.ReadBasic.All"};
AuthenticationResult result;
var app = PublicClientApplicationBuilder.Create(clientId)
.WithRedirectUri("http://localhost")
.WithAuthority(AzureCloudInstance.AzurePublic, tenantId).Build();
try
{
result = await app.AcquireTokenInteractive(scopes)
.ExecuteAsync();
}
catch (MsalUiRequiredException) //see all possibl exceptions!
{
However, I don't receive claims inside token.
My idea is to send this token to server, then validate it, and if sucessfull create user in database and then use my own authenication mechanism I use for other users (that are not part of domain, completely separate user).
But I don't want all users from domain have access to this app.
So I would like to get claims, roles...
How to get claims, using this or any other lib given user email, or some other unique data?
Here I summarize all of the steps you may need to follow:
1. You need to register a app in azure ad for your service app, you can refer to this document
2. Then you need to register another app in ad as the client app, you can follow the steps in this document
3. After that, you need to do the steps in this document which I already provided in comments. Do it in the service app but not client app.
4. Then you can get the access token with your code and check the claim roles. Please note, do not add microsoft graph permissions into scopes in your code. You need to add api://<the client id of the registered app for service app>/.default into scopes.
5. Now you can find the claim roles in your access token.

Azure.Authenticate with interactive user login (Microsoft.Azure.Management.Fluent)

I used to manage Azure resources an old preview version. The authentication worked something like this:
// Authorize
this.AuthenticationResult = this.Authorize();
this.Credentials = new TokenCloudCredentials(config.SubscriptionId, this.AuthenticationResult.AccessToken);
this.ResourceManagement = new ResourceManagementClient(this.Credentials, new Uri(config.ManagementBaseUrl));
That would pop up and interactive user login window. I'd like to do the same with the new fluent nuget package (Microsoft.Azure.Management.Fluent version="1.0.0")
Azure.Authenticate(???)
This seems to be the best documentation of the authentication method: https://github.com/Azure/azure-sdk-for-net/blob/Fluent/AUTH.md
But it only covers options that will store credentials on the HDD which I'd like to avoid. So that whatever user is using my program is needed to login.
So in summary: How do I authenticate using an interactive user login with the latest Azure management API?
According to SDK source code, there is no interactive user login currently.
credentialsCache[adSettings.TokenAudience] = await UserTokenProvider.LoginSilentAsync(
userLoginInformation.ClientId, TenantId, userLoginInformation.UserName,
userLoginInformation.Password, adSettings, TokenCache.DefaultShared);
But it only covers options that will store credentials on the HDD which I'd like to avoid. So that whatever user is using my program is needed to login.
To avoid storing credentials on the HDD , if no interactive user login is accepted we could use Login Slient model with username and password.
var credentials = new AzureCredentials(new UserLoginInformation { ClientId = "Azure client Id",UserName = "username",Password = "Password"}, "tenant Id", AzureEnvironment.AzureGlobalCloud); //AzureChinaCloud,AzureGermanCloud,AzureUSGovernment
var azure = Azure
.Configure()
.Authenticate(credentials)
.WithDefaultSubscription();
Fluent libraries does not support interactive login. If your project targets .Net Core then you can use Device Flow authentication, but that will require you to pop-up to the caller information received from Azure AD
Source code in Fluent Repo

Azure AD: user_interaction_required issue when authenticating a native application

I have Exchange Online from Office 365 with a mailbox and I need to access this mailbox with my console C# application that uses Managed EWS. The requirement is that the console application should use OAuth authentication to access the Exchange Online.
I have Azure AD set up, and created an application there, received clientid and redirect uri. I have given full permissions to the application - please have a look at the screenshot below:
I'm using Active Directory Authentication Library for .NET (latest version from NuGet) to issue a token, but having a problem to get it running...
My code is:
AuthenticationContext authenticationContext = new AuthenticationContext("https://login.windows.net/rsoftgroup.onmicrosoft.com", false);
AuthenticationResult authenticationResult = null;
try
{
var authenticationTask = authenticationContext.AcquireTokenAsync(
"outlook.office365.com",
"c4fa7d60-df1e-4664-a8f8-fb072d0bb287",
new Uri(redirectUri),
new PlatformParameters(PromptBehavior.Never)
);
authenticationTask.Wait();
authenticationResult = authenticationTask.Result;
exchangeService.Credentials = new OAuthCredentials(authenticationResult.AccessToken);
}
catch (AdalException)
{
// Exception occured on the authentication process.
}
I get AdalException with message: "user_interaction_required: One of two conditions was encountered: 1. The PromptBehavior.Never flag was passed, but the constraint could not be honored, because user interaction was required. 2. An error occurred during a silent web authentication that prevented the http authentication flow from completing in a short enough time frame"
Can somebody help me how to solve it?
I need the OAuth authentication to work without user interaction, as this will be a command line application...
Any suggestions highly appreciated.
Your application still needs to authenticate as some user, currently if you look at your code you don't authenticate because of PromptBehavior.Never and you don't specify any user-credentials and use the implicit auth flow eg http://www.cloudidentity.com/blog/2014/07/08/using-adal-net-to-authenticate-users-via-usernamepassword/
For a standard Console apps where you are going to authenticate (eg ask for credentials when the app is run) I would use out of band call urn:ietf:wg:oauth:2.0:oob (you then don't need a redirection endpoint) and set your code to prompt eg
AuthenticationContext ac = new AuthenticationContext("https://login.windows.net/Common");
var authenticationTask = ac.AcquireTokenAsync(
"https://graph.windows.net",
"5471030d-f311-4c5d-91ef-74ca885463a7",
new Uri("urn:ietf:wg:oauth:2.0:oob"),
new PlatformParameters(PromptBehavior.Always)
).Result;
Console.WriteLine(authenticationTask.AccessToken);
When you run the Console app windows and the ADAL library will handle the plumbing and show the correct authentication prompts and get the Token back and you get the benefits of reduce attack surface over prompting for the credentials yourself in your code (or as parameters etc)
As Venkat comments suggests if you don't need to use EWS (eg no existing code base investment etc) then using the REST endpoints maybe a better solution if your building a daemon type application as you can take advantage of this type of auth flow eg https://blogs.msdn.microsoft.com/exchangedev/2015/01/21/building-daemon-or-service-apps-with-office-365-mail-calendar-and-contacts-apis-oauth2-client-credential-flow/

This API call requires a valid app_id asp.net c# - facebook

I want to post messages in my friends wall using a program. I will post the message using my asp.net application. I tried facebook's graph api. the problem is every time I have to use facebook provided login dialog to get the access token which requires manually enter username and password. Therefore I created a facebook app and obtained appid and app secret string. I am trying the below code to post a message in my wall first. I am getting the below exception.
var fb = new Facebook.FacebookClient();
dynamic tokenInfo =
fb.Get(
String.Format(
"/oauth/access_token?client_id={0}&client_secret={1}&grant_type=client_credentials",
"1234567890",
"2bebebdf4709xxxxxxxxxxxxxxx"));
fb.Post("/100006xxxxxx/feed", new { message = "My Message" });
Error :
This API call requires a valid app_id
Your friend must authorize your app and they need to grant the "publish to feed" privilege to your app. To get this going, you need to have the user authorize your app via "Facebook Connect". Use Facebook Connect to trigger the "authorize your app" process. Once the app is authorized, the facebook api should recognize that your friend is logged into facebook (facebook api uses cookies to know that the user is logged into FB or not). Only then will issuing this command work. Hope this helps.
var fb = new FacebookClient(acctocken);
var args = new Dictionary<string, object>();
args["Message"] = "Hai Dear";
fb.PostAsync("[friend id]/feed", args);
Hope Its Help You

DropNet DropBox login, how to do it programmatically in a console application?

Question:
I'm using a DropBox csharp API from here:
https://github.com/dkarzon/DropNet
From the Unit tests, and the only working sample from here
https://github.com/dkarzon/DropNet/blob/master/DropNet.Samples/DropNet.Samples.Web/Default.aspx.cs
I figured that it works like this:
DropNet.DropNetClient client = new DropNet.DropNetClient(strApiKey, strAppSecret);
DropNet.Models.UserLogin login = client.GetToken();
client.UserLogin = login;
var accountInfo = client.AccountInfo();
str = accountInfo.quota_info.quota.ToString();
The probem is, it throws an exception on accountinfo. (System.Net.HttpStatusCode.Unauthorized)
Everything before works fine, I get the login (usertoken & usersecret) .
I think my problem is this part of the sample application:
var url = _client.BuildAuthorizeUrl(Request.Url.ToString() + "?dropboxcallback=1");
Response.Redirect(url);
Where it redirects to dropbox for a login...
I don't have a web application, so I have no URL...
What I have is a console application, that should make a backup of my database every evening automatically as a service, for which it certainly is very bad requiring a webbrowser and a user which has to type in email/username + password.
How can I do a login by directly supplying the hardcoded username and password ?
If I use the sample application, then it works, but that requires typing in the username and password on the web, and that sucks big time for a console application...
As far as I know from other API's (facebook, google, stack exchange etc.) you'll have to redirect your user to a webpage of Dropbox, where it will grant permissions to you to use it's account to perform things.
So in general it is not possible to achive this without a webbrower. Otherwise you'll have to perform really dirty hacks to hack arround the permission system of dropbox.
Please have a look at "OAuth 2.0 authorization flow" on google.
Here's a diagram I found at Yahoo which show's how it works:
For uisng the DropnetClient's 4 argument constructor also we need to build web based url and allow the user to authenticate his account this is compusory thing, accesstoken will generate after the user hit allow button in authentication process
As GameScripting explained the Dropbox API uses oauth which requires user login through the dropbox website to authenticate the access tokens.
Checkout the documentation here: http://dkdevelopment.net/what-im-doing/dropnet/ for the 3 step process.
What sort of application are you building? Normal process is to load a browser control inside the application and navigate to the login URL with it.
Also have a look at the sample Windows Phone app to give you an idea of how this process works: https://github.com/dkarzon/DropNet/blob/master/DropNet.Samples/DropNet.Samples.WP7/MainPage.xaml.cs
Instead of hardcoding the username and password, you can hardcode the OAuth access token.
First, create a simple program (using the same app key) that follows the standard browser-based authorization flow. Then use it to authorize the app with the desired user. This will give you an OAuth access token (a "token" and "token secret") associated with that user and your app key.
Then, in your service-style application, just hardcode the OAuth access token (using DropNetClient's 4-argument constructor).
It is possible, using SharpBox - tested, works.
One needs to acquire the AccessToken as a one-time-action manually, then after that, one can omit the login page and use the saved AccessToken.
http://www.jayway.com/2012/02/06/unboxing-dropbox-and-sharpbox-2/
The magic line is:
Globals.DropBox.Token = AppLimit.CloudComputing.SharpBox.StorageProvider.DropBox.DropBoxStorageProviderTools
.ExchangeDropBoxRequestTokenIntoAccessToken(
Globals.DropBox.config
, Globals.DropBox.AppKey, Globals.DropBox.AppSec
, Globals.DropBox.requestToken
);

Categories

Resources