michelepatrassi
michelepatrassi

Reputation: 2076

Microsoft Graph API - Create user in Azure AD B2C with local account identity gives Request_ResourceNotFound error

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):

enter image description here

with the following permissions (updated following also @Tony Ju screenshot):

enter image description here

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

Answers (1)

Tony Ju
Tony Ju

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:

enter image description here

I registered an application under Azure Active Directory and granted Directory.ReadWrite.All permission.

enter image description here

enter image description here

Upvotes: 4

Related Questions