UNPKG

realm-object-server

Version:

Realm Object Server

119 lines 4.96 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const AuthProvider_1 = require("../AuthProvider"); const errors = require("../../errors"); const crypto = require("crypto"); const superagent = require("superagent"); const fs = require("fs-extra"); const cloudKitBaseUri = "https://api.apple-cloudkit.com"; const protocolVersion = 1; class CloudkitAuthProvider extends AuthProvider_1.AuthProvider { constructor(config) { super(); this.name = "cloudkit"; this.options = config; } start() { return __awaiter(this, void 0, void 0, function* () { this.privateKey = yield fs.readFile(this.options.privateKeyPath, "utf-8"); }); } authenticateOrCreateUser(body) { return __awaiter(this, void 0, void 0, function* () { let userRecordName = body.data; if (!userRecordName) { throw new errors.realm.MissingParameters("data"); } const foundUser = this.service.getUserByProviderId("cloudkit", userRecordName); if (foundUser) { return foundUser; } const path = this.absoluteDatabasePath("users/discover"); const requestBody = { lookupInfos: [{ userRecordName }], }; let response; try { response = yield this.signedRequest(path, requestBody); } catch (err) { if (err.response && err.response.body) { const body = err.response.body; const reason = body.reason; if (reason === "No valid user ids to lookup") { throw new errors.realm.InvalidCredentials(); } } throw err; } if (response.body.users === undefined) { throw new Error("Cloutkit: response did not contain any user."); } if (response.body.users.length !== 1) { throw new Error(`Cloudkit: response contained unexpected number of users: ${response.body.users.length}.`); } const lookupInfo = userRecordName = response.body.users[0].lookupInfo; if (!lookupInfo) { throw new Error("Cloudkit: response did not contain lookupInfo."); } userRecordName = lookupInfo.userRecordName; if (!userRecordName) { throw new Error("Cloudkit: response did not contain userRecordName."); } return this.service.createOrUpdateUser(userRecordName, "cloudkit", false); }); } signedRequest(path, body) { return __awaiter(this, void 0, void 0, function* () { const date = new Date().toISOString().replace(/.\d{3}(\w+)$/, "$1"); const bodyJson = JSON.stringify(body); const bodyHash = this.hash(bodyJson); const signature = this.sign(`${date}:${bodyHash}:${path}`); const typeRequestHeaders = { "Accept": "application/json", "Content-Type": "text/plain", }; const authRequestHeaders = { "X-Apple-CloudKit-Request-ISO8601Date": date, "X-Apple-CloudKit-Request-KeyID": this.options.keyId, "X-Apple-CloudKit-Request-SignatureV1": signature, }; const header = Object.assign(typeRequestHeaders, authRequestHeaders); const url = `${cloudKitBaseUri}${path}`; return superagent .post(url) .set(header) .send(bodyJson); }); } absoluteDatabasePath(path) { return [ "/database", protocolVersion, this.options.container, this.options.environment, "public", path, ].join("/"); } hash(str) { const hash = crypto.createHash("sha256"); hash.update(str); return hash.digest("base64"); } sign(str) { const sign = crypto.createSign("RSA-SHA256"); sign.update(str); return sign.sign(this.privateKey, "base64"); } } exports.CloudkitAuthProvider = CloudkitAuthProvider; //# sourceMappingURL=CloudkitAuthProvider.js.map