Getting user attributes via the Graph Explorer in Azure AD B2C and Entra External ID

Rory Braybrook
The new control plane
3 min readAug 24, 2024
Image of graph
Sergey Fedotov, CC BY-SA 4.0 via Wikimedia

I’ve previously posted about getting attributes via this utility and via PowerShell.

You can also use Graph Explorer to do this.

You need to sign in with a work account, e.g. abc@tenant.onmicrosoft.com.

In this case, the tenant is a B2C one.

The Graph Explorer tries to guess the permissions you use:

Image of Graph Explorer with “Modify permissions” and “Consent”

and you consent to the ones you need.

Graph Explorer will try to help with permissions, e.g.,

"message": "Calling principal does not have required MSGraph permissions AuditLog.Read.All",

If the permission you need is not in the list, you can add it in the Identity section at the top right:

Image of logged in user with “Consent to permissions”

Running this query:

https://graph.microsoft.com/v1.0/me

results in:

{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"@microsoft.graph.tips": "This request only returns a subset of the
resource's properties. Your app will need to use $select to return
non-default properties. To find out what other properties are available for
this resource see https://learn.microsoft.com/graph/api/resources/user",
"businessPhones": [],
"displayName": "TOTP Admin",
"givenName": "TOTP",
"jobTitle": null,
"mail": null,
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": null,
"surname": "Admin",
"userPrincipalName": "totpadmin@tenant.onmicrosoft.com",
"id": "5c9...6bd"
}

You only get a subset.

To get more attributes, you need to use $select.

To get a more extensive list, we could try:

https://graph.microsoft.com/v1.0/users/771...8f2?$select=id,accountEnabled,ageGroup,assignedLicenses,assignedPlans,businessPhones,city,companyName,consentProvidedForMinor,country,createdDateTime,creationType,department,displayName,employeeId,employeeType,externalUserState,faxNumber,givenName,hireDate,identities,imAddresses,jobTitle,mail,mailNickname,mobilePhone,officeLocation,onPremisesDistinguishedName,onPremisesDomainName,onPremisesImmutableId,onPremisesLastSyncDateTime,onPremisesSamAccountName,onPremisesSecurityIdentifier,onPremisesSyncEnabled,passwordPolicies,postalCode,preferredLanguage,proxyAddresses,refreshTokensValidFromDateTime,showInAddressList,signInActivity,state,streetAddress,surname,usageLocation,userPrincipalName,userType

but this results in:

"message": "Tenant does not have a SPO license.",

SPO stands for Sharepoint Online, and I guess I’m trying to get some SP attributes?

This makes little sense because you can’t access SP via a B2C account.

Scaling back the request:

https://graph.microsoft.com/v1.0/users/771...8f2?$select=id,accountEnabled,ageGroup,businessPhones,city,companyName,createdDateTime,creationType,department,displayName,employeeId,employeeType,faxNumber,givenName,identities,imAddresses,jobTitle,mail,mailNickname,mobilePhone,officeLocation,passwordPolicies,postalCode,preferredLanguage,proxyAddresses,refreshTokensValidFromDateTime,showInAddressList,signInActivity,state,streetAddress,surname,usageLocation,userPrincipalName,userType

leads to:

{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(id,accountEnabled,ageGroup,businessPhones,city,companyName,createdDateTime,creationType,department,displayName,employeeId,employeeType,faxNumber,givenName,identities,imAddresses,jobTitle,mail,mailNickname,mobilePhone,officeLocation,passwordPolicies,postalCode,preferredLanguage,proxyAddresses,refreshTokensValidFromDateTime,showInAddressList,signInActivity,state,streetAddress,surname,usageLocation,userPrincipalName,userType)/$entity",
"id": "771...8f2",
"accountEnabled": true,
"ageGroup": null,
"businessPhones": [],
"city": null,
"companyName": null,
"createdDateTime": "2024-08-20T22:21:42Z",
"creationType": "LocalAccount",
"department": null,
"displayName": "TOTP User",
"employeeId": null,
"employeeType": null,
"faxNumber": null,
"givenName": "TOTP",
"imAddresses": [],
"jobTitle": null,
"mail": "totpuser@company.co.nz",
"mailNickname": "771...8f2",
"mobilePhone": null,
"officeLocation": null,
"passwordPolicies": "DisablePasswordExpiration, DisableStrongPassword",
"postalCode": null,
"preferredLanguage": null,
"proxyAddresses": [
"smtp:771...8f2@tenant.onmicrosoft.com",
"SMTP:totpuser@company.co.nz"
],
"refreshTokensValidFromDateTime": "2024-08-20T22:21:42Z",
"showInAddressList": null,
"state": null,
"streetAddress": null,
"surname": "User",
"usageLocation": null,
"userPrincipalName": "771...8f2@tenant.onmicrosoft.com",
"userType": "Member",
"identities": [
{
"signInType": "emailAddress",
"issuer": "tenant.onmicrosoft.com",
"issuerAssignedId": "totpuser@company.co.nz"
},
{
"signInType": "userPrincipalName",
"issuer": "tenant.onmicrosoft.com",
"issuerAssignedId": "771...8f2@tenant.onmicrosoft.com"
}
],
"signInActivity": {
"lastSignInDateTime": "2024-08-23T03:55:51Z",
"lastSignInRequestId": "d86...900",
"lastNonInteractiveSignInDateTime": null,
"lastNonInteractiveSignInRequestId": null,
"lastSuccessfulSignInDateTime": "2024-08-23T03:55:51Z",
"lastSuccessfulSignInRequestId": "d86...900"
}
}

The same commands work with Entra External ID.

Running the same scaled-back request to an Entra ID External user results in:

{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(id,accountEnabled,ageGroup,businessPhones,city,companyName,createdDateTime,creationType,department,displayName,employeeId,employeeType,faxNumber,givenName,identities,imAddresses,jobTitle,mail,mailNickname,mobilePhone,officeLocation,passwordPolicies,postalCode,preferredLanguage,proxyAddresses,refreshTokensValidFromDateTime,showInAddressList,signInActivity,state,streetAddress,surname,usageLocation,userPrincipalName,userType)/$entity",
"id": "bed...f7f",
"accountEnabled": true,
"ageGroup": null,
"businessPhones": [],
"city": null,
"companyName": null,
"createdDateTime": "2024-01-16T03:18:20Z",
"creationType": null,
"department": null,
"displayName": "Test User",
"employeeId": null,
"employeeType": null,
"faxNumber": null,
"givenName": "Test",
"imAddresses": [],
"jobTitle": null,
"mail": "testu@company.co.nz",
"mailNickname": "TestU",
"mobilePhone": null,
"officeLocation": null,
"passwordPolicies": null,
"postalCode": null,
"preferredLanguage": null,
"proxyAddresses": [
"smtp:TestU@tenant.onmicrosoft.com",
"SMTP:testu@company.co.nz"
],
"refreshTokensValidFromDateTime": "2024-01-24T02:01:25Z",
"showInAddressList": null,
"state": null,
"streetAddress": null,
"surname": "User",
"usageLocation": null,
"userPrincipalName": "TestU@tenant.onmicrosoft.com",
"userType": "Member",
"identities": [
{
"signInType": "userPrincipalName",
"issuer": "tenant.onmicrosoft.com",
"issuerAssignedId": "TestU@tenant.onmicrosoft.com"
}
],
"signInActivity": {
"lastSignInDateTime": "2024-02-26T02:00:49Z",
"lastSignInRequestId": "cdf...100",
"lastNonInteractiveSignInDateTime": "2024-01-24T02:13:53Z",
"lastNonInteractiveSignInRequestId": "9ee...100",
"lastSuccessfulSignInDateTime": "2024-02-15T21:37:59Z",
"lastSuccessfulSignInRequestId": "704...000"
}
}

All good!

--

--

The new control plane
The new control plane

Published in The new control plane

“Identity is the new control plane”. Articles around Microsoft Identity, Auth0 and identityserver. Click the “Archive” link at the bottom for more posts.

Rory Braybrook
Rory Braybrook

Written by Rory Braybrook

NZ Microsoft Identity dude and MVP. Azure AD/B2C/ADFS/Auth0/identityserver. StackOverflow: https://bit.ly/2XU4yvJ Presentations: http://bit.ly/334ZPt5

No responses yet