enum

Changelog

  • 2025-04-09 - initial version
  • 2025-04-11 - updated with AADInternals OSINT tool

Tenant public information

Your tenant-id

With the page https://www.whatismytenantid.com/, you can find your TenantID

How does it work? We can check the Network tab of the browser and find a query to the OpenID Configuration endpoint based on the domain:

https://login.microsoftonline.com/{{YOUR-DOMAIN-HERE}}/.well-known/openid-configuration

^ We can also find a tenant location with the tenant_region_scope field.

^ Whatismytenantid doesn’t work? You can get the same from the website https://gettenantpartitionweb.azurewebsites.net/!

A new tenant helper (scanner)

With the website https://o365.rocks/, you can check if the name for the tenant is free - all tenants are created with {{name}}.onmicrosoft.com domain - so each name should be unique.

AADInternals OSINT tool

We can get full details about the tenant, including:

  • Tenant ID
  • Tenant Name (onmicrosoft.com domain)
  • Domains
  • brand name

https://aadinternals.com/osint/

All details in one place like on the screen for my tenant: OSINT

Public User Details

userrealm endpoint

Let’s start with the example with the HTTP GET to my workshop tenant and user Mati https://login.microsoftonline.com/common/userrealm/[email protected]?api-version=2.1

{
  "NameSpaceType":"Managed",
  "Login":"[email protected]",
  "DomainName":"workshop.factorlabs.pl",
  "FederationBrandName":"DEV E5 M365: Workshop Factorlabs","TenantBrandingInfo":null,
  "cloud_instance_name":"microsoftonline.com"
}

Nice, but now when we check the mati2 - not existing user, we see that the response doesn’t allow enumerate users. The response is the same for existing and non-existing users.

{
  "NameSpaceType":"Managed",
  "Login":"[email protected]",
  "DomainName":"workshop.factorlabs.pl",
  "FederationBrandName":"DEV E5 M365: Workshop Factorlabs","TenantBrandingInfo":null,
  "cloud_instance_name":"microsoftonline.com"
}

summary

  • We can get details about the user source (tenant) - and review if the tenant exists in the Entra ID realm.

GetCredentialType

After sending a POST request to the endpoint https://login.microsoftonline.com/common/GetCredentialType, we can receive more details about the user. Look at the example:

POST https://login.microsoftonline.com/common/GetCredentialType
Content-Type: application/json

{
 "username": "[email protected]",
 "isOtherIdpSupported":  true
}

Result

{
    "Username": "[email protected]",
    "Display": "[email protected]",
    "IfExistsResult": 0,
    "IsUnmanaged": false,
    "ThrottleStatus": 0,
    "Credentials": {
        "PrefCredential": 1,
        "HasPassword": true,
        "RemoteNgcParams": null,
        "FidoParams": null,
        "QrCodePinParams": null,
        "SasParams": null,
        "CertAuthParams": null,
        "GoogleParams": null,
        "FacebookParams": null,
        "OtcNotAutoSent": false
 },
    "DfpProperties": {},
    "EstsProperties": {
        "UserTenantBranding": null,
        "DomainType": 3
 },
    "IsSignupDisallowed": true,
    "apiCanary": "PAQABDgEAAABVrSpeuWamRam2jAF1XRQE4hLOxSuqm0PBVn6F8MFuh-ioTMYqr4JrzUcvwxH-dWS3zfZ4D32YyFUAgEmogAKk80svE0qlE6DZdiS7eD6u0-2YoXg6TD4D2PYDOUI8hvNLkDVB1jIOowAkHlAOcFAh8jREqUcA_AMyfriklkKp4yw7_p6gOVPOx-Zj_vq4D340F8MkWbAP2jqgefO6W5Vhr9ZzH-30SXX63rQf3kcE5iAA"
}

^ The most interesting response field is IfExistsResult which returns 0 for existing users and 1 for not.

Try it on your own. As a response, we get:

  • Branding details from the tenant.
  • Keep-Me-Signed-In details.

Entra External ID

I checked the behaviour of the external customer tenant:

  • replace common endpoint with tenant GUID
  • custom tenant domain instead of login.microsoftonline.com

I can’t return enumerate the user with that same query, we need to modify the request with the sCtx as originalRequest. From the Browser perspective, we can enumerate non-existing accounts (and as opposite action existing) with the Entra ID Error message: enumeration

{
    "username":"[email protected]",
    "originalRequest":"{{sCtx}}"
}

To get the sCtx, we need to check the authorization endpoint to Entra External ID. Andy Robbins made a similar try for the Device Code flow at https://posts.specterops.io/browserless-entra-device-code-flow-0802f3bbb91a.

HRD

hrd

In general, we should remember that Entra ID Sign-In flow has two steps: home realm discovery (HRD) and authentication(s) methods, we can be:

  • asked for PassKey;
  • redirected to social login (Google, Facebook, etc.);
  • redirected to Entra ID workforce tenant to use corporate credentials.

Summary

  • We can enumerate Entra ID Workforce users with the GetCredentialType endpoint.
  • Enumerating users in the Entra External ID tenant is a bit harder, but it is possible with the sCtx parameter automatically. It is easy to do with the browser.
  • There are helper websites to check the tenant name availability and tenant ID.