Salesforce, Python, SQL, & other ways to put your data where you need it

Need event music? 🎸

Live and recorded jazz, pop, and meditative music for your virtual conference / Zoom wedding / yoga class / private party with quality sound and a smooth technical experience

OIDC issuers: passwordless isn't trustless

12 Dec 2025 🔖 devops integration
💬 EN

Table of Contents

Right now, I’m a little stuck deliberating how much I trust the OpenID Connect (“OIDC”) secretless authentication (“authN”) protocol when the OIDC “issuer” isn’t, at the scale of, say, a hyperscaler cloud service provider.


Microsoft is encouraging OIDC

I first encountered OIDC in early 2024, after Microsoft started encouraging customers to convert their Azure DevOps (“ADO”) Azure Pipelines service connections and their GitHub Actions azure/login invocations.

Microsoft encouraged customers to abandon secretful / passwordful flows for authenticating into assuming the identity of an Entra service principal, and instead to use the new “secretless” / “passwordless” approach that leverages OIDC identity “federation.”

Since mid-May 2025, Microsoft also seems to be encouraging customers whose Azure applications were, for whatever reason, unable to do the work they needed to over Azure system-assigned managed identities and Azure RBAC, to do a similar conversion from secret/certificate-based authentication to OIDC federated credentials.

Anywhere that Microsoft customers can eliminate secrets and certificates, and simply trust Microsoft to manage the encryption and authentication and rotation and whatnot, Microsoft has been encouraging customers to do so. Personally, I’m bought in on that idea. Microsoft’s got the scale to do it right and do it reliably, in ways that most of its cloud-service customers simply don’t.


How OIDC works

Instead of attaching a secret hash, or a public key, to the Entra App Registration responsible for the existence of a given Entra service principal, you attach a “don’t worry, I’m expecting to hear (from the ABC-XYZ Azure Pipelines service connection / from the 123-456 GitHub Actions workflow) – you can let it become you” note to the Entra App Registration. This is called attaching a “Federated Credential” to it.

  • Note: You can also attach Federated Credentials to Azure User-Assigned Managed Identities, which also become Entra Service Principals under the hood.
    • Azure system-assigned managed identities are a third type of thing that become Entra Service Principals under the hood, but by design, you’re not allowed to attach your own Federated Credentials to them. Azure itself controls them fully.

Seriously – all you do is punch in some details about your ADO Service Connection or your GitHub Actions workflow into Entra, and Entra just … says:

“Cool, I’ll watch for it.”

So! How does Entra ensure that no hacker whose computer puts out an HTTP request knocking on Entra’s door, asking to “become” a protected Entra Service Principal, could ever successfully manage to lie to Entra about being an ADO service connection, or a GitHub workflow?

After all, Entra is no longer going to ask that computer to “prove it” by owning a password/secret or a certificate private key!

What Entra does is visit the OIDC “issuer” URL that you said, as part of the notes in your “Federated Credential” you created, that legitimate traffic from ADO or GitHub would be coming from. Entra looks to see what cryptographic public key is advertised at that URL.

If the current incoming HTTP request doesn’t mathematically check out to clearly have been signed using a private key that corresponds to that public key, then Entra can ignore the incoming HTTP request, because it’s obviously illegitimate.

Pretty clever, huh?


Where OIDC could fail

Of course, this presumes that the “issuer” URL you told Entra to visit, so as to obtain a copy of that public key, is a URL that the legitimate owner of the URL can adequately protect from hackers.

If the OIDC issuer’s domain name ownership, DNS records, or web servers serving the validation-URL’s traffic, are compromised, then the whole system can be compromised.

All a hacker would have to do is make sure that the validation-URL you’ve put on file as the “Federated Credential” OIDC “issuer” displays the hacker’s cryptographic public key when visited by Entra, instead of displaying the legitimiate issuer’s cryptographic public key.

At that point, Entra would authenticate the attacker’s requests, while rejecting legitimate traffic from, say, Azure DevOps or GitHub.


Hopefully hyperscalers have the staff to protect OIDC issuer URLs

I’m nervous, because over my life, I’ve seen a lot of news stories that involved hacking someone, and making given URL they thought they owned display malicious content. Especially when that “someone” wasn’t adequately resourced to defend themselves, and the hacker was determined enough.

For Microsoft / Amazon / Google / etc.-sized vendors, they can afford the staff necessary to protect those OIDC “issuer” validation-URLs. The ones that prove GitHub is really GitHub, and ADO is really ADO. (And to notice and fix things darned fast, if they do get compromised.)

I suppose smaller companies whose entire sales pitch is “modernizing identity and access management” (e.g. being an identity provider that competes with hyperscalers’ IdPs, such as Entra, in its own right) probably prioritize investing in proper controls, service-level agreements, incident response capacity, etc. as well. For example, Auth0/Okta.


Have good conversations

This doesn’t mean you shouldn’t use OIDC instead of secrets/certificates with smaller vendors’ integrations into your Entra tenant.

In theory, a compromised short-lived OIDC token in a “secretless”/”passwordless” authentication flow sounds less-bad than a compromised long-lived secret/password/certificate, and, like … yeah, I imagine it probably is, once your enterprise gets its ducks in a row about incident response in case of compromise, risk management to avoid incidents/compromises, etc.

And it’s not like you don’t have to trust vendors in “secretful” flows, either. You have to decide that you trust that they’ll properly salt and hash the secrets/passwords you type into their user interfaces, or protect the private keys you upload into them, appropriately. You’re not having to trust the vendor more – you’re just having to trust a different one of its departments. You’re shifting trust from “will they protect their copy of your secret/certificate?” (which perhaps they’ve got staff who are accustomed to managing, at a level you approve of) to “will they protect their own OIDC issuer signing key content?” (which perhaps they don’t yet have the capacity to do, to a level you approve of). Both require trust in your vendor – just in different operational security practices that they have to do each day.

(Could be a good use case for vendor security questionnaires, etc.?)

But if your enterprise has a certain set of assumptions well-baked into the culture about how to govern the threat of compromised secrets/passwords/certificates, I’d hate for it to let its guard down (rather than just re-shape the caution more appropriately to OIDC’s particularities – e.g. making sure your anomaly detection monitoring (e.g. on token exchanges, on federated credential login/usage in general, etc.), your IdP conditional access rules, etc. are all ready to detect, prevent, and handle OIDC issuer compromises as well as they can currently detect, prevent, and handle secret/certificate compromises).

Personally, my gut is telling me that it seems valuable to evaluate each potential OIDC issuer vendor-by-vendor, one at a time, when considering migrating from nonhuman / “workload” / “system” authentication into your identity provider over secrets/credentials vs. over identity federation / OIDC.


Auditing Entra for non-Microsoft OIDC issuers

Accordingly, I wrote this little PowerShell script for a company I was consulting with, so they could audit whether anyone had yet added a non-Microsoft domain name to the issuer property of an Entra App Registration or Azure User-Assigned Managed Identity’s Federated Credential.

Anyone who can list all directory items in Entra via Microsoft’s Graph API should be able to run it on their machine, provided they’ve also installed the appropriate PowerShell modules (Microsoft.Graph.Authentication and Microsoft.Graph.Applications) into their Powershell environment.

Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Applications


Connect-MgGraph -NoWelcome


# Azure user-assigned managed identities (UMIs)
$entraSPs = Get-MgServicePrincipal -All -ExpandProperty 'federatedIdentityCredentials' # Fetch every single Entra Service Principal; UMIs put FedCreds here
$entraSPsWithFedCreds = $entraSPs | Where-Object { $_.federatedIdentityCredentials.Count -gt 0 } # Filter it down to the ones with FedCreds
$entraSPFedCredIssuerDomains = @() # Array into which we will store the FedCred issuer domain names we find
Write-Host('')
Write-Host("~~~Begin:  quick-parse of $($entraSPsWithFedCreds.Length) Service Principals (based on Azure UMIs) looking for FedCreds~~~")
ForEach ($servicePrincipal in $entraSPsWithFedCreds) {
    ForEach ($fedCred in $servicePrincipal.FederatedIdentityCredentials) {
        if ($fedCred.issuer) {
            $issuerUri = [System.Uri]$fedCred.issuer # Read the issuer from the FedCred
            $issuerDomainName = $issuerUri.Host # Read the domain name from the issuer
            $entraSPFedCredIssuerDomains += $issuerDomainName # Add the domain name into the array
        }
    }
}
Write-Host("~~~End:  quick-parse of $($entraSPsWithFedCreds.Length) Service Principals (based on Azure UMIs) looking for FedCreds~~~")
Write-Host('')
$uniqueEntraSpFedCredIssuerDomains = $entraSPFedCredIssuerDomains | Sort-Object -Unique # Filter the FedCred domain names list into a set
$uniqueEntraSpFedCredIssuerDomains # Display partial results


# Entra app registrations (AppRegs)
$entraAppRegs = Get-MgApplication -All -ExpandProperty 'federatedIdentityCredentials' # Fetch every single Entra Service Principal; UMIs put FedCreds here
$entraAppRegsWithFedCreds = $entraAppRegs | Where-Object { $_.federatedIdentityCredentials.Count -gt 0 } # Filter it down to the ones with FedCreds
$entraAppRegFedCredIssuerDomains = @() # Array into which we will store the FedCred issuer domain names we find
Write-Host('')
Write-Host("~~~Begin:  quick-parse of $($entraAppRegsWithFedCreds.Length) AppRegs looking for FedCreds~~~")
ForEach ($entraApp in $entraAppRegsWithFedCreds) {
    ForEach ($fedCred in $entraApp.FederatedIdentityCredentials) {
        if ($fedCred.issuer) {
            $issuerUri = [System.Uri]$fedCred.issuer # Read the issuer from the FedCred
            $issuerDomainName = $issuerUri.Host # Read the domain name from the issuer
            $entraAppRegFedCredIssuerDomains += $issuerDomainName # Add the domain name into the array
        }
    }
}
Write-Host("~~~End:  quick-parse of $($entraAppRegsWithFedCreds.Length) AppRegs looking for FedCreds~~~")
Write-Host('')
$uniqueEntraAppRegFedCredIssuerDomains = $entraAppRegFedCredIssuerDomains | Sort-Object -Unique # Filter the FedCred domain names list into a set
$uniqueEntraAppRegFedCredIssuerDomains # Display partial results


# Combined UMIs and AppRegs
$uniqueFedCredIssuerDomains = ($uniqueEntraSpFedCredIssuerDomains + $uniqueEntraAppRegFedCredIssuerDomains) | Sort-Object -Unique
Write-Host('')
Write-Host("~~~Stitched-together list (count:  $($uniqueFedCredIssuerDomains.Length)):~~~")
Write-Host('')
$uniqueFedCredIssuerDomains # Display final results

If you find any that seem to be from non-Microsoft issuers, you can edit the PowerShell script to, say, Write-Host the ID of whichever object you’re looping over, whenever the $issuerDomainName seems to be non-Microsoft, and go investigate those one-by-one, and decide how you feel about that.

(Obviously, your identity and access management teams, security teams, etc. are going to be the ones to ping – don’t just wildcard say “I guess it’s fine” or “I hate this” on your own, in an enterprise context.)

Hope that helps.

--- ---