Obtaining Microsoft Entra Refresh Tokens via Beacon
An alternative technique for obtaining Microsoft Entra refresh tokens (and "family refresh tokens") using beacon on a compromised endpoint.
Background
I was recently in a situation where I needed to pivot from a compromised windows endpoint to my target’s Entra tenancy. The usual go-to in this scenario is to extract the primary refresh token (PRT) from the endpoint via beacon (using BOFs like aad_prt_bof or request_aad_prt by Kozmer). However, in this case, my beacon was running on a non-domain-joined, BYOD device, meaning the PRT extraction approach was off the table. I needed another way to obtain refresh tokens, so that I could maintain access to the compromised identity when the beacon inevitably dies.
Side note - I’d strongly recommend reading “An Operator’s Guide to Device-Joined Hosts and the PRT Cookie” by Matthew Creel for a great insight into PRTs.
During a quick chat, my good friend Jack made me aware of the new BOF that was recently added to TrustedSec’s Remote Ops Repo, called get_azure_token by Christopher Paschen. This BOF is awesome and is the inspiration for this post.
In short, the BOF works by leveraging the user already being authenticated to Entra via the browser. It starts by launching a new browser window and initiating an authorization code flow for a given Entra client ID and scope. It then starts a local ‘listener’ to capture the incoming authorization code, and uses the captured code to request an access and refresh token, which is then displayed to the operator.
The BOF's approach has various advantages, one of them being that all requests originate from the end-user’s machine and IP address. However, an important caveat to note for this BOF is that the specified client ID must allow “http://localhost” as the redirect_uri parameter.
Redirect URI
Unfortunately, because the redirect_uri parameter is set to localhost, it limits the number of client IDs that can be used with this technique - especially if you wanted to leverage the family of client ID (FOCI) abuse.
Searching through the currently known first-party client IDs that are both FOCI-enabled and support “http://localhost” yields very few results. I found only three:
Microsoft Azure CLI
Microsoft Azure PowerShell,
Visual Studio – Legacy
To prying eyes (the SOC), authenticating to any three of these could potentially seem unusual for a typical user and trigger an alert. To make matters more difficult, in mature tenancies, there’s a chance that these specific applications wouldn't have consent in the tenant (which unfortunately for me, was the case).
Microsoft’s Native Client Redirect URI
Microsoft provides a predefined redirect URI called the native client redirect URI (https://login.microsoftonline.com/common/oauth2/nativeclient
), which is used in OAuth flows for native applications like desktop or mobile apps. It essentially allows these apps to receive an authorization code from Entra without hosting a web server or using a custom URI scheme - the browser simply redirects to this URI with a “code” parameter, which the app captures and exchanges for access and refresh tokens.
To get a better understanding of the authcode flow in action, check out JUMPSEC’s tool called TokenSmith (made by Sunny Chau) which automates the process (although the URL and authcode must be copied between the target by hand). If you paste the URL into a browser where you’re signed in (and the client ID is allowed), you’ll see the authcode returned almost instantly.

It occurred to me that the authorization code also resides in the window title. If we extracted it from there, it could allow us to use the native client redirect URI instead, giving us access to a much larger range of FOCIs and removing the restriction of only being able to use FOCIs that allow "http://localhost" as the redirect URI.
There’s going to be multiple ways to do this, but the easiest to PoC I could come up with was extraction via GetWindowTextA
API. With this approach, we could carry out authcode flows against a greater number of FOCIs - including our favourites like Teams, Copilot, Edge, etc. This can make a massive difference in terms of OPSEC.
I noted the following first-party FOCIs allow the “native client” redirect URI:
BOF or it didn’t happen
As a basic proof-of-concept, I threw together a BOF that does the following:
Opens a browser window to the authcode flow URL (for a client ID and scope)
Extracts the returned code from the window title
Uses the code to request and obtain the tokens
beacon> entra-authcode-flow <clientid> <scope>
You can find the BOF and usage instructions at my GitHub, here.
Closing Thoughts
It goes without saying, but this is probably for edge-case scenarios only. In my eyes, obtaining the PRT is an easier and more reliable method for identity persistence. This was purely a concept that I wanted to try out, and I was pleased to see that it worked somewhat reliably for me and my team.
Again, the most important benefit with this approach (for the red team) is that all authentication requests and token requests originate from the compromised endpoint. When paired with your favourite post-exploitation tools like GraphSpy (especially via SOCKS) this could become a nice little technique to have on standby.
Thanks for reading!
Acknowledgements
Christopher Paschen (@freefirex) for creating the original get_azure_token BOF
FOCI research by SecureWorks and Dirk-Jan’s first-party scopes
V3ded and Jack Halon for proofreading and code review (thank you guys <3)
@ethicalsoup for some extra proofreading!