This response is probably going to go into too much detail. Why you see the different behavior for Access Token validation is because of the OAuth 2.0 spec never really defined it. Going into the history of things, OAuth was established well before JWT, and there are still some missing pieces. OAuth 2.0 says you should treat the access token as opaque from the client perspective but, nothing for how a Resource Server should validate a JWT bearer token that was generated by an Authorization Server.
Below is how the OAuth 2.0 spec defines access token validation:
The client accesses protected resources by presenting the access
token to the resource server. The resource server MUST validate the
access token and ensure that it has not expired and that its scope
covers the requested resource. The methods used by the resource
server to validate the access token (as well as any error responses)
are beyond the scope of this specification but generally involve an
interaction or coordination between the resource server and the
The method in which the client utilizes the access token to
authenticate with the resource server depends on the type of access
token issued by the authorization server. Typically, it involves
using the HTTP “Authorization” request header field [RFC2617] with an
authentication scheme defined by the specification of the access
token type used, such as [RFC6750].
You can see how implementers can go down the rabbit hole here.
OpenID came into play, and there was already some anxiety around how different resource servers and authorization servers interacted. OpenID Connect got opinionated on the token type, claims, and how they are validated. This definition was a great thing, JWTs were well defined and fit well.
From the OpenID Connect spec on how you should treat OpenID Connect
188.8.131.52. ID Token Validation
Clients MUST validate the ID Token in the Token Response in the following manner:
The Issuer Identifier for the OpenID Provider (which is typically obtained during Discovery) MUST exactly match the value of the iss (issuer) Claim.
The Client MUST validate that the aud (audience) Claim contains its client_id value registered at the Issuer identified by the iss (issuer) Claim as an audience.
Our security team agrees that this discovery mechanism can mitigate a particular type of attack regardless of the token type. OAuth 2.0 has discovery in a similar way that OpenID Connect does. We took it as a requirement for our Okta JWT verifier libraries (since they are using OpenID and OAuth discovery) to provide this mitigation. This does require the clients to specify an issuer, and the okta integrations and JWT verifiers initialize based on the discovery mechanism to make sure this type of attack can’t be exploited.
Hope this helps,