I'm creating new user using GraphServiceClient with SignInType as userName something like this:
var user = new User
{
AccountEnabled = true,
GivenName = "Joe",
Surname = "Bob",
DisplayName = "Name",
Mail = "joe#bob.com",
MobilePhone = "111111111",
Identities = new List<ObjectIdentity>()
{
new ObjectIdentity
{
SignInType = "userName",
Issuer = "<Issuer...>",
IssuerAssignedId = "someName"
},
},
PasswordProfile = new PasswordProfile
{
ForceChangePasswordNextSignIn = false,
Password = "<pass>"
},
PasswordPolicies = "DisablePasswordExpiration,DisableStrongPassword",
};
await gsc.Users.Request().AddAsync(user);
After that user is created in Azure and I can use this account for login into app that is using B2C SignIn policy. But when I want invoke ResetPassword policy for that user, after successfully email verification, I'm getting error: "An account could not be found for the provided user ID.". After some trial and error I've figure out that there is missing data in azure user profile tab "Authentication methods" When I fill out input for email everything is working fine and user is able to reset password.
So I'm searching for a way how to populate user email into this section "Authentication methods" during creation time.
In this circumstance, where you want to create users via Graph API, you cannot populate the strongAuthenticationEmail attribute usng Graph API. This attribute holds the email associated with a username based account for password reset operations. User Flows will read this attribute during password reset. Therefore this wont work.
You need to use a custom policy for a username based journey and replace all instances of strongAuthenticationEmail with extension_whatever. Then in your Graph API payload, insert the email address in a key called extension_GUID_whatever.
https://github.com/azure-ad-b2c/samples/tree/master/policies/username-signup-or-signin
Related
In the code below, I created a user on b2c but when I checked the user on azure portal, all fields were correct except for the Id, how can I make azure b2c create an identical user with exact user Id?
private static async Task MigrateUserAsync(GraphServiceClient client, MigratedUser user, string b2cDomainName)
{
var userPrincipalName = $"cpim_{Guid.NewGuid()}#{b2cDomainName}";
await client.Users.Request().AddAsync(new User
{
AccountEnabled = true,
Id = "837b0857-11cb-46ad-a229-4cd8de66d033",
DisplayName = user.DisplayName,
GivenName = user.GivenName,
Surname = user.Surname,
Identities = new List<ObjectIdentity>
{
new ObjectIdentity
{
SignInType = "emailAddress",
Issuer = b2cDomainName,
IssuerAssignedId = user.Email
},
},
PasswordProfile = new PasswordProfile
{
Password="xXx111!!!",
ForceChangePasswordNextSignIn=false
},
PasswordPolicies = "DisablePasswordExpiration",
});
}
the user created had a different Id than the one I specified when I created the user. I could not find any documentation addressing this issue.
The id, objectId, is randomly generated when the user is created in the directory. You cannot provide the objectId.
You could instead add another identity to the identities collection to store the old Id. This would provide a way to look up the account with the old Id.
new ObjectIdentity
{
SignInType = "oldId",
Issuer = "legacyIdp.com",
IssuerAssignedId = "<GUID>"
},
I'm using Graph Api to pre-create users in B2C before sending an email with a "Reset Password"-userflow URL as:
https://xxx.b2clogin.com/xxx.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1_ResetPassword&client_id=xxx&nonce=defaultNonce&redirect_uri=https%3A%2F%2Fjwt.ms&scope=openid&response_type=code&prompt=login&code_challenge=xxx&login_hint=me#example.com
Is there a way to pre-populate the email address field, so the user dosn't need to write it manually? I've tried appending login_hint but it doesn't work.
Code for creating user:
`var user = new User
{
DisplayName = displayName,
AccountEnabled = true,
UserType = "Member",
Identities = new List<ObjectIdentity>()
{
new ObjectIdentity
{
SignInType = "emailAddress",
Issuer = "xxx",
IssuerAssignedId = email
},
},
PasswordProfile = new PasswordProfile
{
Password = password,
ForceChangePasswordNextSignIn = false
},
PasswordPolicies = "DisablePasswordExpiration",
AdditionalData = customAttributes
};
await graphClient.Users
.Request()
.AddAsync(user);`
login_hint is used for sign-in, doc here. It doesn't work in the password reset policy, and you could feedback here.
There is no direct way to pre-populate the email address in this flow. You could use custom policies to define technical profiles and user journeys. Try to see this similar issue.
In an app where users aren't signed up by themselves but are instead created (name, email input) by existing users and sent an invitation email with link to password reset. Do I create a user and generate a random placeholder password like this:
const newUser = {
name: input.name,
email: input.email,
password: generateAndHashRandomPassword()
}
await User.create(newUser)
await sendEmail(newUser.email)
Or is there a best practice / standard / simpler other method to achieve this functionality?
The password reset also changed the isActive property on user model to true from default before password change being false
i have created an account as a multitenant user using the "federated account" creating settings following this: MS documentation for Create Users
code:
var user = new Microsoft.Graph.User
{
DisplayName = "John Doe",
Identities = new List<ObjectIdentity>()
{
SignInType = "federated",
Issuer = "myOrganizatinName.com.au",
IssuerAssignedId = "abc#myOrganizatinName.com.au"
}
},
PasswordProfile = new Microsoft.Graph.PasswordProfile
{
Password = "Officework1",
ForceChangePasswordNextSignIn = false
},
PasswordPolicies = "DisablePasswordExpiration",
OtherMails = new List<String>()
{
"JohnDoe#gmail.com"
},
};
user is created successfully:
but when i see the User in Azure Portal that user is present with only UserPrincipalName as: objectId#myTenantDomainname.onmicrosoft.com only and the email address i provided while creating the user through graph Api is not present anywhere.
and ehen i try to sign in using this email address and password provided in user creating time makes error of "userName and password is invalid"
only the UPN appearing with objectID##myTenantDomain.onmicrosoft.com is making me success to sign in.
the question is how can i sign in using the email address which i provided while creating the user?
any help in this will be much appriciated.
You can use the Ms Graph api to modify the userPrincipalName field.
I have the following method for registering users:
// Registration method
exports.register = function(req, res) {
var username = req.body.username,
password = req.body.password,
first = req.body.first;
last = req.body.last;
role = req.body.institution;
nano = require('nano')('http://127.0.0.1:5984');
var users = nano.use('_users');
var user = {
"_id": "org.couchdb.user:" + username,
"name": username,
"type": "user",
"roles": [],
"password": password,
"realname": first + " " + last
};
users.insert(user, function(err, body) {
if(err) {
res.send(err.reason, err.status_code);
} else {
res.send(body, 200);
}
});
};
As you can see, I have a variable called role which I would like to set in the "roles" array. Unfortunately, as you probably know, CouchDB only allows the admin to set roles. I'm okay with this, but I'm using the roles as institutions, so I'd like a registering user to be able to pick what institution they're registering under and therefore it should automatically be assigning them this role. Without hard-coding my admin credentials into this method, i.e.
nano.config.url = "http://admin:password#127.0.0.1:5984/"
How can I automatically assign a new user to their specified role as I've mentioned?
The roles array is used by CouchDB to decide database authorization. This allows you to configure access to a given database by a user's role. If the user can set their own role then somebody can give themselves access to any institution. They can even make themselves an admin, which defeats the purpose of protecting your admin password.
I'm not sure what your use-case is, but I don't think you are trying to prevent access to other institutions. Rather, I suspect you are trying to use the roles to perform some other application function (e.g. filtering out information for them to simplify what they see). Since you are wanting to perform a non-security function, I strongly suggest that you just add your own field to the users documents. You could add an institutions property to each user.
If you really want to do this, there is a way. The error you are receiving is coming from an update validation function in _design/_auth in the _users database. As an admin you can change this function.
Download the document. Open the file and search for Only _admin may edit roles to see where the test is being performed. Remove that conditional and save the document back to CouchDB.