I am building user authentication based on Azure Active Directory using OpenId Connect.
I can successfully log into my website by using my account in AAD.
After I'm logged in, I would like to retrieve my account information via the AAD graph API.
I can get the user ID via the ClaimsIdentity:
ClaimsIdentity identity = this.User.Identity as ClaimsIdentity;
string userID = identity.GetUserId();
And I can get user information via the graph API:
public IUser GetProfileById(string userID)
{
ActiveDirectoryClient client = GetAadClient();
var user = client.Users.Where(x => x.ObjectId == userID).ExecuteSingleAsync().Result;
return user;
}
However, the user ID that is stored on the ClaimsPrincipal does not seem to be the Object ID in AAD, so I'll need to find some other way to retrieve the user information. Another option might be to find the user based on the email address, but I can't find out how to do that either.
Any help or suggestions will be appreciated.
Thanks to #juunas I found out the type:
ClaimsIdentity identity = this.User.Identity as ClaimsIdentity;
string objectID = identity.Claims.FirstOrDefault(x => x.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
Then the object ID can be used to obtain the user information via the AAD graph API.
Here's a quick answer for anyone else still looking.
public void GetUserFromAD(GraphServiceClient gsc)
{
try
{
ClaimsIdentity identity = ClaimsPrincipal.Current.Identity as ClaimsIdentity;
string objectID = identity.Claims.FirstOrDefault(x => x.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
var user = gsc.Users[objectID].Request().GetAsync().Result;
}
catch(Exception ex)
{
// do something.
}
}
Note you can use direct lookup using Users[objectid] rather than enumerating through the result list.
Can you please show me some c# example for Authorizing and getting instances using Google Compute engine? When I tried authorizing through some of the code that are out there it is always popping up the gmail login page. Is it necessary to use my own login username or can I use the username of the person who created the vm instances on the google cloud platform?
Can you please show me some c# example for Authorizing and getting instances using Google Compute engine?
The following code can help.
private async Task<List<Instance>> GetAllInstances()
{
List<Instance> instanceResult = new List<Instance>();
var service = assign GooglecomputeServiceObject;
InstancesResource instancesResource = new InstancesResource(service);
InstanceList instanceList = await instancesResource.List(your ProjectId, specify_Zone).ExecuteAsync();
if (instanceList.Items != null)
foreach (var item in instanceList.Items)
{
instanceResult.Add(item);
}
return instanceResult;
}
I'm trying to build an API (using ASP.NET WebApi) that will be consumed by a native mobile app for a school project. (I'm not concerned about/developing the mobile app, this responsibility falls on a different member)
I'm at a point where I need to implement a token based Facebook login. There are a lot of tutorials available for how to implement this feature for browser based apps (this is pretty straight forward and most of it comes inbuilt), but I don't think I follow how this would work with native apps. What I don't understand is how the redirects would work?
According to this link, nothing needs to be handled specifically by my server. And I don't think I understand how this would work? How would the tokens from Facebook be handled?
Also, what part of token handling should I implement, I couldn't really find good documentation for WebApi external login authentication.
Anyway, if someone could point me to the exact flow of token exchanges that happen and what is implemented by default by ASP.NET, that would be super helpful.
Also, the biggest point of confusion for me is I don't understand how the token returned by Facebook will be handled.
I assume the token will be returned to the client (mobile app), how do I get access to it on my server?
How do I create a local token from facebook's token?
Is this all done internally/auto-magically by ASP.NET?
I'm sorry if this is something I should've been able to figure out. I did do quite a bit of research and I found myself drowning in (related & unrelated) information. I don't think I even know how to search for the information I need.
Some links I've read:
Claims And Token Based Authentication (ASP.NET Web API)
Token Based Authentication using ASP.NET Web API 2, Owin, and Identity
ASP.NET Web API 2 external logins with Facebook and Google in AngularJS app
I had to do pretty much the same thing for an application I was working on. I also had a lot of trouble finding information about it. It seemed like everything I found was close to what I needed, but not exactly the solution. I ended up taking bits and pieces from a bunch of different blog posts, articles, etc. and putting them all together to get it to work.
I remember two of the links you posted "Claims and Token Based Authentication" and "ASP.NET Web API 2 external logins with Facebook and Google in AngularJS app" as being ones that had useful information.
I can't give you a comprehensive answer since I don't remember everything I had to do, nor did I even understand everything I was doing at the time, but I can give you the general idea. You are on the right track.
Essentially I ended up using the token granted by Facebook to confirm that they were logged into their Facebook account, created a user based on their Facebook user ID, and granted them my own bearer token that they could use to access my API.
The flow looks something like this:
Client authenticates with Facebook via whatever method (we used oauth.io)
Facebook returns them a token
Client sends token information to the registration endpoint of my WebApi controller
The token is validated using Facebook's Graph API, which returns user info
A user is created in the database via ASP.NET Identity with their Facebook user ID as the key
Client sends token information to the authentication endpoint of my WebApi controller
The token is validated using Facebook's Graph API, which returns user info
The user info is used to look up the user in the database, confirm they have previously registered
ASP.NET Identity is used to generate a new token for that user
That token is returned to the client
Client includes an Authorization header in all future HTTP requests with the new token granted by my service (ex. "Authorization: Bearer TOKEN")
If the WebApi endpoint has the [Authorize] attribute, ASP.NET Identity will automatically validate the bearer token and refuse access if it is not valid
There ended up being a lot of custom code for implementing the OAuth stuff with ASP.NET Identity, and those links you included show you some of that. Hopefully this information will help you a little bit, sorry I couldn't help more.
I followed this article. The flow is basically this
The server has the facebook keys just like with web login
The app asks for available social logins and displays buttons (you can hardcode this I guess)
When a button is pressed the app opens a browser and sets the URL to the one related to the specified social login. The ASP.NET then redirects the browser to facebook/google/whatever with the appropriate Challenge
The user might be logged in or not and might have given permission to your app or not. After he gives the permissions facebook redirects back to the provided callback URL
At that point you can get the external login info from the SignInManager and check if the user already exists and if you should create a new account
Finally a token is generated and the browser is redirected to a URL in which the token is placed. The app gets the token from the URL and closes the browser. Uses the token to proceed with API requests.
Honestly I have no idea if this approach is legit...
The code of the action buttons should redirect to:
public async Task<IEnumerable<ExternalLoginDto>> GetExternalLogins(string returnUrl, bool generateState = false)
{
IEnumerable<AuthenticationScheme> loginProviders = await SignInManager.GetExternalAuthenticationSchemesAsync();
var logins = new List<ExternalLoginDto>();
string state;
if (generateState)
{
const int strengthInBits = 256;
state = RandomOAuthStateGenerator.Generate(strengthInBits);
}
else
{
state = null;
}
foreach (AuthenticationScheme authenticationScheme in loginProviders)
{
var routeValues = new
{
provider = authenticationScheme.Name,
response_type = "token",
client_id = Configuration["Jwt:Issuer"],
redirect_uri = $"{Request.Scheme}//{Request.Host}{returnUrl}",
state = state
};
var login = new ExternalLoginDto
{
Name = authenticationScheme.DisplayName,
Url = Url.RouteUrl("ExternalLogin", routeValues),
State = state
};
logins.Add(login);
}
return logins;
}
The code for the callback action:
[Authorize(AuthenticationSchemes = "Identity.External")]
[Route("ExternalLogin", Name = "ExternalLogin")]
public async Task<IActionResult> GetExternalLogin(string provider, string state = null, string client_id = null, string error = null)
{
if (error != null)
{
ThrowBadRequest(error);
}
if (!User.Identity.IsAuthenticated)
{
return new ChallengeResult(provider);
}
string providerKey = User.FindFirstValue(ClaimTypes.NameIdentifier);
var externalLoginInfo = new ExternalLoginInfo(User, User.Identity.AuthenticationType, providerKey, User.Identity.AuthenticationType);
if (externalLoginInfo.LoginProvider != provider)
{
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
return new ChallengeResult(provider);
}
var userLoginInfo = new UserLoginInfo(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey, externalLoginInfo.ProviderDisplayName);
User user = await UserManager.FindByLoginAsync(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey);
if (client_id != Configuration["Jwt:Issuer"])
{
return Redirect($"/#error=invalid_client_id_{client_id}");
}
if (user != null)
{
return await LoginWithLocalUser(user, state);
}
else
{
string email = null;
string firstName = null;
string lastName = null;
IEnumerable<Claim> claims = externalLoginInfo.Principal.Claims;
if (externalLoginInfo.LoginProvider == "Google")
{
email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
firstName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value;
lastName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value;
}
else if (externalLoginInfo.LoginProvider == "Facebook")
{
email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
string[] nameParts = claims.First(c => c.Type == ClaimTypes.Name)?.Value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
firstName = nameParts?.First();
lastName = nameParts?.Last();
}
//some fallback just in case
firstName ??= externalLoginInfo.Principal.Identity.Name;
lastName ??= externalLoginInfo.Principal.Identity.Name;
user = new User
{
UserName = email,
Email = email,
FirstName = firstName,
LastName = lastName,
EmailConfirmed = true //if the user logs in with Facebook consider the e-mail confirmed
};
IdentityResult userCreationResult = await UserManager.CreateAsync(user);
if (userCreationResult.Succeeded)
{
userCreationResult = await UserManager.AddLoginAsync(user, userLoginInfo);
if (userCreationResult.Succeeded)
{
return await LoginWithLocalUser(user, state);
}
}
string identityErrrors = String.Join(" ", userCreationResult.Errors.Select(ie => ie.Description));
Logger.LogWarning($"Error registering user with external login. Email:{email}, Errors:" + Environment.NewLine + identityErrrors);
return Redirect($"/#error={identityErrrors}");
}
}
private async Task<RedirectResult> LoginWithLocalUser(User user, string state)
{
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
DateTime expirationDate = DateTime.UtcNow.AddDays(365);
string token = user.GenerateJwtToken(Configuration["Jwt:Key"], Configuration["Jwt:Issuer"], expirationDate);
return Redirect($"/#access_token={token}&token_type=bearer&expires_in={(int)(expirationDate - DateTime.UtcNow).TotalSeconds}&state={state}");
}
I am doing some research and can't seem to find a definitive way to query Twitter's API to get a user's tweets on WP8 using C#.
The twitter user isn't my own account and all I want to do is retrieve tweets and not post any tweets.
Do I therefore need to Authenticate myself/my app? Is the TweetSharp library appropriate for my objective?
I used the following example http://code.msdn.microsoft.com/wpapps/Twitter-Sample-using-f36bab75:
if (NetworkInterface.GetIsNetworkAvailable())
{
//Obtain keys by registering your app on https://dev.twitter.com/apps
var service = new TwitterService("abc", "abc");
service.AuthenticateWith("abc", "abc");
//ScreenName is the profile name of the twitter user.
service.ListTweetsOnUserTimeline(new ListTweetsOnUserTimelineOptions() { ScreenName = "the_appfactory" }, (ts, rep) =>
{
if (rep.StatusCode == HttpStatusCode.OK)
{
//bind
this.Dispatcher.BeginInvoke(() => { tweetList.ItemsSource = ts; });
}
});
}
else
{
MessageBox.Show("Please check your internet connestion.");
}
I created a new application user the twitter dev website: https://dev.twitter.com/user/login?destination=home. Once this was set-up, I essentially copied and pasted the keys within the AuthenticateWith and TwitterService methods.
I haven't solved exactly how I shall display the data but, at runtime, I can see data being passed in.
I am trying to retrieve all users in domain but it's never work. I never got any error in my code.
I am adding as reference Google.GData.Apps.dll in my project. I am using Google Apps Provisioning API. I am referring these link https://developers.google.com/google-apps/provisioning/
Code :-
string domain = #"<domain name>";
string subs = #"<Authorization code>";
AppsService appService = new AppsService(domain, subs);
// appService.CreateUser("john.jain","James","anderson","james#1234");
// appService.DeleteUser("Amitesh");
appService.RetrieveAllUsers();
The following works for me - RetrieveAllUsers() returns a UserFeed object containing all users. Note that I am using a different constructor for the apps service (using username/password credentials and not OAuth).
this.appsService = new AppsService(credential.Domain, credential.Username, credential.Password);
UserFeed userFeed = this.appsService.RetrieveAllUsers();
// Selecting all users except domain super administrators.
var usernamesInDomain =
(from UserEntry user in userFeed.Entries
where user.Login.Admin != true
select user.Login.UserName).ToList();
What does the returned UserFeed object contain in your case?
This is my solution :-
Google.GData.Apps.UserFeed s = appService.RetrieveAllUsers();
foreach (UserEntry s1 in s.Entries)
{
string username = s1.Login.UserName.ToString();
}