A signed JWT sounds like the magical solution in theory. What I see in practice, is that application often require multiple third-party authentication providers (google/microsoft/etc), which indirectly requires that the application provisions a local user-account and needs to look it up on each request. This can be solved by using a service like Azure B2C, Auth0, Okta, etc, but then where do you maintain other user-profile information specific to your application? You can integrate with the external service, but how hard do you want to lock yourself to a single vendor?
Apart from that, and I’m probably unlucky, but all applications I had to create in the last 10 years required more complex authorization rules on object level rather than ‘this user has role X’. This also requires us to look up access rules for each request + using the external sub-claim as a unique identifier between services is also very limiting, so we’re back to local user-account provisioning.
In the end, the client application (front-end) stops reading out JWT claims in favor of doing a back-end request to get the required information. The JWT has now turned into a dead access token, which is prone to XSS and can be read out by browser extensions.