[OAUTH-WG] Token Revocation error codes

Sergey Ponomarev <stokito@gmail.com> Sat, 19 May 2018 21:42 UTC

Return-Path: <stokito@gmail.com>
X-Original-To: oauth@ietfa.amsl.com
Delivered-To: oauth@ietfa.amsl.com
Received: from localhost (localhost []) by ietfa.amsl.com (Postfix) with ESMTP id AF48A12EB01 for <oauth@ietfa.amsl.com>; Sat, 19 May 2018 14:42:04 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.998
X-Spam-Status: No, score=-1.998 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([]) by localhost (ietfa.amsl.com []) (amavisd-new, port 10024) with ESMTP id tBfCJ72JFQIF for <oauth@ietfa.amsl.com>; Sat, 19 May 2018 14:42:02 -0700 (PDT)
Received: from mail-ot0-x22b.google.com (mail-ot0-x22b.google.com [IPv6:2607:f8b0:4003:c0f::22b]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id C135112E041 for <oauth@ietf.org>; Sat, 19 May 2018 14:42:01 -0700 (PDT)
Received: by mail-ot0-x22b.google.com with SMTP id t1-v6so12996960oth.8 for <oauth@ietf.org>; Sat, 19 May 2018 14:42:01 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=SCwiPZlo+/PcxjAfh4ktsHdoPptphpaT9VcNA6T6UQ0=; b=gz5j9iU9By1e7he1RTH1RJkoyDONejyY5XeK5f2Hzdhe6dPG/5mPvhdoLIGo3d+Mos 7wLtPbgzoYZ8yXAHTH76uMu8/Gs3sKPMu4Fd90Qv+8E4te+SSSvSHRr9nKrzK1atg1uR da6WQGOHjnOLu9lIlOlBCQMOBZd3FZyVBb8bcgxkhXO/mpR2aYrMdRzVrREXwOk3ahBM //zk5KucsuKTfjUlBv5eLqusDb4zVXwS4MZ1T6zseCYKQE3Kg6DRelJi+46rQ9Ai5j3z hG7TE7w0fDDWVZ5Vj3qSmmVlcJrQ4LD2MW/A5oZJMavwWzzJYWzzMfiomeDk9J/1GMHG SX1Q==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=SCwiPZlo+/PcxjAfh4ktsHdoPptphpaT9VcNA6T6UQ0=; b=BtBsZibuBu/y8TrwO4I/Bg1EoU47omUnHG4KcrPMhkb5p/FxyYpQ42hIx0DfXl4BiH o9Jre28yNJlzDRltyQR4wV0fK3KLCxuiB+4zLR5hN4wIuO391q9+IzvAU4auLW9RV93K 1EXOdF9RPnDXOouGJj4bMDXE7DDIhl9yv0zJXvXgrR38+3eZ6PIUpOZjLdcyFMBocfZv lYvJde1o+kEnywjRE1RfE4bQ4X7rmNGl1YoJqc41petpqKvvCbNIx8wD6YLgO7GFTY9C Bi2XMtjV2OT7aHmbbmr0NEwf1+fbJCtkKq0iW4zZzISYgdB5y1g22WaNPHXMB6dfC5vw 9WCg==
X-Gm-Message-State: ALKqPweKRFvPlKCqtPq76hh4WsHbRgrWoQACQ52ywdn3FwW442yC+qFm 7vAEiK50chAECYUibBXivHZoSKgu/UCYhEAufydttXaT
X-Google-Smtp-Source: AB8JxZqt8QmXFiUg8iYsVfV2GJ7+0FBjXr9UjeniBRP26LNY1wscziqYI97ODKlXteCHFHJdaxrWQKexFv4ObrJ4g8g=
X-Received: by 2002:a9d:7259:: with SMTP id a25-v6mr10260803otk.267.1526766121003; Sat, 19 May 2018 14:42:01 -0700 (PDT)
MIME-Version: 1.0
From: Sergey Ponomarev <stokito@gmail.com>
Date: Sun, 20 May 2018 00:41:24 +0300
Message-ID: <CADR0UcWmKLmy=NcvCAH+6C2c55vgux1=z+7xpMHMApYLV-VQrw@mail.gmail.com>
To: oauth@ietf.org
Content-Type: multipart/alternative; boundary="0000000000004c2dbf056c95f08b"
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/w68pbTcp2jjk4tzldnS0gOS127Q>
Subject: [OAUTH-WG] Token Revocation error codes
X-BeenThere: oauth@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: OAUTH WG <oauth.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/oauth>, <mailto:oauth-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/oauth/>
List-Post: <mailto:oauth@ietf.org>
List-Help: <mailto:oauth-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/oauth>, <mailto:oauth-request@ietf.org?subject=subscribe>
X-List-Received-Date: Sat, 19 May 2018 21:42:05 -0000


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
<https://tools.ietf.org/html/rfc7009>  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

Sergey Ponomarev <http://www.linkedin.com/in/stokito>