How can I get a user password using the Auth0 Management API nuget package? - auth0

We are currently trying to make a change to our website so that it uses Auth0 to authenticate. As part of that, I am rewriting a "config" website that we have for managing the users. The users will now be stored in Auth0 and the config website will therefore have to be able to add and edit Auth0 users in my tenant.
The config website uses the Auth0 Management API nuget package: https://github.com/auth0/auth0.net
But I have run into a problem. I can get a list of users and I can create a user. I can get the user's details and present them in an edit form onscreen, but I can't save the changes made, because when I try to do this I get an error that I need to supply a password in the UserUpdateRequest.
But when I get the user's details (client.Users.GetAsync(id)), it doesn't give me back a password property. If I could get the password from the call to GetAsync(id) then I could add it to the UserUpdateRequest. But if I can't get the password from GetAsync, how can I put the password in the UserUpdateRequest? How am I supposed to ever save a user?
I guess my ultimate question is: how can I get the user's password using the Management API...so that I can supply it later on to the UserUpdateRequest model when calling Users.UpdateAsync. Or if I can't get the user's password, can I somehow update the user without knowing their password?
It looks like the Nuget Management API was expecting this method to be used by the user themselves (and they could therefore put in their password to change their details), not an admin user operating through a config/admin website that wouldn't know the users password.
C# User/Edit [HttpGet] action method to get users and display them:
var token = GetAccessToken();
var apiClient = new ManagementApiClient(token, new Uri("https://MY_TENANT_ID.au.auth0.com/api/v2"));
var user = await apiClient.Users.GetAsync(id);
var userModel = MapUserToUserModel(user);
return View(userModel);
C# User/Edit [HttpPost] action method to save the changes to user's details:
var token = GetAccessToken();
var apiClient = new ManagementApiClient(token, new Uri("https://MY_TENANT_ID.au.auth0.com/api/v2"));
var updateReq = new UserUpdateRequest()
{
UserName = model.UserId,
Email = model.Email,
Password = model.Password,
EmailVerified = model.EmailVerified,
AppMetadata = model.AppMetadata,
UserMetadata = model.UserMetadata
};
var user = await apiClient.Users.UpdateAsync(model.UserId, updateReq);

Related

Graph API Call Issues - POST Event

I'm running into issues when trying to create an event in a specific user calendar.
This call works fine: POST https://graph.microsoft.com/v1.0/me/events
But when I change the API Call to include the other user details, it throws this error: "The specified object was not found in the store."
I have created an app on Azure and assigned all necessary permissions.
App Permissions
Error:
Can someone please assist if I'm missing something?
Please note when you use /me, it means you are calling the ms graph api with a delegate api permission which is authentiated by entering user name/password, you can only do operations on your own account with this kind of authentication. While you want to do operations for other users like /users/user_id/xxx, you required the application api permission. That's why api document showed api permission in Delegated and Application. One for personal and another for all users.
When we need to get access token contain application permission, we need to use client credential flow. This flow is used for daemon application since this kind of application doesn't have user interactive operation, so we can only use application permission for this kind of scenario. And as you can see it will offer "very big ability" to the application(allow application to create/change/delete items for any user in your tenant), so we need to use appliation permission with caution.
Come back to the case, you can follow this section to generate access token and call the api. You can also using graph SDK in your code to call that api.
using Azure.Identity;
using Microsoft.Graph;
public async Task<string> testAsync() {
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "azure_ad_clientid";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var a = await graphClient.Users["user_id"].Request().GetAsync();
return a.DisplayName;
}

How to sign out previous login on new login in .net core?

How to sign out previous login when user log in through another browser in .net core?
I referred to this link but confused about how to use it.
enter link description here
You simply call UpdateSecurityStampAsync on your UserManager instance with the user in question. Then sign them in. This won't automatically log out other sessions, because there's a client-side component that must come into play. However, on the next request made from another browser, the cookie there will be invalidated because the security stamp won't match, and then the user will be effectively logged out.
It worked for me doing like:
After login done:
var loggedinUser = await _userManager.FindByEmailAsync(model.Email);
if (loggedinUser != null)
{
var Securitystamp = await _userManager.UpdateSecurityStampAsync(loggedinUser);
}
and in StartUp.cs
services.Configure<SecurityStampValidatorOptions>(options => options.ValidationInterval = TimeSpan.FromSeconds(0));

How to do multiple-step login in IdentityServer4?

We were using IdentityServer3, implicit grant and the login consists of multiple screen. In IdentityServer3, there's built in support for such multiple step login workflow (for example for accepting EULA, two-factor login, etc.), The feature called "partial login" and there is even an example: https://github.com/IdentityServer/IdentityServer3.Samples/tree/master/source/CustomUserService/CustomUserService
We've recently upgraded to AspNetCore and IdentityServer4 and wondering how suppose to achieve the same? That is, check username and password in the first step, and if correct, store it securely (for example in an encrypted cookie) for the next step(s).
Our solution was to replicate the IdentityServer3's partial login: use a custom cookie to persist data between steps.
First, we need to register our custom cookie authentication (at Startup.Configure)
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "my-partial",
AutomaticAuthenticate = false,
AutomaticChallenge = false
});
The first step/entry point of the login workflow should be mapped to GET /account/login (as of IdentityServer4 1.0.0-rc2).
In second step, after the credentials are sent and verified, we persist the username (and eventually any other data) into a cookie.
Code:
var claims = new []
{
new Claim("my-user", username),
new Claim("some-attribute", someAttribute)
};
await HttpContext.Authentication
.SignInAsync("my-partial", new ClaimsPrincipal(new ClaimsIdentity(claims)));
Important: avoid using POST /account/login as a second step. Because regardless of your result, IdentityServer's middleware will redirect you back to the authorization endpoint (as of RC2). Just pick any other path.
At your last step, key parts
we read the persisted data from the cookie
remove the partial cookie
sign in the "real" user
redirect to returnUrl (this was added to the first step as a query parameter. Don't forget to send along it)
In code
var partialUser = await HttpContext.Authentication.AuthenticateAsync("my-partial");
var username = partialUser?.Claims.FirstOrDefault(c => c.Type == "dr-user")?.Value;
var claims = new [] { /* Your custom claims */};
await HttpContext.Authentication
.SignOutAsync("my-partial");
await HttpContext.Authentication
.SignInAsync(username, username, claims);
return Redirect(returnUrl);
In addition, you might want to validate inputs, for example return to the first step, if there is no partial cookie, etc.

AspNet Core External Authentication with Both Google and Facebook

I am trying to implement the Form-Authentication in ASP.Net Core with Both Google and Facebook Authentications. I followed some tutorials and after some struggles, I managed to make it work both.
However, the problem is that I cannot use both authentications for the same email.
For example, my email is 'ttcg#gmail.com'.
I used Facebook authentication to log in first... Registered my email and it worked successfully and put my record into 'dbo.ASPNetUsers' table.
Then I logged out, clicked on Google Authentication to log in. It authenticated successfully, but when I tried to register it keeps saying that my email is already taken.
I tried to do the same thing for other online websites (Eg, Stackoverflow). I used the same email for both Google and Facebook and the website knows, I am the same person and both my login / claims are linked even though they come from different places (Google & Facebook).
I would like to have that feature in my website and could you please let me know how could I achieve that.
In theory, it should put another line in 'dbo.AspNetUserLogins' and should link the same UserId with multiple logins.
Do I need to implement my own SignInManager.SignInAsync method to achieve that feature? Or am I missing any configuration?
You need to link your Facebook external login to your Google external login with your email by using UserManager.AddLoginAsync, you cannot register twice using the same adresse if you use the adresse as login.
Check out the Identity sample on Identity github repo.
https://github.com/aspnet/Identity/blob/dev/samples/IdentitySample.Mvc/Controllers/ManageController.cs
To link external login to a user, the Manae controller expose methods LinkLogin and LinkLoginCallback
LinkLogin requests a redirect to the external login provider to link a login for the current user
LinkLoginCallback processes the provider response
//
// POST: /Manage/LinkLogin
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult LinkLogin(string provider)
{
// Request a redirect to the external login provider to link a login for the current user
var redirectUrl = Url.Action("LinkLoginCallback", "Manage");
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User));
return Challenge(properties, provider);
}
//
// GET: /Manage/LinkLoginCallback
[HttpGet]
public async Task<ActionResult> LinkLoginCallback()
{
var user = await GetCurrentUserAsync();
if (user == null)
{
return View("Error");
}
var info = await _signInManager.GetExternalLoginInfoAsync(await _userManager.GetUserIdAsync(user));
if (info == null)
{
return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error });
}
var result = await _userManager.AddLoginAsync(user, info);
var message = result.Succeeded ? ManageMessageId.AddLoginSuccess : ManageMessageId.Error;
return RedirectToAction(nameof(ManageLogins), new { Message = message });
}

Limiting OAuth login to a specific email domain

I am using the Google PHP API to authenticate user login. I would like to restrict login access to specific email domains, eg only users with email #thedomain.com can login.
I've tried setting the hd parameter as suggested, with no luck. I also noticed that the returned $client = new Google_Client(); object returns an empty string for ["hd"]=> string(0) ""
Checking the email domain after authentication may be viable, but i fell like there must be a method within the Google API.
Anyone have ideas or suggestions?
Ended up using the hd object, which required instantiating a new $service
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
// create service to pull userinfo
$service = new Google_Service_Oauth2($client);
$user = $service->userinfo->get();
$userHd = $user['hd'];
if ($userHd === 'thedomain.com') {
// log the user in
}