As Justin pointed out earlier in the thread, if the value `token` is clearly not a valid token, then returning an invalid_request response is fine. The key is if the value provided for the token parameter is a token, then the API MUST NOT leak whether the token was valid or not.

Is this not sufficient?

On 1/26/22 3:01 PM, Sergey Ponomarev wrote:
Thank you, Waren,

Sorry that was misleading, I meant literally the 'null'  as a string which may be because of a bug in the client.
That was an example taken from Thomas Broyer letter:
> For months, my AS received requests with token=Array, and now receives requests with token=null. Those are clearly bugs in the client code, and because I return a 200 OK, the developers aren't aware of it.

If you are interested here is the entire thread:
https://mailarchive.ietf.org/arch/msg/oauth/w68pbTcp2jjk4tzldnS0gOS127Q/

In an ideal world the AS may store even revoked tokens (or JWT kid) and clearly return some error in case of unknown token. At least for a day, for example. But at least it on a spec level there must be few words added into "Security Considerations" section



On Wed, 26 Jan 2022 at 20:13, Warren Parad <wpa...@rhosys.ch> wrote:

    According to RFC7009, I don't see anywhere which says you have to
    return a 200 for token=null. I interpret it as you return a 200,
    if the token passed would never have been accepted as a valid
    token. *Null* isn't an invalid token, it is an invalid value for
    the *token* parameter which is required.

           token   REQUIRED. The token that the client wants to get
        revoked.


    So the correct response is either an error immediately (returning
    a 4XX), or feel free to return the 200 and then the AS should
    redirect the user to a verified location with the *error *and
    *error_description* query parameters.

    I do see some gray area for what to do with real invalid tokens,
    i.e. the token signature is invalid. So some clarity on the
    definition of *invalid. *Since the spec talks about invalidation
    lots of times we should interpret it to mean *a token that has
    already been invalidated.* And I would interpret all other tokens
    as justifications for returning a 4XX status code.

        

    Warren Parad

    Founder, CTO

    Secure your user data with IAM authorization as a service.
    Implement Authress <https://authress.io/>.


    On Wed, Jan 26, 2022 at 6:44 PM Sergey Ponomarev
    <stok...@gmail.com> wrote:

        Hi and sorry for raising the four years old topic.

        As a recup I reported a SECURITY VULNERABILITY on OAuth 2
        specification level. It's minor (I hope) but still seen in the
        real
        world AS implementation.
        In short, to logout a user the revocation endpoint is called
        with the
        user's token. And by a the RFC7009 the AS must always return
        200 Ok
        status code even if the token is invalid:

        > The authorization server responds with HTTP status code 200
        if the token has been revoked successfully or if the client
        submitted an invalid token.
        > Note: invalid tokens do not cause an error response since
        the client cannot handle such an error in a reasonable way. 
        Moreover, the purpose of the revocation request, invalidating
        the particular token, is already achieved.

        So if a client just made an incorrect call e.g. token=null then it
        will anyway receive a 200 OK and the user will think that
        logout was
        successful and a session closed. But internally the token may be
        stored in many places and even shared  between
        microservices/UI and
        other parties and it will remain still working.

        Can anybody take some actions and at least make some errata to
        the spec?

        P.S. adding to CC authors of the spec

        On Tue, 22 May 2018 at 20:29, Sergey Ponomarev
        <stok...@gmail.com> wrote:
        >
        > What is also should be discussed and specified is revoking
        of expired token. For example in Keycloak you can invalidate a
        session by expired token:
        >>
        >> It should be possible to logout a session with a token that
        is expired. This is to make sure that a user can invalidate a
        session if there's a suspicion that the refresh/offline token
        has been leaked. In such a case it could be that the real user
        has an expired refresh token while an attacker has been able
        to refresh the token and obtain a new not expired refresh token.
        >
        >
        > KEYCLOAK-3302
        >
        > Think this is doubtful but makes sense.
        >
        > To summarize: we have to create some threat model with
        description of possible use cases.
        >
        >
        > On Tue, 22 May 2018 at 18:18, Sergey Ponomarev
        <stok...@gmail.com> wrote:
        >>
        >> From OAuth perspective we can't say that the token should
        have some structure: they can be any random value in case of
        reference (opaque) tokens. But the Google's OAuth Server
        responds in this case with 400 error "invalid_token".
        >> The same can be used for JWTs with invalid sign or issuer.
        >> So it would be better if specification allow OAuth servers
        to respond with this error code if it clearly know that token
        was invalid by format.
        >>
        >> On Tue, 22 May 2018 at 17:51, Thomas Broyer
        <t.bro...@gmail.com> wrote:
        >>>
        >>> IFF the server processes it!
        >>> RFC 7009 says “An authorization server MAY ignore this
        parameter, particularly if it is able to detect the token type
        automatically.” which BTW is exactly my case.
        >>>
        >>> For months, my AS received requests with token=Array, and
        now receives requests with token=null. Those are clearly bugs
        in the client code, and because I return a 200 OK, the
        developers aren't aware of it.
        >>>
        >>> If tokens have an expected "structure", I think AS should
        probably return an error when the token value clearly is not a
        token (at one point I may change my implementation to do just
        that). As soon as it looks like a potential token though, then
        200 OK sounds good to me.
        >>>
        >>> On Tue, May 22, 2018 at 4:34 PM Justin Richer
        <jric...@mit.edu> wrote:
        >>>>
        >>>> In that specific case, the token_type_hint value is
        invalid and can be rejected as an invalid_request.
        >>>>
        >>>>  — Justin
        >>>>
        >>>>
        >>>> On May 22, 2018, at 5:27 AM, Joseph Heenan
        <jos...@authlete.com> wrote:
        >>>>
        >>>>
        >>>> I think one important point Sergey raised was that the
        response to the client from submitting the wrong token is the
        same 200 response as submitting a valid token, and that hugely
        increases the chance that the developer of the client app
        might submit the wrong token and never realise. Making it
        easier for the developer of the client app to see that they've
        done something wrong and need to fix their implementation
        seems like a worthwhile goal to me, and that would appear to
        explain what google are thinking with their responses.
        >>>>
        >>>> An example of an easy to make error that would get a 200
        response is getting the values the wrong way around, i.e. a
        body of:
        >>>>
        >>>> token=refresh_token&token_type_hint=45ghiukldjahdnhzdauz
        >>>>
        >>>> (as token_type_hint may be ignored by the server.)
        >>>>
        >>>> The example Sergey gave of the developer accidentally
        sending the id token instead of the intended token seems quite
        likely to happen in the real world too, and a 200 response in
        that case does seem wrong to me.
        >>>>
        >>>>
        >>>> Joseph
        >>>>
        >>>>
        >>>> On 21 May 2018, at 22:29, Justin Richer <jric...@mit.edu>
        wrote:
        >>>>
        >>>> I’m with George here: revocation is almost a best-effort
        request from the client’s perspective. It sends a message to
        the server saying “hey I’m done with this token, you can throw
        it out too”. If the server does revoke the token, the client
        throws it out. If the server doesn’t revoke the token? Then
        the client still throws it out. Either way the results from
        the client’s perspective are the same: it’s already decided
        that it’s done with the token before it talks to the server.
        It’s an optional cleanup step in most  OAuth systems.
        >>>>
        >>>>  — Justin
        >>>>
        >>>> On May 21, 2018, at 5:08 PM, George Fletcher
        <gffletch=40aol....@dmarc.ietf.org> wrote:
        >>>>
        >>>> I'm not understanding how these different cases matter to
        the client? I doubt that the running code will be able to
        dynamically handle the error. So it seems this information is
        only relevant to the developers and not relevant from an end
        user and the client perspective.
        >>>>
        >>>> Also, for the 5 states you define, the effect of calling
        revocation is still that the token is "revoked" because the
        token is already not valid.
        >>>>
        >>>> So from an implementation perspective, where is the
        concern that developer will do the "wrong thing" without these
        more detailed error responses?
        >>>>
        >>>> Thanks,
        >>>> George
        >>>>
        >>>> On 5/19/18 5:41 PM, Sergey Ponomarev wrote:
        >>>>
        >>>> Hi,
        >>>>
        >>>> I developing an implementation of back channel token
        revocation endpoint. And I think we should reconsider and
        probably change the specification to improve error handling.
        >>>>
        >>>> Here we see several situations of error state:
        >>>> 1. token wasn't sent in request.
        >>>> 2. token is invalid by format i.e. not JWT or JWT with
        invalid signature
        >>>> 3. token is expired or token is even unknown
        >>>> 4. token was already revoked
        >>>> 5. token type is unsupported
        >>>>
        >>>> According to  RFC7009 OAuth 2.0 Token Revocation  section
        2.2 Revocation Response:
        >>>>
        >>>>> The authorization server responds with HTTP status code
        200 if the token has been revoked successfully or if the
        client submitted an invalid token.
        >>>>> Note: invalid tokens do not cause an error response
        since the client cannot handle such an error in a reasonable
        way.  Moreover, the purpose of the revocation request,
        invalidating the particular token, is already achieved..
        >>>>
        >>>>
        >>>> As you may see this section covers only case 3 and case 4
        but it's very unclear: calling token as "invalid" is very
        broad definition.
        >>>> I think we should take a look on each case separately:
        >>>>
        >>>> 1. token wasn't sent in request.
        >>>> Most implementations returns 400 status code, error:
        "invalid_request", error_description": "Missing required
        parameter: token".
        >>>> Note that returned error is not "invalid_token" but
        "invalid_request" and I think this should be correct behavior
        and should be clearly specified.
        >>>>
        >>>> 2. token is invalid by format i.e. not JWT or JWT with
        invalid signature
        >>>> This error is mostly related to JWT but for reference
        (opaque) tokens can be also applied (e.g. token is too long).
        >>>> Goolge OAuth returns 400 code with "error":
        "invalid_token" and I think this is correct behavior.
        >>>> The client can have a bug and sends invalid tokens so we
        should return an error response instead of 200 status.
        >>>>
        >>>> 3. token is expired or even unknown
        >>>> Spec says that IdP should return 200 in this case but in
        case of unknown token this may be a symptom of a bug on client
        side. Even if IdP can clearly determine that token is expired
        (in case of JWT) this is hard to determine in case of
        reference token that was removed from DB.
        >>>> So personally I think that from security perspective it's
        better to response with 400 status because client can have a
        bug when it's sends some unknown token and think that it was
        revoked while it wasn't.
        >>>>
        >>>> For example Google OAuth revocation endpoint
        implementation do not follow the spec and returns 400 Bad
        Request with error message "Token is revoked or expired".
        >>>>
        >>>> 4. token was already revoked
        >>>> The same as above: this can be a bug in a client and we
        should return 400 status. In case of reference token which was
        removed from DB we can't distinguish that the token was
        revoked or even existed so this situation is the same as
        unknown token.
        >>>>
        >>>> 5. token type is unsupported
        >>>> For this case specification introduces a new error code
        for case 5 in section 2.2.1. Error Response :
        >>>>>
        >>>>> unsupported_token_type:  The authorization server does
        not support the revocation of the presented token type.  That
        is, the client tried to revoke an access token on a server
        not   supporting this feature.
        >>>>
        >>>> But it would be better to mention that revocation of ID
        token (which can be is considered as "public" and not used to
        auth) definitely should cause this error.
        >>>>
        >>>> It would be great if we discuss this cases and improve
        specification.
        >>>>
        >>>> P.S. Also it may be worse to mention that specification
        says that content of successful response is empty but status
        code is 200 instead of 201 "No Content".
        >>>>
        >>>> Regards,
        >>>> Sergey Ponomarev
        >>>>
        >>>>
        >>>> _______________________________________________
        >>>> OAuth mailing list
        >>>> OAuth@ietf.org
        >>>> https://www.ietf.org/mailman/listinfo/oauth
        >>>>
        >>>>
        >>>> _______________________________________________
        >>>> OAuth mailing list
        >>>> OAuth@ietf.org
        >>>> https://www.ietf.org/mailman/listinfo/oauth
        >>>>
        >>>>
        >>>> _______________________________________________
        >>>> OAuth mailing list
        >>>> OAuth@ietf.org
        >>>> https://www.ietf.org/mailman/listinfo/oauth
        >>>>
        >>>>
        >>>> _______________________________________________
        >>>> OAuth mailing list
        >>>> OAuth@ietf.org
        >>>> https://www.ietf.org/mailman/listinfo/oauth
        >>>>
        >>>>
        >>>> _______________________________________________
        >>>> OAuth mailing list
        >>>> OAuth@ietf.org
        >>>> https://www.ietf.org/mailman/listinfo/oauth
        >>>
        >>> _______________________________________________
        >>> OAuth mailing list
        >>> OAuth@ietf.org
        >>> https://www.ietf.org/mailman/listinfo/oauth
        >>
        >>
        >>
        >> --
        >> Sergey Ponomarev, skype:stokito
        >
        >
        >
        > --
        > Sergey Ponomarev, skype:stokito



-- Sergey Ponomarev,
        stokito.com <http://stokito.com>

        _______________________________________________
        OAuth mailing list
        OAuth@ietf.org
        https://www.ietf.org/mailman/listinfo/oauth



--
Sergey Ponomarev <https://linkedin.com/in/stokito>,
stokito.com <http://stokito.com>

_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth
_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth

Reply via email to