Get Google user name when using OAuthWebSecurity in ASP.NET MVC 4? - asp.net-mvc

I've created a standard boilerplate ASP.NET MVC 4 Internet project. When using OAuthWebSecurity to enable my web site to do social login with Facebook, I see how I can access the Facebook user name in the ExternalLoginCallback() action in the AccountController by accessing the AuthenticationResult's ExtraData:
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication( Url.Action( "ExternalLoginCallback", new { ReturnUrl = returnUrl } ) );
var facebookName = result.ExtraData["name"];
When logging in with Google, however, ExtraData contains only "email". Is it possible to get the Google user name? Am I missing a configuration tweak somewhere?

Found my answer here: Plugging custom OAuth/OpenID providers. This has been a known issue since August 2012 and as yet (DotNetOpenAuth.AspNet 4.2.2.13055, April 2013) has not been fixed.
The workaround is to write your own Google provider, and the blog post above includes a complete working example. It is then a simple matter to get the Google user name:
var googleName = result.ExtraData["firstName"] + " " + result.ExtraData["lastName"];

Related

Get Customer Resource Id with Multi Tenant OAuth on Microsoft Dynamics

I want our my users who are using online Microsoft dynamics to give us access to their account through OAuth2. To be clear, my users live in their own tenants and NOT part of my tenant.
So I registered an Azure AD application and made it multi-tenant but the authorize URL required the resource id which is the exact customer URL on MS Dynamics. like
https://{orgid}.crm.dynamics.com
but I do not want the user to enter their URL manually. I want to automatically figure out their resource id during the OAuth process and complete the process.
how can I do so?
Btw, I am not using C# and I would appreciate it if the HTTP calls could be provided.
Recently I have been working/wrestling with some multi-tenant web apps that need to access D365 via OAuth2. While I do not claim to have mastered it, I have gotten a few such apps working.
Here are some thoughts for you:
I have not attempted to put the tenantId into the CRM url. To construct the CRM url I use the org "url name", which you can get using the below code.
This code assumes that you've put the base URL into the appSettings node of the web.config:
<add key="ida:OrganizationHostName" value="https://{0}.crm.dynamics.com" />
Then this code might should help you along:
private string getOrgName(string user)
{
var a = user.IndexOf('#');
var b = user.IndexOf('.');
return user.Substring(a + 1, b - (a + 1));
}
var signedInUserID = ClaimsPrincipal.Current.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier).Value;
var tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
var userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var OrganizationHostName = ConfigurationManager.AppSettings["ida:OrganizationHostName"];
var organizationName = getOrgName(User.Identity.Name);
var resource = string.Format(OrganizationHostName, organizationName);
Where I have seen the tenant Id used is when establishing the auth context
var authContext = new AuthenticationContext($"https://login.windows.net/{tenantID}");
As shown above you can get it from the ClaimsPrincipal, but I think my apps are all now using https://login.windows.net/common rather than appending the tenantId.
If you want to get fancy you can query the Discovery service to see what orgs a user has access to. For me, Colin Vermander's article was the key to getting that working.

A simple ASP .NET MVC API controller using roles

I wrote a web application using ASP .NET MVC and authorization system by default. I configured IdentityRole and input through external providers. Using the current database I have created my data context. Now I want to write a Xamarin.Android app and connect to my database, I want a simple API. But the feature that you want to access this API was only available to user with a certain role. The API is really very simple and therefore do not want to add to the draft WCF or WebAPI project. How to do it best?
First, you don't need a separate project to use Web Api; you can use both MVC and Web Api in the same project. For one off endpoints for things like in-site AJAX requests, just creating MVC actions that return JSON or XML would be fine, but if you're talking about a true API, even if it's fairly simplistic, I'd say go Web Api.
You'd protect your Web Api actions much the same as you would your MVC actions, using the [Authorize] attribute. If you need to restrict by role, you just pass a role(s) to that. However, the big difference here, especially if you're serving a mobile app, is that you'll need pass the authorization along with the request. That's generally accomplished using the Authorization header along with a bearer token. Basically, you would need to set up an endpoint that signs a user in and returns a token. Then, each subsequent request that needs authorization includes that token in the header.
I want to finish and to fully answer this question and close this topic. I've been searching for how to add the ability for a mobile client to connect to an existing site on ASP.NET MVC. In my search, I came across a great article Justin Hyland on March 2, 2014
In principle, everything in this article is well and clearly written, but I want to make a tiny contribution for clarity.
Under Setup WebAPIConfig stated that the need
added in the following code to the WebApiConfig Register method
But if we consider the case ASP.NET MVC we don't have such file. It's all very simple, you just need such a file to create the folder App_Start. The contents of the file can be left exactly as it is in the article.
To get rid of the bugs which will inevitably appear we need to install two nuget package: Microsoft.AspNet.WebApi and Microsoft.AspNet.WebApi.Owin.
Excellent! Now we can turn to the method to obtain the token and then adding the token to the query we can get the needed data closed by the attribute [Authorize].
A small remark. If You need to access a method which is closed for a specific role that to the Authenticate method from the article should add a few lines of code. Immediately after the line:
identity.AddClaim(new Claim(ClaimTypes.Name, user));
add the line:
identity.AddClaim(new Claim(ClaimTypes.Role, role));
where role you can get the following, for example:
var userIdentity = UserManager.FindAsync(user, password).Result;
var role = RoleManager.FindById(userIdentity.Roles.First().RoleId).Name;
User and password you have to send a request.
I also want to give an example of code which will send request and receive response. To not have to look for and immediately start coding.
async Task<string> GetToken(string userName, string password)
{
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>( "user", userName ),
new KeyValuePair<string, string> ( "password", password )
}
);
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.PostAsync(APP_PATH + "/Authenticate", content);
var result = await response.Content.ReadAsStringAsync();
return result;
}
}
async Task<string> GetUserInfo(string token)
{
using (var client = CreateClient(token))
{
var response = await client.GetAsync(APP_PATH + "/ValidateToken");
return await response.Content.ReadAsStringAsync();
}
}
HttpClient CreateClient(string accessToken = "")
{
var client = new HttpClient();
if (!string.IsNullOrWhiteSpace(accessToken))
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}
return client;
}
All have only to call the appropriate methods in the correct order. I hope that is useful to someone.
P.S.
If You create a new project in Visual Studio to get this functionality you just need to tick:

How do I work with Google Analytics oAuth in a WebAPI?

I am building an extension for open source ASP.NET CMS Umbraco where I want to fetch the analytic's from the user's account once they have authorised via oAuth.
The example MVC 4 snippet over on the Google API .NET wikiw page for oAuth seems to only work with a controller and not a WebAPI controller as far as I can tell, is this right?
AuthorizationCodeMvcApp(this, new AppFlowMetaData()).AuthorizeAsync(cancellationToken);
The first parameter in the example expects it to be a regular MVC Controller
https://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis.Auth.Mvc4/OAuth2/Mvc/AuthorizationCodeMvcApp.cs
So my question is really, how do I work with oAuth with a WebAPI in mind, as I want to return stats back from the API as JSON from the WebAPI so I can use a client side library such as AngularJS to bind the JSON returned to the HTML view?
I would love for any ideas, feedback or suggestions on how I could solve this please.
Thanks,
Warren :)
I have looked into your problem and the i have tested the service account solution. It's tricky to setup but when it runs it works.
This is the code I used in a webapi controller :
String serviceAccountEmail = "805395301940-cu3nhkuqi4ipa3453o276bar5u2e70lq#developer.gserviceaccount.com";
var cert = HttpContext.Current.Server.MapPath("/key.p12");
var certificate = new X509Certificate2(cert, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { AnalyticsService.Scope.Analytics }
}.FromCertificate(certificate));
var service = new AnalyticsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential
});
//var ga = service.Data.Ga.Get("ga:31335471", "2013-01-01", "2013-01-31", "ga:visits");
// Not Working Currently in Beta
//var ga = service.Data.Realtime.Get("ga:31335471", "ga:activeVisitors");
var ga = service.Management.Profiles.List("~all", "~all");
return ga.Execute();

Login with Twitter account in Asp.net MVC

I am trying to let users login with their twitter acount for my web site. I am using Tweetsharp library.
Now the problem is: after i enter twitter user name and password, the twitter page shows me a number like "7825362101" and says to enter this number into the concern web site.
I have no clue what shall my website do with that number!! I already have 'consumer key' and 'consumer secret' while i created the app in twitter.
I hope someone can help me!!
cheers
You don't need to do anything with that number if you are using the Tweetsharp in a web application. Just do the following in your controller, this will return a list of tweets from the public timeline:
private readonly string _consumerKey = "yourconsumerkey";
private readonly string _consumerSecret = "yourconsumersecretkey";
public ActionResult Index()
{
var service = new TwitterService(_consumerKey, _consumerSecret);
IEnumerable<TwitterStatus> model = service.ListTweetsOnPublicTimeline();
return View(model);
}
Spring.NET Twitter provides a sample for ASP.NET MVC.
http://www.springframework.net/social-twitter/
I think something is missing on redirect to Twitter authentication.Twitter API not getting all required values. So just follow the below link to authenticate your web application using Tweetsharp library
http://tutorialslink.com/Articles/Login-with-Twitter-account-in-Aspnet-MVC/24

ASP.NET MVC Facebook

I am trying to do a seemingly simple thing, but having trouble accomplishing it. I am trying to automate the posting on my Facebook wall. Basically I have a ASP.NET MVC website that I post updates on, and I want to automatically submit the post to my wall.
I see a lot of stuff on FB Connect and getting data, I just want to post.
Thanks for any help or guidance.
UPDATE: Just trying to resurrect and be a little more clear in my description as I am not getting anywhere.
I have a page that I want with a text box and a button. When I submit the form I want the message to post to my Facebook wall. I thought it was Facebook Connect, but I am getting no where as to how to automatically authenticate myself and post to my wall.
I would like to use C# rather than JavaScript.
private const string ApplicationKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
private const string SecretKey = "XXXXXXXXXXXXXXXXXXXXXXXXXX";
private Facebook.Rest.Api _facebookAPI;
private Facebook.Session.ConnectSession _connectSession;
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection form)
{
_connectSession = new Facebook.Session.ConnectSession(ApplicationKey, SecretKey);
if (_connectSession.IsConnected())
{
_facebookAPI = new Facebook.Rest.Api(_connectSession);
string response = _facebookAPI.Stream.Publish("This is a generated test");
}
return View();
}
}
The IsConnected() is returning false.
Any help is appreciated.
This code was right, the problem was that I had not added my application to my profile. Dumb miss, but my thought is that the whole thing is poorly documented. I have another issue with offline access, but that is for a different post.
string apiKey = "XXXXXXXXX";
string apiSecret = "XXXXXXXXXXXX";
Facebook.Session.ConnectSession._connectSession = new Facebook.Session.ConnectSession(apiKey, apiSecret);
if (_connectSession.IsConnected)
{
Facebook.Rest.Api api = new Facebook.Rest.Api(_connectSession);
string response = api.Stream.Publish("Test", null, null, null, api.Users.Session.UserId);
}
It could be that you tested your Website on your localhost. The Facebook Cookie is not written out, when you test your Website on localhost. See this link http://forum.developers.facebook.net/viewtopic.php?pid=247332
This might solve your problem:
Add "127.0.0.1 localhost.local" to your file
Update your FB application Connect settings to use "http://localhost.local/" URL and "localhost.local" domain.
Create an IIS Web site on port 80 with the name "localhost.local". I had to stop my default web site, which is also on port 80
Update my Visual Studio 2010 web application to use IIS with the "http://localhost.local/" url.
To see cookies, make sure to install FireCookies, along with FireBug.

Resources