I am the assigned Gen-ART reviewer for this draft. The General Area Review Team (Gen-ART) reviews all IETF documents being processed by the IESG for the IETF Chair. Please treat these comments just like any other last call comments. For more information, please see the FAQ at . Document: draft-ietf-oauth-status-list-13 Reviewer: Dale R. Worley Review Date: 2025-11-11 IETF LC End Date: 2025-11-11 IESG Telechat date: [not known] Summary: This draft is basically ready for publication, but has nits that should be fixed before publication. None of these issues seem to be serious problems. I have grouped them below by how broad their scope is across the document rather than how technically severe they are. Major issues: It appears to be that the intention is that when a token expires, it is *not* marked as INVALID in the status list, that its "status" remains VALID. This seems to be done to ensure that status lists compress well (as only a small proportion of tokens are invalidated before they expire) and (I think) to prevent attackers from being able to discern the rate of allocation of tokens. Is this correct? In any case, how ordinary expiration interacts with the VALID status should be detailed in sec. 7.1. And if expired tokens are marked INVALID, there are a number of places in the document where certain special considerations regarding revocations would need to be extended to include expirations as well. The first example in sec. 4.1 shows an extra or padding byte following the defined 16 bits but gives no explanation. This points out that that a step 3.5 is needed that defines when/where/how padding is used. This is very important as there is no assurance that the defined bits for the tokens form a compete byte. We've specified that the unused bits are at the high end of the last byte, but don't specified here what values are put into those bits. And it's likely that we want to allow the list to contain trailing bytes whose bits are (so far) unassigned, but that hasn't been stated, nor has what values can be put in them. At the least, this needs a reference to sec. 13.3, which discusses default status values which would be used for padding. 7.1. Status Types Values The Status Type value 0x03 and Status Type values in the range 0x0B until 0x0F are permanently reserved as application specific. Please confirm that 0x0B was intended and not 0x0C (because 0x0B-0F contains 5 values, which is an unusual grouping). 9.3. Status List Aggregation in JSON Format Is there a reason that there is no parallel "Status List Aggregation in CBOR Format"? Sec. 4.3 defines an "aggregation_uri" datum for CBOR Status Lists. Minor issues: A number of places say "amount of" where "number of" would be more proper, as the quantities involved are all integers. (The exception to this is "amount of time", which is the preferred form.) The figures on pages 5, 30, 34, and 43 are not in ASCII. I don't know if that is allowed these days, but it wasn't in the past. The line 78dadbb918000217015d # "xÚÛ¹\x18\x00\x02\x17\x01]" at the bottom of sec. 4.3 contains non-ASCII characters which seem to be unintended. Similar lines appear on pages 17 and 21, but they may be intended. ISTM better to give these characters as hex escapes. Starting in sec. 4.1 item 1 there is a parameter named "bits". This is difficult to read because "bits" is already used (frequently) as a noun with the usual meaning. Sec. 4.1 item 2 defines a parameter "size", although its use is less clear and ISTM less confusing. Perhaps change these to BITS and SIZE to distinguish the various uses. Nits/editorial comments: Abstract This specification defines a mechanism called Token Status List (abbreviated TSL), data structures and processing rules for representing the status of tokens secured by JSON Object Signing and Encryption (JOSE) or CBOR Object Signing and Encryption (COSE), such as JWT, SD-JWT VC, CBOR Web Token and ISO mdoc. It also defines an extension point and a registry for future status mechanisms. The meaning of "status mechanisms" in the last sentence is unclear. Perhaps amend the first sentence to This specification defines a "status mechanism" called Token Status List ... Table of Contents ... Size comparison . . . . . . . . . . . . . . . . . . . . . . . . . 57 Status List size for varying sizes and revocation rates . . . . 57 Compressed array of UUIDv4 (128 bit UUIDs) for varying sizes and revocation rates . . . . . . . . . . . . . . . . . . . 58 Test vectors for Status List encoding . . . . . . . . . . . . . . 58 1 bit Status List . . . . . . . . . . . . . . . . . . . . . . . 59 2 bit Status List . . . . . . . . . . . . . . . . . . . . . . . 59 4 bit Status List . . . . . . . . . . . . . . . . . . . . . . . 60 8 bit Status List . . . . . . . . . . . . . . . . . . . . . . . 62 Document History . . . . . . . . . . . . . . . . . . . . . . . . 70 ... ISTM that "Size comparison", "Test vectors for Status List encoding", and "Document History" are appendixes and they should be given numbers/letters and their listed subsections given numbers/letters. 1. Introduction The arrows in the image at bottom of p. 5 show the functional relationship between the depicted actors. E.g the arrow from Issuer to Holder is labeled "issue Referenced Token", meaning "Issuer issues Referenced Token to Holder". But the "update status" arrow isn't quite right, or at least, not as clear, since it's possible that in an architecture the Status Issuer will actively obtain the updated status by querying the Issuer, and thus be the actor that "updates". I suggest labeling the arrow "provide status", meaning "Issuer provides status to Status Issuer", similarly to the "provide Status List" arrow. Furthermore, the document defines an extension point that enables other specifications to describe additional status mechanisms and creates an IANA registry. "creates an IANA registry" seems to not clearly describe what is registered. Perhaps move it earlier in the sentence as "creates an extension point and IANA registry that enables ...". 1.2. Rationale This specification seeks to find a balance between scalability, security and privacy by minimizing the status information to mere bits (often a single bit) and compressing the resulting binary data. Perhaps "by representing statuses in the minimum number of bits, packing the bits into an array, and compressing the array." 1.4. Prior Work Representing a status with bits in array is a rather old Perhaps better "Representing an array of statuses with bits in an array ...", since the crux of the status list is that there are a lot of statuses and that the array of them compresses well. 1.5. Status Mechanisms Registry This specification establishes the IANA "Status Mechanisms" registry for status mechanisms and registers the members defined by this specification. Other specifications can register other members used for status retrieval. At this point (as opposed to in the Abstract) it should be made clear that there are two registries, one for JWT and one for CBOR. Thus, This specification establishes IANA "Status Mechanisms" registries for status mechanisms for JWT tokens and for status mechanisms for CBOR tokens and registers the members defined by this specification. 2. Conventions and Definitions Probably better to say "Normative terminology" as this section doesn't really contain definitions, those are in sec. 3. 3. Terminology Referenced Token: A cryptographically secured data structure that contains a "status" claim that is referencing a mechanism to retrieve status information about this Referenced Token. s/that is referencing/that references/ base64url: Denotes the URL-safe base64 encoding without padding as defined in Section 2 of [RFC7515] as "Base64url Encoding". I would clarify this as "the URL-safe base64 encoding without padding of a byte sequence as defined...". 4.1. Compressed Byte Array Tokens within the byte array. The status of each Referenced Token is identified using an index that maps to one or more specific bits within the byte array. The index starts counting at 0 and ends with amount of Referenced Tokens - 1 (being the last valid entry). The bits within an array are counted from the least significant bit ("0") to the most significant bit ("7"). All bits of the byte array at a particular index are set to a status value (see Section 7 for more details on the values). I think this would be clearer: Each Referenced Token is assigned a distinct index from 0 to one less than the number of Referenced Tokens assigned to the status list (which may grow over time). Each index identifies a contiguous block of BITS bits in the byte array, with the blocks being packed into bytes from the least significant bit to the most significant bit These bits contain the encoded status of the Referenced Token. The following example illustrates the byte array of a Status List that represents the statuses of 16 Referenced Tokens with a bits of 1, requiring 2 bytes (16 bits) for the uncompressed byte array: The examples are awkward, as the first part treats the described statuses as simply the binary "0" and "1", but the second adds a status SUSPENDED and assigns it a value of 2 (which probably ought to be "10") but neither gives a complete status table. Better to present the example statuses as pure binary (0 and 1 in the first; 00, 01, and 10 in the second) or as complete name/value tables (VALID=00, and INVALID=01 in the first; VALID=00, INVALID=01, and SUSPENDED=10 in the second). 4.2. Status List in JSON Format * The StatusList structure is a JSON Object and MUST contain at least the following members: This is awkward since it says "MUST contain" but one item is OPTIONAL. What is the typical way to express this in JSON specifications? The following example illustrates the JSON representation of the Status List with bits 1 from the example above: The following example illustrates the JSON representation of the Status List with bits 2 from the example above: Probably better to say "first example above" and "second example above". Or maybe "with bits = 1" and "with bits = 2". 4.3. Status List in CBOR Format - bits: REQUIRED. CBOR Unsigned integer (Major Type 0) that Probably the usual usage is s/Major Type/major type/. 7. Status Types A Status List can not represent multiple statuses per Referenced Token. This can be strengthened: A Status List necessarily represents exactly one status per Referenced Token. 7.1. Status Types Values * 0x01 - "INVALID" - The status of the Referenced Token is revoked, annulled, taken back, recalled or cancelled. Might be worth adding "This status is typically permanent." * 0x02 - "SUSPENDED" - The status of the Referenced Token is temporarily invalid, hanging, debarred from privilege. This state is usually temporary. s/state/status/ This document creates a registry in Section 14.5 that includes the most common Status Type values. Additional values may defined for particular use cases. Perhaps add after this "Applications SHOULD use registered values for statuses if they have the correct semantics." The processing rules for Referenced Tokens (such as JWT or CWT) precede any evaluation of a Referenced Token's status. For example, if a token is evaluated as being expired through the "exp" (Expiration Time) but also has a status of 0x00 ("VALID"), the token is considered expired. I think this is more exact: The processing rules for Referenced Tokens (such as JWT or CWT) supersede the Referenced Token's status in a TSL. For example, if a token is evaluated as being expired through the "exp" (Expiration Time) but in a TSL has a status of 0x00 ("VALID"), the token is considered expired. 8. Verification and Processing ... however the same rules would also apply for the Holder. This can be made more direct as ... however the same rules apply for the Holder. 8.1. Status List Request To obtain the Status List Token, the Relying Party MUST send an HTTP GET request to the URI provided in the Referenced Token. Is this truly a MUST or is it possible that the Relying Party might obtain the status list by some other method? Perhaps the meaning is that if the Relying Party sends an HTTP request to the aggregation_uri URL, the response MUST get the Status List Token. That is, this is a requirement on the URL and the HTTP server, not a requirement on the Relying Party. 8.2. Status List Response Note that while the examples for Status List Tokens in CWT format in this document are provided in hex encoding, this is done purely for readability and does not mean that hex encoding is expected for HTTP messages. Better '... this is done purely for readability; CWT format response bodies are "in binary".' The HTTP response SHOULD use gzip Content-Encoding as defined in [RFC9110]. Does this gain much? OK, for JWT there's a benefit, as the body is URL-safe characters and so will compress well. But for CWT the body is in binary and seems that using a Content-Encoding will gain little. For that matter, does CoAP even use overall content encodings like gzip? 8.3. Validation Rules b. If the Relying Party has custom policies regarding the freshness of the Status List Token, it SHOULD check the issued at claim (iat or 6) I'm not sure that "custom policies" is the best term. I think "local policies" is more common. 6. Retrieve the status value of the index specified in the Referenced Token as described in Section 4. Fail if the provided index is out of bounds of the Status List s/Fail/Validation fails/ Or perhaps "This check fails ..." to parallel the later sentence "If any of these checks fails ...". 8.4. Historical resolution If support for historical status information is required, this can be achieved by extending the request for the Status List Token as defined in Section 8.1 with a timestamp. I think this would be clearer if the phrases were reordered: ... by extending with a timestamp the request for the Status List Token as defined in Section 8.1. -- with the additional query parameter time Clearer as with the additional query parameter "time" -- If the Server does not support the additional query parameter, it SHOULD return a status code of 501 (Not Implemented) or if the requested time is not supported it SHOULD return a status code of 406 (Not Acceptable). However, it seems plausible that sometimes the server doesn't know of this capability and might respond 404. Do we want to warn implementers that the Relying Party must be prepared to accept any failure response code as meaning that historical information is not available? A Status List Token might be served via static file hosting (e.g., leveraging a Content Delivery Network), which would result in the client not being able to retrieve those status codes. Thus, the client MUST verify support for this feature by verifying that the requested timestamp is within the valid time of the returned token signaled via iat (6 for CWT) and exp (4 for CWT). ISTM that it's not possible for the client to verify support. But you can say: A Status List Token might be served via static file hosting (e.g., leveraging a Content Delivery Network) that ignores query parameters, which would result in the client requesting a historical status list but receiving the current status list. Thus, the client MUST reject a response unless the requested timestamp is within the valid time of the returned token signaled via iat (6 for CWT) and exp (4 for CWT). 9. Status List Aggregation mechanisms and allow offline validation of the status of a reference token for a period of time. s/reference token/Referenced Token/ 9.1. Issuer Metadata it is RECOMMENDED to use status_list_aggregation_endpoint for its metadata defined by [RFC8414]. I suspect some words are missing here. It seems to mean something like "to use a data item named "status_list_aggregation_endpoint" for its metadata in the ??? structure defined by [RFC8414]". 11. Security Considerations The Status List as defined in Section 4 only exists in cryptographically secured containers which allows checking the integrity and origin without relying on other aspects like transport security (e.g., the web PKI). It seems to me s/aspects/factors/. Perhaps ask the Editor. "the web PKI" seems to be an example of "transport security", which is one of the "aspects" that should not be relied on. But the sentence reads awkwardly. Maybe The Status List as defined in Section 4 only exists in cryptographically secured containers which allows checking the integrity and origin without relying on other factors such as transport security or web PKI. 11.1. Correct decoding and parsing of the encoded Status List Implementations are RECOMMENDED to verify correctness using the test vectors given by this specification. Perhaps raise this to "MUST"? At least, "SHOULD"! 11.2. Security Guidance for JWT and CWT A Status List Token in the JWT format should follow the security considerations of [RFC7519] and the best current practices of [RFC8725]. A Status List Token in the CWT format should follow the security considerations of [RFC8392]. Raise these to "SHOULD"! 11.4. Redirection 3xx Clients that follow 3xx (Redirection) class of status codes should be aware of possible dangers of redirects, such as infinite redirection loops since they could be used as an attack vector for possible denial of service attacks on clients. A client SHOULD detect and intervene in cyclical redirections (i.e., "infinite" redirection loops). More guidance for redirects given in Section 15.4 of [RFC9110] should be applied. I would adjust the wording to HTTP clients that follow 3xx (Redirection) class of status codes SHOULD be aware of the possible dangers of redirects, such as infinite redirection loops, since they can be used for denial of service attacks on clients. A client SHOULD detect and intervene in infinite redirections. Clients SHOULD apply the guidance for redirects given in Section 15.4 of [RFC9110]. 11.5. Expiration and Caching Clients should check that both values ... Should this be raised to MUST? Or is that impossible because there's no rigid definition of "reasonable range"? Concrete values for both claims highly depend on the use-case requirements and clients should be configured with lower/upper bounds for these values that fit their respective use-cases. Raise this to "SHOULD". Also, when you say "clients should be configured" is that a requirement that clients SHOULD be *configurable*? But "Concrete values" isn't the right wording, I think. Perhaps "reasonable values". You may need to be verbose and say "What constitutes reasonable ranges for both claims ..." Might be worth reiterating here that the TTL/expiration used for caching is the values in the tokens, not any that may be delivered as part of an HTTP response. (See sec. 7.1.) 11.6. Status List Token Protection Implementers should only use MACs to implementers should default to digital signatures if they are unsure. ISTM you want SHOULD here. 12.3. Observability of Relying Parties Once the Relying Party receives the Referenced Token, this enables them to request the Status List to validate its status through the provided uri parameter and look up the corresponding index. The use of pronouns here is confusing. Clearer to say Once the Relying Party receives the Referenced Token, the Relying Party can request the Status List through the provided uri parameter and can validate the Referenced Token's status by looking up the corresponding index. 12.5.1. Colluding Relying Parties Two or more colluding Relying Parties may link two transactions involving the same Referenced Token by comparing the status claims of received Referenced Tokens and therefore determine that they have interacted with the same Holder. ISTM that the colluding Relying Parties could just compare the Referenced Tokens they have received (or hashes thereof). Is there some way to create two functionally-equivalent Referenced Tokens that are not bitwise-identical. To avoid privacy risks for colluding Relying Parties, it is RECOMMENDED that Issuers provide the ability to issue batches of one- time-use Referenced Tokens s/for colluding Relying Parties/of colluding Relying Parties/ Do we need to warn that a batch of one-time-use Referenced Tokens MUST NOT all use the same aggregation_uri and index? Naively that would seem to be an optimization if you're generating a lot of one-time-use "clones" of an ordinary Referenced Tokens, but it would subvert the intention of having one-time-use Referenced Tokens. 12.5.2. Colluding Status Issuer and Relying Party It is therefore recommended to use Status Lists for Referenced Token formats that have similar unlinkability properties. It is not clear to me what this means. 12.8. Status Types That means that any Status Type that transports special information about a Referenced Token ... "special information" seems vague. Consider ... information beyond the routine statuses VALID and INVALID ... -- This document defines one additional Status Type with "SUSPENDED" that conveys such additional information. I suggest adding "but in practice all statuses other than VALID and INVALID are likely to contain information with privacy implications". 13.2. Linkability Mitigation ... in order to prevent this from becoming a possible source of correlation. s/this/the index value/ Revoking batch- issued Referenced Tokens might reveal this correlation later on. Clearer would be: Batch revocation of a batch of Referenced Tokens might reveal that they are all members of the same batch. But also batch creation of a batch of Referenced Tokens has the same risk if that causes the Status List to be extended to accommodate the batch of Referenced Tokens. 13.4. Status List Size It is RECOMMENDED that the size of a Status List in bits is divisible in bytes (8 bits) without a remainder, i.e. size-in-bits % 8 = 0. This condition is necessary by the construction of the data structure: the statuses are a list of bytes and there is no "length of array" field in the data structure, so the number of statuses is (number of bytes) * 8 / (bits). Of course there can be "unused" entries at the end that aren't referenced by any Referenced Token, but the Status List gives no indication of that, only the Issuer knows it. This may be useful for setups where Probably s/setups/ecosystems/, which is used elsewhere. * After initial fetching, the Relying Party checks for updates at time of iat + ttl. This seems hazardous, because it's quite possible that iat + ttl < now, causing the client to check for updates immediately, obtaining the same Status List with the same iat and ttl values, possibly triggering the client to immediately check again. Also, the figure at the top of page 43 shows the first option (and is incompatible with the other options) but there's no text saying that. * If no ttl is given, then Relying Party SHOULD check for updates latest after time of exp. There seems to be a word missing here. 13.8. Relying Parties avoiding correlatable Information If the Relying Party does not require the Referenced Token or the Status List Token, e.g. for subsequent status checks or audit trail, it is RECOMMENDED to delete correlatable information, in particular: I would say "... does not require the Referenced Token or the Status List Token for further processing, it is RECOMMENDED ...". * the status claim in the Referenced Token (after the presentation) What is "the presentation"? Does it mean "presentation to the Relying Party"? * the Status List Token itself (after expiration or update) The Relying Party should instead only keep the relevant payload from the Referenced Token. Perhaps s/relevant payload/needed fields/. Size comparison Status List size for varying sizes and revocation rates I would phrase this "Size of status lists for varying sizes and revocation rates" and similarly "Size of compressed array of UUIDv4 (128 bit UUIDs) for varying sizes". The following tables show a size comparison for a Status List (compressed byte array as defined in Section 4.1 and a compressed There is a missing ")" after "Section 4.1". The table gives these numbers but has no discussion of why the provide a useful comparison. One factor is "these are not sizes for complete Status List Tokens in JSON/CBOR nor Certificate Revocation Lists (CRLs), as they don't contain metadata, certificates and signatures". Is there reason to believe that the omitted parts are either (1) small relative to the data parts or (2) quite similar in size for both structures? Also, there is no description of why a list of UUIDs somehow is characteristic of a CRL. I am guessing that the concept is that the JWT/CWT IDs will be UUIDs and a CRL will contain a list of such UUIDs. If so I would clarify this for the naive: ... a compressed Byte Array of UUIDs (as an approximation to the list of IDs of Referenced Tokens in a Certificate Revocation List). -- Document History Commonly document histories are marked to be removed by the Editor, but this one is not. Is that intended for this document? [END]