Wot-thing-description: Guarantee RDF round-tripping for security definitions

Created on 5 May 2021  路  11Comments  路  Source: w3c/wot-thing-description

Security definitions are indexed JSON that (may) repeat in a TD. They are currently not materialized after transformation to RDF.

See also #1015. (Different issue but same requirement.)

canonicaliziation

Most helpful comment

In particular, my directory always returns a string in case the array is unitary or an array if this contains more than one value. If a user provides "security" : ["basic_sc"] the directory will always return this as "security" : "basic_sc"; which according to the standard is ok but is not the original TD that the user provided. Could we do something about this issue (it happens also with more fields than security). I think the standard should try to avoid having this duplicity in the data representation since it will make hard for TDs to be interoperable.

Although I understand that this "duplicity" allows _less verbose_ TDs, I always found it a little bit problematic. It creates ambiguity for parsers and users. I would say that we might need to reconsider this choice but I don't think we can do it in a back-compatible manner (never mind actually we can be stricter and disallow plain strings).

All 11 comments

Since the proposed approach for a schema definition block (to be used in additionalResponses) has a similar structure we should have similar solutions and ontology structure: https://github.com/w3c/wot-thing-description/issues/1053

There is a general requirement to import a TD into an RDF database and re-export it as something that is a valid TD. In particular, SecurityScheme objects are not valid in "security", only their names. Furthermore, to support canonicalization, their name cannot change.

We could do a (reversible) mapping like this:

"securityDefinitions": {
    "a": { "scheme": "basic", ... },
    "b": { "scheme": "oauth2", ...}
}

this could get mapped internally to

"securityDefinitions": [
    { "@id": "a", "scheme": "basic", ... },
    { "@id": "b", "scheme": "oauth2", ...}
]

and then we can "flatten" these into security objects, so

"security": "a"

becomes

"security": { "@id": "a", "scheme": "basic", ... }

Then, when we reserialize, we have to "collect" all the definitions, remove duplicates, and put them back into a "securityDefinitions" block.

Issue: "security" can be defined at two levels, and these are equivalent ways to state the same thing. We should define one way to do this for canonicalization. The simplest thing is to only use "security" at the form level upon reserialization (more verbose, but).

There is a similar problem with prefixes wrt canonicalization; when you import the TD and replace prefixes with URLs for processing, when you reserialize you have to replace the base URLs with any prefix defined for that URL to keep the serialization from being different. This implies:

  1. We have to keep the @context block around in the information model (it has the table of prefixes to URL mappings)
  2. Canonical form should disallow use of raw URLs if a prefix is defined (otherwise the round tripping will not recreate the input) - this is something I should add an explicit assertion for.

See also https://github.com/w3c/wot-thing-description/issues/300 and https://github.com/w3c/wot-thing-description/issues/757.

The solution should be compatible with allowing a MIX of string names and SecurityScheme objects in "security" values. The inline SecurityScheme objects would be anomymous and so when reserialized would be left in place and not pulled back up to a "securityDefinitions" block. Only "named" SecurityScheme objects should be "pulled".

Note that inline SecurityScheme objects is only a proposed feature for TD 2.0 (see PR https://github.com/w3c/wot-thing-description/pull/945). So we would not support it immediately, only named objects; I mention it only since we probably want to plan for it (but if we add an @id, we could make it mandatory in TD1.1 and optional in TD2.0...).

Note also for TD2.0 I was proposing deprecating use of arrays for the value for "security" and only allowing single elements. Then AND/OR combinations would be explicitly declared with "combo" Schemes (and the "combo" scheme would be the default, giving a nice but explicit syntax for AND/OR combinations). Then a "security" value would be EITHER a string or an (anonymous) SecurityScheme object.

BTW, I don't have time for updates to how security is handled before I duplicate it for schema definitions. So I am going to plow ahead with duplicating what we are currently doing with security or schemas even if it is "wrong"... and then we will have to fix the ontologies/containers/information model/rendering scripts for both.

I have a thought regarding RDF and round-tripping, I bump into this during the development of the WoT directory. If a user provides the following description:

{
    "@context": "https://www.w3.org/2019/wot/td/v1",
    "id": "urn:dev:ops:32473-WoTLamp-1234",
    "title": "MyLampThing",
    "securityDefinitions": {
        "basic_sc": {"scheme": "basic", "in":"header"}
    },
    "security": ["basic_sc"],
    "properties": {
        "status" : {
            "type": "string",
            "forms": [{"href": "https://mylamp.example.com/status"}]
        }
    }
}

I can translate this easily into RDF, which will be:

@prefix dc: <http://purl.org/dc/terms/> .
@prefix td: <https://www.w3.org/2019/wot/td#> .
@prefix ns1: <https://www.w3.org/2019/wot/json-schema#> .
@prefix ns2: <https://www.w3.org/2019/wot/hypermedia#> .

<urn:dev:ops:32473-WoTLamp-1234>
  dc:title "MyLampThing" ;
  td:hasPropertyAffordance [
    a <https://www.w3.org/2019/wot/json-schema#StringSchema> ;
    ns1:propertyName "status" ;
    td:hasForm [ ns2:hasTarget <https://mylamp.example.com/status> ]
  ] ;
  td:hasSecurityConfiguration <https://json-ld.org/playground/basic_sc> ;
  td:securityDefinitions [
    td:in "header" ;
    td:scheme "basic"
  ] .

This RDF is translated into a triple store or memory store and stays there. After a while a user requests this TD under the original form application/td+json. Now the directory has to translate back this TD and here comes the problem.

Several fields from this TD can be either arrays or just one string, for instance "security" could be either translated into ["basic_sc"] or just "basic_sc. This means that there is no way to know which of those two serialisations where provided in the begining by the user, and therefore, the directory must choose a "canonical" representation for this fields and return back a TD that potentially could be different.

In particular, my directory always returns a string in case the array is unitary or an array if this contains more than one value. If a user provides "security" : ["basic_sc"] the directory will always return this as "security" : "basic_sc"; which according to the standard is ok but is not the original TD that the user provided. Could we do something about this issue (it happens also with more fields than security). I think the standard should try to avoid having this duplicity in the data representation since it will make hard for TDs to be interoperable.

In particular, my directory always returns a string in case the array is unitary or an array if this contains more than one value. If a user provides "security" : ["basic_sc"] the directory will always return this as "security" : "basic_sc"; which according to the standard is ok but is not the original TD that the user provided. Could we do something about this issue (it happens also with more fields than security). I think the standard should try to avoid having this duplicity in the data representation since it will make hard for TDs to be interoperable.

Although I understand that this "duplicity" allows _less verbose_ TDs, I always found it a little bit problematic. It creates ambiguity for parsers and users. I would say that we might need to reconsider this choice but I don't think we can do it in a back-compatible manner (never mind actually we can be stricter and disallow plain strings).

never mind actually we can be stricter and disallow plain strings

Forcing to use always arrays could be a good solution

Just to keep up with this issue, the same thing happens with other fields from the TD. In the JTD library what I do is transform unitary arrays into just one string for several properties I have observed that have this duplicity. Maybe we should do the same for all of them: "op", "scopes", "@type" (this is especially concerning), and "items".

Was this page helpful?
0 / 5 - 0 ratings