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

Authentication and restricting read access #55

Closed
joepio opened this issue Jul 29, 2021 · 3 comments
Closed

Authentication and restricting read access #55

joepio opened this issue Jul 29, 2021 · 3 comments

Comments

@joepio
Copy link
Member

joepio commented Jul 29, 2021

We have authentication + authorization for writes (using Commits and signatures), but not for read access.

Issue in atomic-server.

Goals:

  • Secure: Because, what's the point of authentication if it's not?
  • Ease of use: Setting up an identity should not require any effort, and proving identity should be minimal effort.
  • Anonimity allowed: Users should be able to have multiple identities, some of which are fully anonymous.
  • Self-sovereign: No dependency on servers that user's don't control. Or at least, minimise this.
  • Dummy-proof: We need a mechanism for dealing with forgetting passwords / client devices losing data.
  • Compatible with Commits: Atomic Commits require clients to sign things. Ideally, this functionality / strategy would also fit with the new model.
  • Fast: Of course, authentication will slow things down. But let's keep that to a minimum.

Ideas

Signing GET requests

So a couple of methods exist to sign HTTP requests. One is to add a Digest and Authorization HTTP header. Another way is to add a Body with a JWS (or other signature) that contains information about the request, such as the requested resource and some fleeting identifier (timestamp).

WebAuthn

This specification allows browsers to use 2FA devices for signing in - without requiring any password remembering. It works pretty well, but it has some unfortunate limitations for Atomic Data. For one, it can't be used to sign an arbitrary thing, such as an Atomic Commit.

Traversing parents vs explicit rights

As of now, the server determines whether someone can edit something by iterating over parent relations until it encounters a write right. I could do the same thing for read rights.

If a client wants to determine something about the rights of that resource, it will have to perform one or a couple of requests to traverse the graph and get the rights attributes. If rights were more explicit, clients could more easily know whether something should be private or not.

We could also decide to make rights very explicit - every single Resource could describe their own rights. If we were to

Session keys & 2FA

Signing every request with your agent's private key is elegant, but also opens up some attack vectors. For example, a phishing attack for the agent's secret (a login screen that sends the private key to the client, for example) would be devastating. This problem is the same for regular apps that rely on username + password. That's why many apps offer 2FA options.

What we can't do, is sign every single request with a 2FA device - it would ask the user every second to use some app. What we can do, is create a temporary private key used in that session alone. This key can be used to sign the requests.

The downside of this approach, is that Commits will no longer be signed by the public key of the agent, which makes traceability harder.

We could store every Session (and it's public key) as a resource on any server, and let these point to the Agent. These sessions can be signed by the Agent, which proves that the session actually is created by the Agent, and is a legit representative.

@joepio joepio changed the title Authentication in read access Authentication and restricting read access Aug 17, 2021
@joepio
Copy link
Member Author

joepio commented Oct 30, 2021

The Webauthn spec is cool, but does not and will not support signing data. That unfortunately makes it not a fit for Atomic Data.

However, the WebCrypto spec does allow signing, and some are advocating for hardware access.

w3c/webcrypto#263

@joepio
Copy link
Member Author

joepio commented Nov 13, 2021

I'll go for signing requests. We'll need to prevent MITM attacks by including a timestamp. I suggest we use an HTTP header:

x-atomic-signature = someBase64Signature

Signature is calulated by signing the URL + timestamp with Agent's ED25519 private key

https://atomicdata.dev/urlToBeFetched 1596798919

@joepio
Copy link
Member Author

joepio commented Nov 13, 2021

we'll need these headers:

  const privateKey = agent.privateKey;
  const timestamp = getTimestampNow();
  const message = `${subject} ${timestamp}`;
  const signed = await signToBase64(message, privateKey);
  headers.set('x-atomic-public-key', await agent.getPublicKey());
  headers.set('x-atomic-signature', signed);
  headers.set('x-atomic-timestamp', timestamp.toString());
  headers.set('x-atomic-agent', agent?.subject);

The agent subject is needed, because the server needs to find whether the public key is actually the one corresponding to that agent.

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

No branches or pull requests

1 participant