How should I authorize twitter on a clients website? - twitter

I am using Linq-to-twitter on a website I am working on at the moment. All I want to do is grab my clients latest tweets and list them on the site.
I have created an app in my own twitter account for the client.
I cannot work out if I should use Single User Authentication or Application Authentication.
On the face of it, Application Authentication seems to be the right one but I am unsure about the process. Do I setup a page where my client can go to authorize the app and then store the token? It is unclear in documentation if that token ever expires.
Or should I be using Single User Authentication and use the token generated in my own twitter account? Is there any downside to that or security risk if the site gets passed off to someone else to work on and they get the token? (I did set application to read only but its my first time using twitter so I am not sure)
Any advice appreciated as I am rather confused.

Application Authentication is attractive because it gives you more requests. However, not all queries allow application authentication because the query is made on behalf of a user, whereas application authentication is non-user specific. If you have a query that is on behalf of a user (as if that user logged in), single-user authorization would be appropriate.
LINQ to Twitter has demos, including ASP.NET WebForms or MVC, in the downloadable source code. Those demos assume that the user is going through the OAuth authorization sequence. However, if you use application or single user authorization, all you need to do is load credentials and use the TwitterContext without taking the user through that process. The Console Demos have examples of each type of authorization.
Here's an example of instantiating an ApplicationOnlyAuthorizer:
var auth = new ApplicationOnlyAuthorizer()
{
CredentialStore = new InMemoryCredentialStore
{
ConsumerKey = ConfigurationManager.AppSettings["consumerKey"],
ConsumerSecret = ConfigurationManager.AppSettings["consumerSecret"]
},
};
And here's an example of a SingleUserAuthorizer:
var auth = new SingleUserAuthorizer
{
CredentialStore = new SingleUserInMemoryCredentialStore
{
ConsumerKey = ConfigurationManager.AppSettings["consumerKey"],
ConsumerSecret = ConfigurationManager.AppSettings["consumerSecret"],
AccessToken = ConfigurationManager.AppSettings["accessToken"],
AccessTokenSecret = ConfigurationManager.AppSettings["accessTokenSecret"]
}
};
All of the credentials come from the Application's page in the Twitter account.
In either case, the credentials are loaded, so you don't need to take the user through the OAuth process and just create a new TwitterContext, like this:
await auth.AuthorizeAsync();
var twitterCtx = new TwitterContext(auth);
Tokens don't expire. So, you can reload the same tokens every time you instantiate the authorizer.
Here's one approach you can use to minimize security risk with sharing credentials. Use the customer's user account or create a new user account on behalf of the customer. Then create an application under the customer's account and use those credentials. You can give the customer access to the new account and they will be responsible for their own credentials.

Related

How do you implement the new DocuSign OAuth2.0 SOBO using eSignature SDK?

I'm in the process of converting an internal C# API that uses a legacy SOBO integration to one that uses OAuth 2.0 as required by DocuSign. The legacy application makes all requests to DocuSign using DocuSign credentials of an application user (a non-person) and injects SOBO data (email address) in the appropriate header when we need to generate an embedded sending URI and have it appear that the envelope was sent by a real person without using their credentials.
I have successfully converted another (non-SOBO) internal API using JWT grant, but I do not know how replicate the SOBO dependent workflow. Have read Matt King's article "From the Trenches: OAuth 2.0 and the new SOBO", but still a bit confused. I know how to extract userId from email address as mentioned in the article, but not sure what do with it. Similar to my legacy application, I am using a application user to get consent and ask for JWT token without prompting internal users for their consent. Is this still possible using OAuth 2.0?
Happy to help here. Once you've retrieved the user's apiUserName / userId you'll want to add it into the JWT assertion's sub line.
When you go to generate the token, if consent has not been provided by or for the user, our system will send back an error of "Consent_Required." See https://www.docusign.com/blog/developers/oauth-jwt-granting-consent for different methods of granting consent.
For individual consent, the user needs to go to a specific URL containing your clientId, redirectUri, and some additional scopes. If they hadn't previously consented to the scopes in your OAuth request they will be prompted to do this once. You can confirm consent has been applied by having them visit the same link afterwards, which will send them directly to your redirectUri.
Domain consent works a little differently -- you need to have an organization, a claimed domain, and the users you're providing consent on behalf of need to have an email address that is part of that claimed domain.
Happy to connect and walk you through it -- if you can open a ticket at support.docusign.com and in the details request they reach out to me I should be able to have the case transferred and work with you from there.
Regards,
Matt King

Accessing Microsoft Graph API without using login page

I would like to access a user's one drive to upload a document or retrieve a document using Graph API.
I've seen multiple examples over the net which requires using the standard login page for the user to login. You need to get the authorization code from the login page and then use it to get a token, which finally can be used to access a resource like drive.
Am looking for a way to do this without going through the login page. I can have my own login page where I can request user to login.
In short, I want to access drive resource of Graph API using a REST client like Postman (right from authorization to accessing the resource). Is this possible?
Yes, it is possible if you have the right information - all you need to do is to get a delegated access token.
Explanation:
When dealing with access to resources, Microsoft Graph has two levels of access token requirements:
Most methods support Application only tokens, meaning once an OAuth app has consent it can access the resource whenever it wants.
But for some methods, it is not enough (they are too sensitive for an automated process) and require a Delegated token, meaning token which contains both a valid Client and User. You can see in each method documentation which token it requires.
Normally delegated access tokens are the result of the two major OAuth flows which require user interaction (Authorization Code Grant and Implicit Grant) but you can also get them from two other flows: Resource Owner Credentials Grant and On-Behalf-Of Grant, which are both supported by Microsoft.
For a full guide on how to setup everything you need in order to use those flows (including Postman examples) you can look at my article:
Getting Access Token for Microsoft Graph Using OAuth REST API
Yes this is possible. Essentially you grant access application access to Graph API instead of a user.
The documentation for such access is here:
https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_service
You'll still need to a request a bearer token to send with all your REST requests, but the bearer token will be for the application itself and not a user.
I set this up for one of my applications using the Graph SDK for .NET, so if you need specific examples for Graph SDK for .NET let me know.
Although this is possible, it's strongly recommended not to do this for individual user access. The Microsoft Graph only supports OAUTH 2.0 as its authZ protocol, and we recommend that you use the flows within OAUTH where the trusted authority be the one to directly handle login credentials. Allowing application code to provide the forms UI for login credentials would open up the attack vector where your app would have direct access to the user's O365 password, which is not a secure approach.
I've found the documentation is not helpful, especially in terms of trying to acces the Graph API in the application context. But, I managed to get the access token in the context of the application here:
private static async Task<string> AcquireToken()
{
var tenant = "yourtenant.onmicrosoft.com";
var resource = "https://graph.microsoft.com/";
var instance = "https://login.microsoftonline.com/";
var clientID = "YourappID";
var secret = "YourAppSecret";
var authority = $"{instance}{tenant}";
var authContext = new AuthenticationContext(authority);
var credentials = new ClientCredential(clientID, secret);
var authResult = await authContext.AcquireTokenAsync(resource, credentials);
return authResult.AccessToken;
}
Yes, It is possible to access onedrive shared folder with the help of shared url without userlogin.
first you need to get an access token, to hit any microsoft graph API you need access token. follow the link to get access token without user login access token
Encode shared url.
string sharingUrl = "https://onedrive.live.com/redir?resid=1231244193912!12&authKey=1201919!12921!1";
string base64Value = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(sharingUrl));
string encodedUrl = "u!" + base64Value.TrimEnd('=').Replace('/','_').Replace('+','-');
Discovering an endpoint https://learn.microsoft.com/en-us/onedrive/developer/rest-api/concepts/direct-endpoint-differences?view=odsp-graph-online#discovering-an-endpoint
-for OneDrive personal accounts https://api.onedrive.com/v1.0/shares/{shareIdOrUrl}/driveItem?$expand=children
OneDrive for Business and SharePoint
https://graph.microsoft.com/v1.0/shares/{shareIdOrUrl}/driveItem?$expand=children

Getting user information when using OAuth2 - is the following reasonable?

I am creating an API (Restlet, GAE) and implemented OpenId for authentication and OAuth2 to protect access to the API. When testing this from a client web app that I built, everything is fine. When the user hits a part of the web app that wants access to the API, the user is asked to login via OpenId and then is asked to grant access to the web app to grab resources from the API.
However, I noticed that the web app doesn't know who the user is (!). All the web app has is an auth token. Thus, the web app can't say "Hello, username", since it doesn't know who the user is.
With Restlet technology, the authentication is essentially:
// Authentication code
OpenIdVerifier verifier = new OpenIdVerifier(OpenIdVerifier.PROVIDER_YAHOO);
verifier.addRequiredAttribute(AttributeExchange.EMAIL);
Authenticator au = new MyRedirectAuthenticator(getContext(), verifier, null);
While the following handles both authentication and OAuth2 authorization:
// Authentication + OAuth code:
OAuthParameters params = new OAuthParameters("2345678901", "secret2", "http://localhost:8888/v3/", roles);
OAuthProxy local = new OAuthProxy(params, getContext());
Initially I was only using the "Authentication + OAuth" in my web app and the authentication was happening "invisibly" (as mentioned above).
I figured that one way around the "problem" is that if the web app handles the authentication "visibly". So I added the Authentication code to the web app. The flow looks the exact same to the user, but the web app is able to capture the user info (email) and all is fine. There doesn't seem to be any conflict with the "both" code either.
Another way around the problem is to add something to the API that would return the user info associated with an authToken (a la Twitter's verify_credentials).
My question: Is the approach I have taken reasonable? Should I use the Twitter approach instead? Or something completely different? (I am pretty new to all this stuff, so it is hard to figure out if I am choosing a solution that seems to work, only to hit a brick wall later on).
The short answer is that when a client web app gets permission to access OAuth resources on behalf of a user, the client web app isn't supposed to know anything about the user (login, password, etc.). If the client web app wants to know who the user is, it can provide authentication.
I have implemented the above scheme with Restlet and google app engine, allowing the user to authenticate to the resource server via OpenId and also adding Google Authentication for the web client app (just so it can give a "hello" message). All seems fine.

Design for Facebook authentication in an iOS app that also accesses a secured web service

Goal:
Allow a user to authentication with Facebook into an iOS application which requires access to a protected web service that I'm running.
Assumptions:
There is a native authentication (and registration) system in place for those users that opt not to use Facebook for sign in.
Details:
Assume we want to offer the option for a user to sign in with Facebook without creating a separate account/credential for our system.
Because we support our own native auth mechanism (username and password) we have our own user IDs and issue an authentication token that is used for subsequent interactions after the initial credential validation.
I'm surprised that Facebook doesn't have best practices for this in their developer documentation. All the existing documentation is either assuming you are building FB auth into a website, or a standalone mobile app with no service that requires authentication.
Here's my initial thoughts on how this would be designed but want validation on whether it's correct.
Client pops the Facebook iOS Login
UI User signs in with Facebook credentials and gets access token
iOS App passes access token to our server
Our server talks to FB graph API using access token to (a) validate the token and (b) get the FB user ID for that access token.
e.g. Our server would call https://graph.facebook.com/me/?access_token=XYZ which would return profile info in a JSON object
Assuming it's valid, our server extracts the User ID from the JSON object and checks whether the user already has an account. If so, we issue our own auth ticket to client to use for that session. If user doesn't have an account, we create a new one with the Facebook User ID, assign our own unique UserID and issue our auth ticket.
Client then passes auth ticket back on subsequent interactions that need authentication.
This seems like the right approach to me but not sure if I'm missing something insanely basic and going down the wrong (complicated) path.
I just dealt with this myself, and here's the part that bit me:
In your step 5... It's possible for a user to register for an account with you entirely separate from their Facebook ID, right? Then some other time they log in with Facebook.... And you just created them a second account and lost their first one.
There needs to be a way to be logged in to your web service, then log in to facebook, and capture the association between the facebook ID and the local account.
Apart from that, your plan sounds solid.
Update: Facebook has added a doc outlining such a scenario HERE
Use https to transmit the auth token to your server, as stated by Facebook
Sharing of Access Tokens
Our Data Policies explicitly prohibit any sharing of an Access Token
for your app with any other app. However, we do allow developers to
share Tokens between a native implementation and a server
implementation of the same App (ie. using the same App ID) as long as
the transfer takes place using HTTPS.
One problem I can see with this strategy, is that somebody can give you an access token obtained for a different facebook app. As far as I know, there's no way to verify that the access token is for your application, so you'll just go on and use it.
It doesn't sound very harmful, though. Generally people/apps try to protect the access tokens, rather than sharing them.
One possible exploit of this would be, for somebody to create their own site or mobile app, obtain access tokens for their users and try to authenticate them, using your API. If this succeeds (the user is has a facebook account in your site), the malicious site will be able to use your API impersonating the user.
It's a bit of a long shot, but I think it could work.
Edit: It looks like there is a way to validate the access token after all. See the answer by #Daaniel on question Get application id from user access token (or verify the source application for a token).
your solution totally works.
Maybe an alternative: why not just get the email on the client from the initial social service request and send to your web service? The web service could just store the email, and maybe a social_provider as well. I understand that your web service will not be able to validate where the email came from, but isn't there a high-trust relationship between your web service and your client? If there is, seems like you can depend on the email coming from the right place. Someone please let me know what obvious thing I'm missing that makes the email-based approach silly...

Login with FB Connect / Google OAuth in .NET

I'd like to allow my users to login to my website using my login system, or FB Connect or Google Login. I wouldn't want to use big libraries (like dotnetOpenAuth) for only those 2 options - So how should I accomplish this?
Additional question - how should I bind the FB/Google user to my inner user system? I'd like to allow to login using both of them (I could for example login using FB and then login with Google, and still be bound to the same user).
I'm using ASP.NET MVC 2
Thanks!
If you don't like to use big libraries like DotnetOpenAuth you will have to manually implement the OpenID protocol. Here are the specifications you will need to conform to.
This being said, I would recommend you using an existing library. DotnetOpenAuth is the reference library for .NET.
Also a small remark: OpenId and OAuth are different standards and are designed to achieve different things: OpenId is for authentication while OAuth is for authorization.
As far as identifying the same user which could log from different OpenID providers is concerned you will need something to identify them. For example with DotnetOpenAuth when creating an authentication request to the OpenID provider you could require the FullName and the Email:
using (var openid = new OpenIdRelyingParty())
{
var request = openid.CreateRequest(Identifier.Parse(openid_identifier));
request.AddExtension(new ClaimsRequest
{
BirthDate = DemandLevel.NoRequest,
Email = DemandLevel.Require,
FullName = DemandLevel.Require
});
}
and use this information to identify the user within your internal database.
So here's the idea:
You create an internal database table which will contain your site users. At the beginning this table is empty.
A user comes to your site and wishes to use it. He is not yet authenticated so you ask him for his credentials. You provide him the ability to choose his OpenId provider and prepare an authentication request and redirect him to his provider for authentication.
The user authenticates with his provider and is redirected back to your site. At this moment you know his claimed identity and you add the user to your users table. Now the user can always come back to your site and login.
You could provide the possibility to your authenticated users to add another OpenId provider (just like StackOverflow does). The important idea is that the user needs to already be authenticated to your site in order to do this. So he could enter his alternative OpenId provider and get redirected to this provider for authentication. Once he authenticates he is redirected back to your site and because he was already authenticated to your site you could add to the users table his alternative OpenId provider.
The controller action which will handle the redirect from the OpenId provider should check whether the user is already authenticated to your site and if not authenticate him using FormsAuthentication.GetAuthCookie and passing the claimed identity. If the claimed identity doesn't exist in your internal users table you need to add it. If the user is already authenticated to your site it means that he is adding an alternative OpenId provider to his profile, so you would update your users table and add the new provider to it.

Resources