About the necessity for the Resource Server to authenticate
According to rfc7662 Section 2.1.,
"the endpoint (?) MUST require some form of authorization to access this endpoint".
( What we could have done to comply with this specification :
This implementation is waiting for a bearer access token issued for a registered client.
Where this access token is coming from is depending upon the service.
It may have been obtained from the server by the caller as a client application.
Or, if the caller is a resource server queried by a client application, it may have been passed to the caller by the application.)
We submit to the reader’s sagacity the following observations:
The purpose of this authorization is "To prevent token scanning attacks".
This kind of attacks are usually mitigated at the firewall level in relation with the service.
For instance, with Apache, we could set a HTTP Basic authentication at the directory level.
Then, on a WHM/cPanel managed server, we could use CSF/LFD to block repetitive login failure.
We could also configure a particular Apache Modsec rule for that purpose.
More generally, mitigation of attacks is better performed upstream than at the application level. It induces a lesser or no computation load on the authorization server.
For the resource server to authenticate itself, it must be registered as a client application [1], which assumes that it belongs to the corporate realm.
This is true in most cases, but we may wish that any foreign resource server can check JWT.
About the purpose of Introspection
Validate the signature
The payload of the JWT token is not encrypted, only encoded. Its content is immediately readable by the RS before validation of the signature.
So, the RS needs introspection to verify that the signature is valid (if not validating it locally using the public key).
Authenticate the application querying the RS
Furthermore, the purpose of passing a token to a RS is to tell him he may answer to its requester and what data it can pass in its response.
An attacker could have stolen a JWT and use it with his own application. The risk is having a RS respond to an unauthorized application and/or user. It is therefore essential to authenticate the application querying the RS in order to prevent responding to a malware (see below).
This said, what specific task should be completed by Introspection and what must be in the response ?
About Introspection response
According to section 2.2. from rfc7662, the only required member is "active", a boolean flag indicating the validity of the token seen from the server that issued it.
It’s more than just validating the signature because it "indicates that a given token was issued by this authorization server, was not revoked by the resource owner, ...".
But including in this value the condition "and is in its given validity time window" does not seem irrelevant: the RS already got the information from the payload. On the other hand, the token could have been invalidated at the server level, and it is this information that introspection will bring. In passing, note that there is no link between the lifetime of the access token and that of the identity token. There is a possibility to revoke the access token, but what about the identity token?
Note that Introspection should also be usable to validate a JWT access token, with fewer and different members. that’s another reason for not authoritatively specifying members.
Preventing the Resource Server responding to a malware
That is the central question!
The specification recognized the question, but don’t give a normalized answer. It is stated in section 2.1.:
"The introspection endpoint MAY accept other OPTIONAL parameters to provide further context to the query. For instance, an authorization server may desire to know the IP address of the client accessing the protected resource to determine if the correct client is likely to be presenting the token. The definition of this or any other parameters are outside the scope of this specification,..."
We propose to implement it this way :
If the Resource Server calling the Introspection endpoint is passing the IP of its own requester in the ’requester_ip’ parameter, we must check that this IP is in the same subnet that the client application identified by the ’aud’ claim. See : Verifying the origin of the request received by a resource server.
About adapting the response to the Resource Server...
It is stated in section 2.2.:
"The authorization server MAY respond differently to different protected resources making the same request. For instance, an authorization server MAY limit which scopes from a given token are returned for each protected resource to prevent a protected resource from learning more about the larger network than is necessary for its operation."
It seems very difficult to implement. In the given example, dealing with scopes, the RS must call introspection with more parameters, or the AS should have information about the RS.
We think that the scopes defining the rights have a meaning that should be interpreted by the protected resource itself, the authentication server having to transmit them transparently. See : Add additional claims to the JWT token.
This prescription can be applied in an enterprise domain for particular applications, so it will not be considered in our "minimal and compatible implementation".
... or not responding at all
It is stated in section 4.:
"If the token can be used only at certain resource servers, the authorization server MUST determine whether or not the token can be used at the resource server making the introspection call".
This prescription is nothing more than a radical variation of the previous one. We will treat it the same way.
Proposal of an Introspection Controller for the library
A "minimal and compatible implementation" of the Introspection controller would have following characteristics:
will be limited to validating the JWT signature with the option of client IP checking (’requester_ip’ parameter), making no assumption of what the token is used for,
will not necessitate authentication of caller,
will accept Bearer token preferably to posting token.
Follow this work on GitHub
See the fork:
Add more commits by pushing to the introspection branch on https://github.com/bdegoy/oauth2-server-php-a1
Test with:
https://github.com/bdegoy/oauth2-server-php-introspection-test
Discuss:
https://github.com/bshaffer/oauth2-server-php/pull/964