A few days ago, I created a fresh Microsoft Entra tenant for a startup project, let’s call it “contoso-labs” for this blog.
The process was ordinary enough:
- Open Azure Portal
- Go to Manage tenants
- Create a new tenant
- Use
contoso-labs.onmicrosoft.com - Switch into it
- Continue with the setup
At least, that was the plan.
Instead, I managed to create a tenant that I could not enter, configure, or delete, or so it seemed.
Every login ended at:
Let’s keep your account secure
Microsoft Entra wanted me to register an authentication method before continuing. Fair enough.
Disclaimer: This article describes a single troubleshooting experience. The goal is not to conclude that Microsoft Entra or Microsoft Authenticator has a product defect, but to demonstrate a structured troubleshooting approach using Microsoft Graph when the portal alone isn't sufficient.
Opening scene
So, I scanned the QR code using Microsoft Authenticator.
Unexpected error. Please contact your local IT administrator.
I was the local IT administrator.
That was not particularly helpful.
A bit of a background
The tenant had been created while I was signed in with an administrator from another Microsoft Entra tenant.
The only identity initially present in the new directory looked like this:
Admin_source-tenant.example#EXT#@contoso-labs.onmicrosoft.com
Although Microsoft Graph reported the user as a member, the UPN clearly indicated that this was an external identity originating from another tenant, which is kinda normal.
My first assumption was that the external bootstrap administrator was causing the problem.
Perhaps Microsoft Authenticator registration did not behave correctly because of that and something was breaking the flow.
It was a reasonable theory.
It was also wrong.
The tenant lockout loop
The problem was not simply that I could not complete MFA registration.
The real problem was the loop this created:
Sign in
↓
Mandatory security registration
↓
Microsoft Authenticator returns “Unexpected error”
↓
No access to the tenant
Without portal access, I could not:
- inspect the tenant configuration
- create another administrator
- change the authentication policy
- disable Security Defaults
- or delete the tenant and start again
At this point, switching browsers, using private sessions, clearing cookies and trying again were not going to tell me much.
The differentiator
The portal was blocked, but the underlying platform wasn’t.
Microsoft Graph is the control plane.
That changed the investigation completely.
Connecting directly to the tenant
Using Microsoft Graph PowerShell and device authentication, I connected directly to the new tenant:
Connect-MgGraph ` -TenantId "<tenant-id>" ` -Scopes ` "User.ReadWrite.All", "RoleManagement.ReadWrite.Directory", "Directory.Read.All" ` -UseDeviceAuthentication
I then confirmed that the Graph session was operating against the correct tenant:
Get-MgContext
This was the first important result. I was getting somewhere!
Even though the interactive portal flow was blocked, Microsoft Graph could still access and manage the directory.
The tenant existed and the directory service worked.
Authorization worked, also.
We were no longer locked out of the actual control plane—only out of its graphical interface.
A small Cloud Shell complication
I was doing all of this from Azure Cloud Shell while signed in with the account that had originally created the tenant.
The preinstalled Microsoft Graph modules had slightly different versions, which resulted in module import conflicts between the authentication and users components.
Rather than spending more time resolving module dependencies, I used the authentication module together with direct REST requests:
Invoke-MgGraphRequest
That turned out to be simpler and gave me direct visibility into the API calls being made.
For example, I listed the users using:
$response = Invoke-MgGraphRequest ` -Method GET ` -Uri "https://graph.microsoft.com/v1.0/users?`$select=displayName,userPrincipalName,userType,id" $response.value
There was only one user: the external bootstrap identity.
Creating a native administrator through Graph
The next step was to remove the external identity from the equation.
Using Microsoft Graph, I created a native cloud-only user:
$passwordProfile = @{
password = "<temporary-strong-password>"
forceChangePasswordNextSignIn = $true
}
$body = @{
accountEnabled = $true
displayName = "Contoso-Labs Administrator"
mailNickname = "admin"
userPrincipalName = "admin@contoso-labs.onmicrosoft.com"
passwordProfile = $passwordProfile
} | ConvertTo-Json -Depth 10
$newAdmin = Invoke-MgGraphRequest `
-Method POST `
-Uri "https://graph.microsoft.com/v1.0/users" `
-Body $body `
-ContentType "application/json"The user was created successfully.
I then assigned the Global Administrator role through Graph.
First, I located the role definition:
$roles = Invoke-MgGraphRequest ` -Method GET ` -Uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions?`$filter=displayName eq 'Global Administrator'"
Then I created the role assignment:
$roleAssignment = @{
principalId = $newAdmin.id
roleDefinitionId = $roles.value[0].id
directoryScopeId = "/"
} | ConvertTo-Json
Invoke-MgGraphRequest `
-Method POST `
-Uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments" `
-Body $roleAssignment `
-ContentType "application/json"We now had a proper native cloud administrator.
Surely that had to be it.
It didn’t.
The new user could:
- sign in
- change the temporary password
- reach the security registration screen
But Microsoft Authenticator still returned the same message:
Unexpected error
That eliminated the external-user hypothesis.
Inspecting the authentication policy
The next possibility was a broken or incomplete authentication-method policy.
I reconnected with the necessary policy permissions:
Disconnect-MgGraph Connect-MgGraph ` -TenantId "<tenant-id>" ` -Scopes ` "User.ReadWrite.All", "RoleManagement.ReadWrite.Directory", "Directory.Read.All", "Policy.Read.AuthenticationMethod", "Policy.Read.All" ` -UseDeviceAuthentication
Then I retrieved the tenant-wide authentication-method policy:
$authPolicy = Invoke-MgGraphRequest ` -Method GET ` -Uri "https://graph.microsoft.com/v1.0/policies/authenticationMethodsPolicy" $authPolicy | ConvertTo-Json -Depth 20
The policy looked normal:
- Microsoft Authenticator was enabled
- Software OATH was enabled
- Temporary Access Pass was enabled
- FIDO2/passkeys were enabled
- Self-service registration was allowed
- All users were included
- There were no suspicious exclusions
The registration campaign was Microsoft-managed and targeted Microsoft Authenticator for all users.
Nothing in the policy explained the failure.
Security Defaults
Security Defaults were enabled, which explained why the tenant insisted on completing registration before allowing portal access.
To test whether this requirement was trapping us in the loop, I retrieved the policy:
$securityDefaults = Invoke-MgGraphRequest ` -Method GET ` -Uri "https://graph.microsoft.com/v1.0/policies/identitySecurityDefaultsEnforcementPolicy" $securityDefaults | ConvertTo-Json
It returned:
{
"isEnabled": true
}I reconnected with the write permission required to modify Security Defaults:
Disconnect-MgGraph Connect-MgGraph ` -TenantId "<tenant-id>" ` -Scopes ` "User.ReadWrite.All", "RoleManagement.ReadWrite.Directory", "Directory.Read.All", "Policy.Read.All", "Policy.ReadWrite.SecurityDefaults" ` -UseDeviceAuthentication
Then temporarily disabled them:
$body = @{
isEnabled = $false
} | ConvertTo-Json
Invoke-MgGraphRequest `
-Method PATCH `
-Uri "https://graph.microsoft.com/v1.0/policies/identitySecurityDefaultsEnforcementPolicy" `
-Body $body `
-ContentType "application/json"The change succeeded.
I confirmed through Graph that Security Defaults were disabled.
Then I opened a completely fresh private browser session and tried again.
The result?
Let’s keep your account secure
Still there.
Microsoft Authenticator?
Unexpected error
Still there.
At this point, the tenant itself looked healthy:
- Graph access worked
- directory operations worked
- native user creation worked
- role assignment worked
- authentication policies were readable
- authentication methods were enabled
- Security Defaults could be modified
- native users could authenticate and change passwords
Based on the evidence I collected, the failure appeared limited to the authentication-method registration flow.
The unexpected workaround
After enough time looking at Graph, policies, role assignments and tenant provisioning, I tried something much simpler.
Instead of scanning the QR code with Microsoft Authenticator, I scanned it with Bitwarden.
Bitwarden stored the TOTP secret and generated a six-digit code.
I entered the code.
It worked.
I was staring at the screen.
I was inside the tenant.
I'm pretty sure a choir of angels started singing somewhere in the distance.
I then logged out and repeated the login using Microsoft Edge InPrivate.
The Bitwarden code worked there too.
So the browser was not the deciding factor.
The tenant accepted standard TOTP correctly. The registration flow completed, and the administrator could access the portal normally.
The exact reason Microsoft Authenticator returned Unexpected error is still not proven. The evidence narrowed the problem to that specific enrollment path on my device or within the application, but I would not call that a definitive root cause without additional diagnostics.
What mattered operationally was that the tenant was recoverable and its control plane was working correctly.
Securing the tenant after recovery
Once inside, I did not immediately start configuring applications.
First, I made sure we could not end up in the same position again.
I:
- re-enabled Security Defaults
- created a second native Global Administrator
- configured it as an emergency administrator account (better you tighten it more based on official Microsoft guidance on true break-glass accounts)1
- registered Bitwarden TOTP independently for both accounts
- added passkeys using Microsoft Authenticator
- added email as another available method
- tested sign-in using the passkey
- tested both administrator accounts
- kept one session active while validating the other account
- deleted the original external bootstrap identity
Interestingly, passkeys stored in Microsoft Authenticator worked perfectly.
Only adding Microsoft Authenticator as a traditional code-generator method continued to produce the same unexpected error.
At that point, continuing the investigation would have been interesting but no longer operationally useful, and it was getting quite late in the day, or I should say better early in the morning.
The tenant had:
- two native administrators
- independent credentials
- working TOTP
- working passkeys
- Security Defaults enabled
- no dependency on the original external account
Mission accomplished. I could finally breathe again.
Lessons learned
The portal is not the platform
The Microsoft Entra and Azure portals are clients of the underlying services.
When the portal blocks you, that does not necessarily mean the tenant is inaccessible.
Microsoft Graph may still provide full administrative control.
That distinction turned an apparent tenant lockout into a recoverable directory-management problem.
Graph permissions are part of the debugging process
Several 403 Forbidden responses initially looked suspicious.
They were not evidence of broken services. They simply indicated that the current Graph token did not include the required permission.
For example:
- reading authentication policies requires policy-read permissions
- modifying Security Defaults requires
Policy.ReadWrite.SecurityDefaults - reading user authentication methods requires authentication-method permissions
A 403 should be interpreted carefully. It does not automatically mean the underlying API or tenant service is broken.
Create native administrators early
The tenant was initially dependent on one externally sourced identity.
Even if that was not the root cause, it was not a good long-term administrative configuration.
A new tenant should quickly receive:
- at least one native administrative account
- a second emergency administrator
- independently registered authentication methods
Do this before building anything important in the tenant.
Do not depend on one MFA implementation
Standards matter.
Bitwarden could use the same QR-based TOTP secret that Microsoft Entra was presenting, even though Microsoft Authenticator failed during that particular registration flow.
Passkeys in Microsoft Authenticator also worked.
Different methods use different enrollment and authentication paths. Having more than one secure option can be the difference between a minor inconvenience and a complete administrative lockout.
Keep one working administrative session open
While configuring the second administrator, I remained signed in with the break-glass account.
That sounds obvious, but it is exactly the kind of precaution people forget when they are tired and trying to repair an access problem.
Never modify the only working authentication path while all other administrator sessions are closed.
Change one variable at a time—when possible
The successful attempt initially changed two variables:
- the browser
- the authenticator application
That meant the first success did not immediately tell us which change mattered.
A later test using Edge InPrivate with the Bitwarden-generated code confirmed that the browser was not the important variable.
In troubleshooting, changing one thing at a time produces cleaner evidence.
In real incidents, however, restoring access comes first. Perfect experimental design comes second.
A practical recovery pattern
The exact circumstances will vary, but the general approach is reusable:
Portal access fails ↓ Connect directly through Microsoft Graph ↓ Confirm the tenant and current identity ↓ Enumerate existing users ↓ Create a native cloud administrator ↓ Assign the required directory role ↓ Inspect authentication policies ↓ Inspect Security Defaults ↓ Test an alternative standards-based authentication method ↓ Recover portal access ↓ Create and validate a break-glass account
The most important shift is conceptual:
Stop treating the portal as the source of truth.
The portal is convenient, but Microsoft Graph exposes the underlying directory objects and policies directly.
Final thoughts
This was not intended to become a deep Microsoft Entra troubleshooting session.
I only wanted to create a clean tenant for my startup project.
Instead, we ended up:
- authenticating directly to a tenant we could not enter through the portal
- creating users through Microsoft Graph2
- assigning Global Administrator through the role-management API
- inspecting tenant-wide authentication policies
- modifying Security Defaults
- testing multiple authentication implementations
- and rebuilding the administrative access model safely
By the end of the investigation, we were no longer troubleshooting a portal screen.
We were operating Microsoft Entra directly through Microsoft Graph.
At some point during the investigation, I caught myself thinking: “Wait… I’m not supposed to be doing Level 3 support tonight.”
Apparently, for one evening, I was.
Sources:
Discover more from sqltattoo blog - Vassilis Ioannidis
Subscribe to get the latest posts sent to your email.
