Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpSig #125

Merged
merged 50 commits into from
Mar 1, 2021
Merged

HttpSig #125

merged 50 commits into from
Mar 1, 2021

Conversation

bblfish
Copy link
Member

@bblfish bblfish commented Feb 4, 2021

Extending the HTTP-Sig authentication IETF HTTPbis work to take into account WebIDs and the Self Sovereign Identity ecosystem with Verifiable Credentials and support for DIDs.

The text is a bit longer than essentially needed in order to help people who are new to Solid understand our use case.

In short it adds the following:

  • a WWW-Authenticate: HttpSig method for the server to let the client know it understands HttpSig method of authentication
  • An extension of the response to:
    • allow keyIds to be URIs: absolute URIs (https or DIDs) or two types of relative URIs: one linking to the server, and one linking to a document on the client
    • allow a Credential or WebID link to be passed in the response header with the header

A credential can be pointed to by the client passing a cred attribute to the Authorization header like this:
Authorization: HttpSig cred="<https://alice.freedom/cred/BAEng>"

Again the URI for the credential can be a https URL, a relative URL pointing to the server or to the client using the P2P extension to HTTP.

A major advantage is that it ties in nicely with the Self Sovereign Identity philosophy of putting the authenticating user at the center of authentication decisions.

It also has a major technical advantage in that optimally it can allow authentication over a single connection, when using the P2P extension to HTTP.

HttpSignature.md Outdated Show resolved Hide resolved
HttpSignature.md Outdated Show resolved Hide resolved
HttpSignature.md Outdated Show resolved Hide resolved
bblfish and others added 3 commits February 9, 2021 19:18
thanks :-)

Co-authored-by: Ted Thibodeau Jr <[email protected]>
Co-authored-by: Ted Thibodeau Jr <[email protected]>
Co-authored-by: Ted Thibodeau Jr <[email protected]>
HttpSignature.md Outdated Show resolved Hide resolved
HttpSignature.md Outdated
The advantage of a URL is that it allows the client to use HTTP Methods such as `POST` or `PUT` to create keys, as well as `PUT`, `PATCH` and `DELETE` to edit them, solving the problem of key revocation.

We also reserve the use of keyIds enclosed with `>` and `<` characters for
We also reserve the use of keyIds enclosed with `'>'` and `'<'` characters for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This suggests >{keyId}< which I think is not what is intended.

"Enclosed with" usually enumerates first the prepend and second the append -- so if the intent is (as I believe) <{keyId}>, this should read

Suggested change
We also reserve the use of keyIds enclosed with `'>'` and `'<'` characters for
We also reserve the use of keyIds enclosed with `'<'` and `'>'` characters for

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

>{keyId}< is exactly what was intended! :-)

The idea is that we want a way to say: this is the relative URL for the key, but it is not to be found out there on the internet, but by asking the client for it.
How does one ask the client for it? By using the P2P extension of HTTP/2 referred to, which allows the server to take on the role of a client on the same connection.

Do you think >{keyId}< would be clearer?

HttpSignature.md Outdated
* is enclosed in '<' and '>' then
* if it is relative it can be fetched on the same server
* if is is an absolute URL it can be fetched by opening a new connection
* is enclosed in `>` and `<` and P2P HTTP extension is enabled, the server can request the credential from the client directly using the same connection opened in (3).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, I think this probably should be

Suggested change
* is enclosed in `>` and `<` and P2P HTTP extension is enabled, the server can request the credential from the client directly using the same connection opened in (3).
* is enclosed in `<` and `>` and P2P HTTP extension is enabled, the server can request the credential from the client directly using the same connection opened in (3).

Copy link
Member Author

@bblfish bblfish Feb 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same point as above. Perhaps this is such an unusual idea that it requires more elaboration, perhaps even a picture or something.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it requires a lexical/literal example, at minimum. If there are other wrapping characters -- whether brackets, braces, parentheses, quotation marks, or otherwise -- which may be used in a more typical manner (the only thing I can quickly think of that uses >…< wrappers in that order is an ASCII emoticon for a cat, >^..^<), I would suggest using them instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I see it is in terms of indexicals eg: I and you. In an HTTP connection of a client C to a server example.com, the you for the client is example.com. The server on the other hand knows nothing of the client so it only can say you. The client wishes to pass a key to the server but it can say: the key at my house at address so and so, or the key in your pocket, or the key in my pocket. We need to be able to distinguish between "the key in my pocket" and "the key in your pocket".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making such distinction doesn't seem to require any specific wrapping characters. It requires knowing who's "speaking", and to whom -- as the entity to which the possessive "my" or "your" refers changes in meaning with the speaker and the audience. In HTTP, we can speak of the Client and the Server, and describe what action each might be taking (requesting, responding, etc.). In other spheres, we have conventions like Requesting Party, Relying Party, Responding Party, etc., to serve the same purpose.

Sometimes, it's very hard to describe an interaction with generalities, but trivial to describe it through a concretized example. I think this might be one of those situations, at least at this point in the ecosystem's development.

Copy link
Member Author

@bblfish bblfish Feb 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making such distinction doesn't seem to require any specific wrapping characters. It requires knowing who's "speaking", and to whom -- as the entity to which the possessive "my" or "your" refers changes in meaning with the speaker and the audience.

Let us say we start with a connection from Phone to Pod .
Phone requests a secure resource, is returned a 401 by Pod, and then sends the Phone a signed message with a relative URL /auth/Cred1 referring to the Credential . Now that the Pod can turn around and be a client on the same connection, it is possible for it to also use relative URLs to make requests to the Phone, which was not possible before the P2P connection extension. So it is now possible for the phone to send a relative URL to the Pod that refers to the Phone's side of the connection. Relative URLs are relative to a communication.

So we want to allow the following two possibilities to exist:

  1. the Credential is on the Phone at >/auth/Cred1<
  2. the Credential is on the server at </auth/Cred1>

The relative path /auth/Cred1 is the same in both cases, so we use the angle bracket reversal to distinguish on which side the URL is relative to the roles at that stage in that conversation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote more about what P2P opens up to the web here w3c/architecture#14
I still want to integrate this into the spec here, but need to be careful not to make too much of it, as what is proposed can also work without it.

HttpSignature.md Outdated Show resolved Hide resolved
HttpSignature.md Outdated Show resolved Hide resolved
HttpSignature.md Outdated Show resolved Hide resolved
HttpSignature.md Outdated Show resolved Hide resolved
@bblfish bblfish changed the base branch from master to main February 23, 2021 16:39
HttpSignature.md Outdated Show resolved Hide resolved
HttpSignature.md Outdated Show resolved Hide resolved
HttpSignature.md Outdated Show resolved Hide resolved
bblfish and others added 2 commits February 25, 2021 16:23
I am learning, slowly ;-)

Co-authored-by: Ted Thibodeau Jr <[email protected]>
Co-authored-by: Ted Thibodeau Jr <[email protected]>
HttpSignature.md Outdated Show resolved Hide resolved
Co-authored-by: Ted Thibodeau Jr <[email protected]>
HttpSignature.md Outdated Show resolved Hide resolved
HttpSignature.md Outdated Show resolved Hide resolved
bblfish and others added 4 commits February 25, 2021 16:31
It is a pitty that one cannot link to that OWL2-Primer using a query with say ?turtle=on to show the turtle examples, as readers of this may not know that one has to go to the top to click on "Turtle" to see those.

Co-authored-by: Ted Thibodeau Jr <[email protected]>
HttpSignature.md Outdated Show resolved Hide resolved
Co-authored-by: Ted Thibodeau Jr <[email protected]>
Copy link
Member

@csarven csarven left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Did I plant some of this in 2017 ( w3c-ccg/http-signatures#8 ) with an all too simple notation for URL in keyId? 😄 Generalising it to relative URLs (as you've commented in that issue) and client side resource reference here is great!

Using URL in keyId was acknowledged to be useful and that the suggestion was to describe the allowed value in a higher level spec. So, this proposal is the right place to reenergise and work this out. It can be defined in general terms and there can also be the Solid-centric bits. I would suggest to make this more clear for extensibility.

There are other relatively minor related considerations eg. whether a new field-name like keyIdType can indicate what to expect from keyId: w3c-ccg/http-signatures#3 . This is not particularly needed though if HttpSig is used to set the method in which the keyId value would be a URL.

Looking back at earlier work and discussions on Signing HTTP Messages, Authentication was in fact part of the earlier drafts (prior to HTTP Working Group's draft): https://tools.ietf.org/html/draft-cavage-http-signatures ( https://www.ietf.org/rfcdiff?url1=draft-cavage-http-signatures-12&url2=draft-richanna-http-message-signatures-00&difftype=--html ). It makes sense to have separate specs for the Authentication component - essentially the case given in this PR.

Lastly, this proposal is an excellent example of making wider interop possible with the works done by other groups / standards bodies in which the Solid ecosystem can benefit from. The Solid Community Group doesn't need to work out all areas/specs that's tied or dependent on eg. wallets, credential managers, crypto APIs, proofs.. We focus on bridging the layers and get some implementation going. Easier said.. of course.

HttpSignature.md Outdated
The protocol allows a client to authenticate by signing a number of HTTP headers with it's private key. In order for the server to be able to verify this signature it needs to know the matching public key. This information must be transmitted by the client in the form of an opaque string known as a `keyId` (see [§2.1.1 keyId](https://tools.ietf.org/html/draft-cavage-http-signatures-11#section-2.1.1)). This string must enable the server to look up the key. How this is done is not specified by the protocol.
HttpSig is a simple but very efficient authentication protocol extending [Signing HTTP Messages](https://tools.ietf.org/html/draft-ietf-httpbis-message-signatures-01) RFC by defining &mdash;
* a `WWW-Authenticate: HttpSig` header the server can return with a 401 or 402 to the client
* a `Authorization: HttpSig` method the client can use in response with two optional attributes `webid` and `cert` both taking `https` or `DID` URLs.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking: Clarify if only certain URI schemes are allowed. Or if https is only intended to be for HTTP over TLS (as you've mentioned later in the document).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yes, WebID would be for https URLs. I actually did not use webid in the text, as I think a WebID is a form of minimal self signed certificate (and so could be covered by cert), by the fact that it is located at the URL of its definition...

HttpSignature.md Outdated
Comment on lines 8 to 10
* a convention for how to encode URLs in the `keyId` attribute of [Signing HTTP Messages](https://tools.ietf.org/html/draft-ietf-httpbis-message-signatures-01)'s `Signature-Input` header when used with the `WWW-Authenticate: HttpSig` header
* the ability to use absolute or relative URLs in all places mentioned where URLs can be used
* allow relative URLs passed by the client to the server to refer to resources on the client using a [P2P Extension to HTTP](https://tools.ietf.org/html/draft-benfield-http2-p2p-02) which would allow authentication over a single HTTP connection.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: If the first and third point are specialisations of the second, consider moving the second to first.

Copy link
Member Author

@bblfish bblfish Mar 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I starting to edit that, but then I realized that the the point that URLs can be used in the cert field of the Authorization header and the keyId of the Signature-Input header are more important changes. The relative URL point makes sense only after those have been introduced. But I'll make a few other improvements to that text.

HttpSignature.md Outdated

The addition to the HTTP Signature protocol made here can be illustrated
by the following Sequence Diagram:
[Signing HTTP Messages](https://tools.ietf.org/html/draft-ietf-httpbis-message-signatures-01) has the advantages of being very simple and being specified directly at the HTTP layer, bypassing the problem of client authentication at the TLS layer.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Not sure if "problem" is the right word here. Perhaps just not a universal solution?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/problem/challenge/?

Copy link
Member Author

@bblfish bblfish Mar 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Merged Version has

bypassing limitations of client authentication at the TLS layer, related to client certificate renegotiation, and the TLS layer occuring at lower layer of the communication stack.

That text can certainly also be improved. Still the problem that TLS is at the wrong level of the stack, is a big challenge for sure. Given that Chrome dropped token binding, something much simpler to do, it looks very difficult to get movement in that direction.

HttpSignature.md Outdated Show resolved Hide resolved

It should also add a `Link:` relation to an Access-Control resource which describes which resources might be accessible.
This is described in [Web Access Control Spec](https://github.com/solid/web-access-control-spec/).
(Without such a Link the client would only be able to guess what key to send.)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps an alternative would be to include keyId in the field-value of WWW-Authenticate. Bonus: 1) efficient; one less connection 2) flexible; no need to hop through a specific access control system.

Copy link
Member Author

@bblfish bblfish Mar 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The WWW-Authenticate: HttpSig header is sent by the server to the client. The HttpSig method is meant to indicate to the client that it can use "Signing Http Messages" with the keyId used as URL.
It could send the content of the ACL in the body so not requiring an extra connection (or with HTTP/2 the server can send it ahead of being asked).

HttpSignature.md Outdated
This is described in [Web Access Control Spec](https://github.com/solid/web-access-control-spec/).
(Without such a Link the client would only be able to guess what key to send.)
Note: With [HTTP/2 server Push](https://tools.ietf.org/html/rfc7540#section-8.2), the server could immediately push the content of the linked-to Access Control document to the client, assuming reasonably that the client would have connected with the right key had it known the rules.
It may also be possible to send the ACL rules directly in the body (Todo: research) of the response.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly. If so, should probably be wrapped in Problem Details in response body eg solid/specification#28

This may not necessarily lead to a new network connection being opened to the outside world in the following cases:
* The `keyId` URL is local to the resource server,
* The `keyId` URL is a [did:key](https://w3c-ccg.github.io/did-method-key/) URL. This is a URL that contains in its name all the data of the public key.
* The `keyId` URL refers to an external resource, but the resource server has a fresh cached copy of it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't fully thought this through (and it is late late night..) but there may be some dependency/expectation that the URI is persistent in that a particular key (resource) is allocated to the URI. If the key resource ever changes but the resource server still uses the cached copy, client may not ever be able to authenticate until cache is cleared. So, either a good practice is encouraged (which is not different than the general best practice of URI Persistence as per AWWW) or there needs to be a way to bust the cache... or don't cache. Todo: more thinking/implementing.

Copy link
Member Author

@bblfish bblfish Mar 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think that type of problem works itself out with experience, and the process followed by the server will depend on how serious the threat is. It the key on the server or with the P2P connection option on the client, these things get to be a lot simpler. With did:keys the key comes along with the message.

HttpSignature.md Outdated
@@ -60,10 +180,12 @@ an RDF format. If we were to use [the cert ontology](https://www.w3.org/ns/auth/
* [The Security Vocabulary](https://web-payments.org/vocabs/security)
* Any other?)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the Web Of Trust RDF Ontology. I use both cert and wot eg. the wot snippet:

@prefix wot: <http://xmlns.com/wot/0.1/> .

<https://csarven.ca/#i>
  wot:hasKey <https://csarven.ca/#key-8e3a> .

<https://csarven.ca/#key-8e3a>
  a wot:PubKey ;
  wot:pubkeyAddress <https://csarven.ca/key/A74187CE3D508E3A.asc> ;
  wot:fingerprint "0ADFF0BACC9F0A16FA782D94A74187CE3D508E3A" .

```

As before we reserve the option of enclosing a relative URL in `>` and `<` to refer to a client side resource, accessible to the server using a P2P extension of HTTP (see [Peer-to-Peer Extension to HTTP/2 draft](https://tools.ietf.org/html/draft-benfield-http2-p2p-02)).
(Todo: how else can one pass the Credential?).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not up to speed with the browser APIs... face scan , fingerprint, voice.. Not sure if/how https://www.w3.org/TR/webauthn/ can fit here to pass the credential.

HttpSignature.md Outdated

The protocol allows a client to authenticate by signing a number of HTTP headers with it's private key. In order for the server to be able to verify this signature it needs to know the matching public key. This information must be transmitted by the client in the form of an opaque string known as a `keyId` (see [§2.1.1 keyId](https://tools.ietf.org/html/draft-cavage-http-signatures-11#section-2.1.1)). This string must enable the server to look up the key. How this is done is not specified by the protocol.
HttpSig is a simple but very efficient authentication protocol extending [Signing HTTP Messages](https://tools.ietf.org/html/draft-ietf-httpbis-message-signatures-01) RFC by defining &mdash;
* a `WWW-Authenticate: HttpSig` header the server can return with a 401 or 402 to the client
Copy link
Member

@csarven csarven Mar 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bikeshedding: Signature was used in earlier drafts. We can reuse that or use HttpSig (or another name) to be specifically URL-based / Solid-centric?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had forgotten that the draft-cavage had a Signature header for authentication. I'd be happy to use that too, but don't want to step on toes in case the intent is too different. Perhaps @msporny has a view on that?

@matthieubosquet matthieubosquet merged commit 5b85646 into solid:main Mar 1, 2021
Copy link
Member

@acoburn acoburn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm late to the game here, but I wanted to signal my +1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants