6.4 KiB
Peer ID Authentication over HTTP
| Lifecycle Stage | Maturity | Status | Latest Revision |
|---|---|---|---|
| 1A | Working Draft | Active | r0, 2023-01-23 |
Authors: @MarcoPolo
Interest Group: Same as HTTP
Introduction
This spec defines an authentication scheme of libp2p Peer IDs in accordance with
RFC 9110. The authentication
scheme is called Libp2p-PeerID.
Mutual Client and Server Peer ID Authentication
-
The server initiates the authentication by responding to a request that must be authenticated with the response header
WWW-Authenticate: Libp2p-PeerID challenge-client="<base64-encoded-challenge>. The challenge MUST be indistinguishable from random data. The Server MAY randomly generate this data, or MAY use an server-encrypted value. If using random data the server SHOULD store the challenge temporarily until the authentication is done. The challenge SHOULD be at least 32 bytes. -
The client sends a request and sets the
Authorizationheader header to the following:Libp2p-PeerID peer-id="<encoded-peer-id-bytes>",[challenge-server="<base64-encoded-challenge-server>",]sig="<base64-signature-bytes>"]- The
challenge-serverparameter is optional. The client should set it if the client wants to authenticate the server. - The peer-id is encoded per the string encoding described in the peer-ids spec.
- The signature is over the concatenated result of:
<varint-length> + "origin=" + server-name + [<varint-length> + "challenge-server=" + base64-encoded-client-chosen-challenge-server + ] <varint-length> + "challenge-client=" + base64-encoded-challenge- Strings are UTF-8 encoded.
- If the challenge server was omitted in the
Authorizationheader it MUST be omitted in the signature. - If provided, the client-chosen
challenge-serverMUST be randomly generated. - The client-chosen
challenge-serverSHOULD be at least 32 bytes. - The client MUST use the same server-name as what is used for the TLS session.
- If the client only wants to authenticate the server and the server does
not need to authenticate the client, the client can omit the
challenge-clientfrom the parameters and signature on its initial request (since it did not receive achallenge-client). If a resource requires client authentication, the server MUST return401 Unauthorizedif a client attempts to authenticate without achallenge-client. - Example on building the message to sign:
origin=example.com client-challenge=qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo= challenge=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=Message To Sign in hex with comments
12 // (18 bytes) 6f726967696e3d6578616d706c652e636f6d // (origin=example.com) 3d // (61 bytes) 636c69656e742d6368616c6c656e67653d7171717171717171717171717171717171717171717171717171717171717171717171717171717171716f3d // (client-challenge=qq...o=) 36 // (54 bytes) 6368616c6c656e67653d414141414141414141414141414141414141414141414141414141414141414141414141414141414141413d // (challenge=AA...A=)All together:
Message To Sign in hex: 126f726967696e3d6578616d706c652e636f6d3d636c69656e742d6368616c6c656e67653d7171717171717171717171717171717171717171717171717171717171717171717171717171717171716f3d366368616c6c656e67653d414141414141414141414141414141414141414141414141414141414141414141414141414141414141413d - The
-
The server MUST verify the signature using the server name used in the TLS session. The server MUST return 401 Unauthorized if the server fails to validate the signature.
-
If the signature is valid, the server has authenticated the client's peer id and MAY fulfill the request according to application logic. If the request is fulfilled, the server sets the
Authentication-Inforesponse header to the following:Libp2p-PeerID peer-id="<encoded-peer-id-bytes>",sig="<base64-signature-bytes>"- The signature is over the concatenated result of:
<varint-length> + "origin=" + server-name + [<varint-length> + "challenge-server=" + base64-encoded-client-chosen-challenge-server + ] <varint-length> + "client=" + <encoded-client-peer-id-bytes> - Strings are UTF-8 encoded.
- Optionally, the server MAY include a Bearer
token in the
Authentication-Inforesponse header. This allows clients to avoid a future iteration of this authentication protocol. If clients see a bearer token, they SHOULD store it for future use. For example, anAuthentication-Infoheader with a bearer token would look like:Libp2p-PeerID peer-id="<encoded-peer-id-bytes>",sig="<base64-signature-bytes>",bearer-token="<token>".
- The signature is over the concatenated result of:
-
The client can then authenticate the server with the the signature from
Authentication-info.
Authentication Endpoint
Because the client needs to make a request to authenticate the server, and the
client may not want to make the real request before authenticating the server,
the server MAY provide an authentication endpoint. This authentication endpoint
is like any other application protocol, and it shows up in .well-known/libp2p,
but it only does the authentication flow. The client and server SHOULD NOT send
any data besides what is defined in the above authentication flows. The protocol
id for the authentication endpoint is /http-peer-id-auth/1.0.0.
Considerations for Implementations
- Implementations MUST only authenticate over a secured connection (i.e. TLS).
- Implementations SHOULD limit the maximum length of any variable length field.
Note on web PKI
Protection against man-in-the-middle (mitm) type attacks is through web PKI. If the client is in an environment where web PKI can not be fully trusted (e.g. an enterprise network with a custom enterprise root CA installed on the client), then this authentication scheme can not protect the client from a mitm attack.
Test Vectors
TODO (marco): include a couple examples of what is signed, exchanged, and resulting signature.