Reputation: 2076
My goal is to create a local account, like [email protected]
, in Azure Active Directory B2C.
I want to use my own UI, so I started to look at how to implement the API. After some research, it looks like the best way to do it should be via Microsoft Graph.
I started by following Manage Azure AD B2C user accounts with Microsoft Graph, and I properly created an app (not sure if I need to choose the third options, but looks like the broader one):
with the following permissions (updated following also @Tony Ju screenshot):
Then I created the client secret and coded my own auth provider
const { AuthenticationContext } = require('adal-node');
class AuthProvider {
async getAccessToken() {
return new Promise((resolve, reject) => {
const tenant = 'tenant';
const authority = `https://login.microsoftonline.com/${tenant}`;
const authenticationContext = new AuthenticationContext(authority);
const resource = 'https://graph.microsoft.com';
const clientId = 'clientId';
const clientSecret = 'clientSecret';
authenticationContext.acquireTokenWithClientCredentials(
resource,
clientId,
clientSecret,
(err, tokenResponse) => {
if (err) {
console.error('error!', err);
return reject(err);
}
return resolve(tokenResponse.accessToken);
},
);
});
}
}
and initialized the client
require('isomorphic-fetch'); //needed for server side request with the client
const { Client } = require('@microsoft/microsoft-graph-client');
const options = {
authProvider: new AuthProvider(),
};
const client = Client.initWithMiddleware(options);
Following the official documentation, I create a local account
const user = {
displayName: 'John Smith',
identities: [
{
signInType: 'emailAddress',
issuer: 'MY_ISSUER.onmicrosoft.com',
issuerAssignedId: '[email protected]',
},
],
passwordProfile: {
password: 'df42bfe2-8060-411f-b277-06b819874573',
},
passwordPolicies: 'DisablePasswordExpiration',
};
client
.api('/users')
.post(user)
.then(data => console.log(data))
.catch(e => console.error(e))
And I get back this "Request_ResourceNotFound" error
GraphError {
statusCode: 404,
code: 'Request_ResourceNotFound',
message:
'Resource \'User_30140fa1-ae7e-40b7-ad5a-ef4d0b4cd4dc\' does not exist or one of its queried reference-property objects are not present.',
requestId: 'fbf4c987-0383-472a-bc22-c94f98710344',
date: 2020-05-18T13:19:14.000Z,
body:
'{"code":"Request_ResourceNotFound","message":"Resource \'User_30140fa1-ae7e-40b7-ad5a-ef4d0b4cd4dc\' does not exist or one of its queried reference-property objects are not present.","innerError":{"request-id":"fbf4c987-0383-472a-bc22-c94f98710344","date":"2020-05-18T15:19:14"}}' }
The error does not help and I don't know how to continue. The basic configuration looks correct, because I'm able to get all the users and also create a user in the same tenant.
What am I missing? Feels so weird having this type of error by following the official docs. I'm starting to think that I need to use the invitation API, but I just want to create a user and don't go into the full email verification flow. Plus, what I exactly need is in the official docs and I would expect it to work. So maybe there is just something wrong on my side.
Upvotes: 1
Views: 4911
Reputation: 15619
Your code works perfectly. I only updated tenant,clientId,clientSecret and MY_ISSUER in your code. Here is the whole code I ran.
const { AuthenticationContext } = require('adal-node');
class AuthProvider {
async getAccessToken() {
return new Promise((resolve, reject) => {
const tenant = '6b72a356-867d-4c35-bde6-959d99388ca8';
const authority = `https://login.microsoftonline.com/${tenant}`;
const authenticationContext = new AuthenticationContext(authority);
const resource = 'https://graph.microsoft.com';
const clientId = '270408b5-85a6-4e99-861e-7634853a5827';
const clientSecret = 'VYD_F_Rr~eHYqLtTXqa1~1KRS_932yNw35';
authenticationContext.acquireTokenWithClientCredentials(
resource,
clientId,
clientSecret,
(err, tokenResponse) => {
if (err) {
console.error('error!', err);
return reject(err);
}
return resolve(tokenResponse.accessToken);
},
);
});
}
}
require('isomorphic-fetch'); //needed for server side request with the client
const { Client } = require('@microsoft/microsoft-graph-client');
const options = {
authProvider: new AuthProvider(),
};
const client = Client.initWithMiddleware(options);
const user = {
displayName: 'John Smith',
identities: [
{
signInType: 'emailAddress',
issuer: 'tonyb2ctest.onmicrosoft.com',
issuerAssignedId: '[email protected]',
},
],
passwordProfile: {
password: 'df42bfe2-8060-411f-b277-06b819874573',
},
passwordPolicies: 'DisablePasswordExpiration',
};
client
.api('/users')
.post(user)
.then(data => console.log(data))
.catch(e => console.error(e))
The result:
I registered an application under Azure Active Directory and granted Directory.ReadWrite.All permission.
Upvotes: 4