mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-10 04:22:09 +10:00
beginnings of download implementation
This commit is contained in:
5
server/api/v1/client/metadata/endpoint.get.ts
Normal file
5
server/api/v1/client/metadata/endpoint.get.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
|
||||
export default defineClientEventHandler(async (h3) => {
|
||||
|
||||
});
|
||||
20
server/api/v1/client/metadata/versions.get.ts
Normal file
20
server/api/v1/client/metadata/versions.get.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
|
||||
export default defineClientEventHandler(async (h3, {}) => {
|
||||
const query = getQuery(h3);
|
||||
const id = query.id?.toString();
|
||||
if (!id)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "No ID in request query",
|
||||
});
|
||||
|
||||
const versions = await prisma.gameVersion.findMany({
|
||||
where: {
|
||||
gameId: id,
|
||||
},
|
||||
});
|
||||
|
||||
return versions;
|
||||
});
|
||||
@ -3,24 +3,29 @@
|
||||
Drop clients need to complete a handshake in order to connect to a Drop server. It also trades certificates for encrypted P2P connections.
|
||||
|
||||
## 1. Client requests a handshake
|
||||
Client makes request: `POST /api/v1/client/auth/initiate` with information about the client.
|
||||
|
||||
Server responds with a URL to send the user to. It generates a device ID, which has all the metadata attached.
|
||||
Client makes request: `POST /api/v1/client/auth/initiate` with information about the client.
|
||||
|
||||
Server responds with a URL to send the user to. It generates a device ID, which has all the metadata attached.
|
||||
|
||||
## 2. User signs in
|
||||
Client sends user to the provided URL (in external browser). User signs in using the existing authentication stack.
|
||||
|
||||
Server sends redirect to `drop://handshake/[id]/[token]`, where the token is an authentication token to generate the necessary certificates, and the ID is the client ID as generated by the server.
|
||||
Client sends user to the provided URL (in external browser). User signs in using the existing authentication stack.
|
||||
|
||||
Server sends redirect to `drop://handshake/[id]/[token]`, where the token is an authentication token to generate the necessary certificates, and the ID is the client ID as generated by the server.
|
||||
|
||||
## 3. Client requests certificates
|
||||
Client makes request: `POST /api/v1/client/auth/handshake` with the token recieved in the previous step.
|
||||
|
||||
The server uses it's CA to generate a public-private key pair, the CN of the client ID. It then sends that pair, plus the CA's public key, to the client, which stores it all.
|
||||
Client makes request: `POST /api/v1/client/auth/handshake` with the token recieved in the previous step.
|
||||
|
||||
*The certificate lasts for a year, and is rotated when it has 3 months or less left on it's expiry.*
|
||||
The server uses it's CA to generate a public-private key pair, the CN of the client ID. It then sends that pair, plus the CA's public key, to the client, which stores it all.
|
||||
|
||||
_The certificate lasts for a year, and is rotated when it has 3 months or less left on it's expiry._
|
||||
|
||||
## 4.a Client requests one-time device endpoint
|
||||
The client generates a nonce and signs it with their private key. This is then attached to any device-related request.
|
||||
|
||||
The client uses a millisecond UNIX timestamp and signs it with their private key. This is then attached to any device-related request. It has 30 seconds to make the request before the nonce becomes invalid (this is to prevent credential stealing & reusing).
|
||||
|
||||
## 4.b Client wants a long-lived session
|
||||
The client does the same as above, but instead makes the request to `POST /api/v1/client/auth/session`, which generates a session token that lasts for a day. This can then be used in the request to provide authentication.
|
||||
|
||||
The client does the same as above, but instead makes the request to `POST /api/v1/client/auth/session`, which generates a session token that lasts for a day. This can then be used in the request to provide authentication.
|
||||
|
||||
@ -14,6 +14,8 @@ type ClientUtils = {
|
||||
fetchUser: () => Promise<User>;
|
||||
};
|
||||
|
||||
const NONCE_LENIENCE = 30_000;
|
||||
|
||||
export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
return defineEventHandler(async (h3) => {
|
||||
const header = await getHeader(h3, "Authorization");
|
||||
@ -30,6 +32,21 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
if (!clientId || !nonce || !signature)
|
||||
throw createError({ statusCode: 403 });
|
||||
|
||||
const nonceTime = parseInt(nonce);
|
||||
const current = Date.now();
|
||||
if (
|
||||
// If it was generated in the future
|
||||
nonceTime > current ||
|
||||
// Or more than thirty seconds ago
|
||||
nonceTime < current - NONCE_LENIENCE
|
||||
) {
|
||||
// We reject the request
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "Nonce expired",
|
||||
});
|
||||
}
|
||||
|
||||
const ca = h3.context.ca;
|
||||
const certBundle = await ca.fetchClientCertificate(clientId);
|
||||
if (!certBundle)
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
# Drop Download System
|
||||
The Drop download system uses a torrent-*like* system. It is not torrenting, nor is it compatible with torrenting clients.
|
||||
Drop downloads come in two types:
|
||||
|
||||
## Clients
|
||||
Drop clients have built-in HTTP APIs that they forward with UPnP. This API exposes different capabilities for different Drop features, like download aggegration and P2P networking. When they sign on, they send a list of supported capabilities to the server.
|
||||
## Public (not quite) HTTPS downloads endpoints
|
||||
These use public HTTPS certificate, and while are authenticated, are 'public' in the sense that they aren't P2P; anyone can connect to them
|
||||
|
||||
## Private mTLS P2P endpoints
|
||||
Drop clients use P2P mTLS aided by the P2P co-ordinator to transfer chunks between themselves.
|
||||
Reference in New Issue
Block a user