Skip to content
Merged
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
28 changes: 26 additions & 2 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ function errorResult(err) {
return { error: err instanceof APIError ? err.message : String(err) };
}

// True for IPv4/IPv6 loopback addresses, including the IPv4-mapped IPv6 form
// Node reports for localhost connections.
function isLoopback(ip) {
return ip === '127.0.0.1' || ip === '::1' || ip === '::ffff:127.0.0.1';
}

// Build the Express app around a Castle client. Accepting the client as an
// argument keeps the routes easy to test (the SDK can be stubbed).
function buildApp(castle = require('./castle')) {
Expand Down Expand Up @@ -91,8 +97,26 @@ function buildApp(castle = require('./castle')) {

// Build the request context (IP, headers, client id) Castle needs from a Node
// request. Lists/Privacy/Events are account-level and don't need it.
const buildContext = (req) =>
ContextPrepareService.call(req, {}, castle.configuration);
//
// The SDK derives the client IP from headers only (X-Forwarded-For, then
// Remote-Addr). In Node the peer address lives on the socket rather than in a
// header, so running this demo directly on localhost neither is present and
// Castle rejects the call with "context[ip] is missing". When the connection
// is loopback (i.e. local development) expose the socket peer as Remote-Addr
// so the demo works. In production a proxy sets X-Forwarded-For with the real
// client IP, so this fallback never applies.
const buildContext = (req) => {
const peer = req.socket?.remoteAddress;
if (
peer &&
isLoopback(peer) &&
!req.headers['x-forwarded-for'] &&
!req.headers['remote-addr']
) {
req.headers['remote-addr'] = peer;
}
return ContextPrepareService.call(req, {}, castle.configuration);
};

// a default value reused across the login / password-reset demos
let registeredAt = '2020-02-23T22:28:55.387Z';
Expand Down
Loading