Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/commands/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export const serverCommand = new Command('server')
.option('--host <string>', 'server host', '127.0.0.1')
.option('--car-storage <path>', 'path for CAR file storage', './cars')
.option('--database <path>', 'path to SQLite database', './pins.db')
.option('--private-key <key>', 'private key for Synapse (or use PRIVATE_KEY env var)')
.option('--private-key <key>', 'private key for Synapse (env: PRIVATE_KEY)')
.option('--access-token <token>', 'bearer token required on all API requests except GET / (env: ACCESS_TOKEN)')

addNetworkOptions(serverCommand)
.addOption(
Expand All @@ -20,6 +21,9 @@ addNetworkOptions(serverCommand)
if (options.privateKey) {
process.env.PRIVATE_KEY = options.privateKey
}
if (options.accessToken) {
process.env.ACCESS_TOKEN = options.accessToken
}
// RPC URL takes precedence over network flag
if (options.rpcUrl) {
process.env.RPC_URL = options.rpcUrl
Expand Down
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export function createConfig(): Config {
// Application-specific configuration
port: parseInt(process.env.PORT ?? '3456', 10),
host: process.env.HOST ?? 'localhost',
accessToken: process.env.ACCESS_TOKEN,

// Synapse SDK configuration
privateKey: process.env.PRIVATE_KEY, // Required: Ethereum-compatible private key
Expand Down
1 change: 1 addition & 0 deletions src/core/synapse/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface Config {
port: number
host: string
privateKey: string | undefined
accessToken: string | undefined
rpcUrl: string
databasePath: string
carStoragePath: string
Expand Down
15 changes: 13 additions & 2 deletions src/filecoin-pinning-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,18 +114,29 @@ export async function createFilecoinPinningServer(
return
}

// If no access token is configured, allow all requests
if (!config.accessToken) {
request.user = DEFAULT_USER_INFO
return
}
Comment on lines +117 to +121
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@rvagg might have better insight, but this seems okay to me. may be easy to miss for consumers though

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think this is good because you will often be running this pinning server on the same machine as the client (e.g. pinmfs). If we don't want this behavior, then we need to make access-token mandatory.


const authHeader = request.headers.authorization
if (authHeader?.startsWith('Bearer ') !== true) {
await reply.code(401).send({ error: 'Missing or invalid authorization header' })
return
}

const token = authHeader.slice(7) // Remove 'Bearer ' prefix
if (token.trim().length === 0) {
const token = authHeader.slice(7).trim() // Remove 'Bearer ' prefix
if (token.length === 0) {
await reply.code(401).send({ error: 'Invalid access token' })
return
}

if (token !== config.accessToken) {
await reply.code(403).send({ error: 'Invalid access token' })
return
}

// Add user to request context
request.user = DEFAULT_USER_INFO
})
Expand Down
Loading