Microsoft Technologies based on the .NET software framework. Miscellaneous topics that do not fit into specific categories.
Hi @Kmcnet ,
There's one small misunderstanding worth clearing up:
the api accepts the JWT, contacts the issuer and validates this request
The API does not contact the issuer on every request. A JWT is self-verifying: the issuer signs it, and the API verifies that signature locally using the shared secret (symmetric) or the issuer's public key (asymmetric). If the signature checks out, the API knows the token wasn't tampered with and came from the matching key.
With asymmetric keys the API does fetch the issuer's public keys once from its discovery endpoint (.well-known/openid-configuration) and caches them — but that's a one-time fetch, not a per-request round trip. That's why JWTs are fast and scalable.
Wouldn't I just generate a hard coded symmetric key then validate it?
Technically yes, that's exactly how the sample code works — the client signs with a symmetric key, the API validates with the same key, no third party involved. It's fine for local testing and for server-to-server calls where both ends are back-end servers you control.
But it breaks down for a Windows desktop app. A desktop app is a public client — it runs on the user's machine and can be decompiled. Anyone who extracts that symmetric key can mint their own tokens and impersonate any user, indefinitely. The deciding factor isn't how many apps you have; it's who can get at the key.
That's what an identity provider solves: the signing key stays on a locked-down server, the app just asks for a token and passes it to your API.
- Windows app asks the identity provider to authenticate the user
- Identity provider (holding the private key on its own servers) mints the token
- Windows app sends that token to your API
So even with one app and one API, a desktop client still needs a provider — Entra, Auth0, Keycloak, or your own via OpenIddict / ASP.NET Core Identity.