0
2
"use strict";
// Patched for local HTTP development: Secure flag removed from CSRF cookie
// so ASWebAuthenticationSession on iOS can send it over HTTP://localhost.
// This file is mounted into the PDS container via docker-compose.yml.
// See: @atproto/oauth-provider/dist/router/assets/csrf.js
var __importDefault =
(this && this.__importDefault) ||
function (mod) {
return mod && mod.__esModule ? mod : { default: mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupCsrfToken = setupCsrfToken;
exports.validateCsrfToken = validateCsrfToken;
exports.getCookieCsrf = getCookieCsrf;
exports.getHeadersCsrf = getHeadersCsrf;
const http_errors_1 = __importDefault(require("http-errors"));
const oauth_provider_api_1 = require("@atproto/oauth-provider-api");
const index_js_1 = require("../../lib/http/index.js");
const crypto_js_1 = require("../../lib/util/crypto.js");
const TOKEN_BYTE_LENGTH = 12;
const TOKEN_LENGTH = TOKEN_BYTE_LENGTH * 2; // 2 hex chars per byte
const CSRF_COOKIE_OPTIONS = {
expires: undefined,
secure: false, // patched: was true, breaks iOS ASWebAuthenticationSession over HTTP
httpOnly: false,
sameSite: "lax",
path: `/`,
};
async function generateCsrfToken() {
return (0, crypto_js_1.randomHexId)(TOKEN_BYTE_LENGTH);
}
async function setupCsrfToken(req, res) {
const token = getCookieCsrf(req) || (await generateCsrfToken());
(0, index_js_1.setCookie)(res, oauth_provider_api_1.CSRF_COOKIE_NAME, token, CSRF_COOKIE_OPTIONS);
}
async function validateCsrfToken(req, res) {
const cookieValue = getCookieCsrf(req);
const headerValue = getHeadersCsrf(req);
(0, index_js_1.setCookie)(
res,
oauth_provider_api_1.CSRF_COOKIE_NAME,
cookieValue || (await generateCsrfToken()),
CSRF_COOKIE_OPTIONS,
);
if (!headerValue) {
throw (0, http_errors_1.default)(400, `Missing CSRF header`);
}
if (!cookieValue) {
throw (0, http_errors_1.default)(400, `Missing CSRF cookie`);
}
if (cookieValue !== headerValue) {
throw (0, http_errors_1.default)(400, `CSRF mismatch`);
}
}
function getCookieCsrf(req) {
const cookieValue = (0, index_js_1.getCookie)(req, oauth_provider_api_1.CSRF_COOKIE_NAME);
if (cookieValue?.length === TOKEN_LENGTH) {
return cookieValue;
}
return undefined;
}
function getHeadersCsrf(req) {
const headerValue = req.headers[oauth_provider_api_1.CSRF_HEADER_NAME];
if (typeof headerValue === "string" && headerValue.length === TOKEN_LENGTH) {
return headerValue;
}
return undefined;
}