UNPKG

realm-object-server

Version:

Realm Object Server

231 lines 11.1 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 auth = require("../auth"); const TestServer_1 = require("../TestServer"); const path = require("path"); const NodeRSA = require("node-rsa"); const uuid = require("uuid"); const jwt = require("jsonwebtoken"); const superagent = require("superagent"); const chai_1 = require("chai"); const util_1 = require("../shared/util"); describe("Custom Refresh Token integration", function () { let publicKey; let privateKey; let server; const signToken = (options = {}, signOptions = {}) => { const payload = { isAdmin: options.isAdmin || false, sub: options.userId || uuid.v4(), }; const validatedSignOptions = { issuer: util_1.getValueOrDefault(signOptions.issuer, "myissuer"), algorithm: util_1.getValueOrDefault(signOptions.algorightm, "RS256"), expiresIn: util_1.getValueOrDefault(signOptions.expiresIn, 3600), jwtid: uuid.v4(), }; const audience = util_1.getValueOrDefault(signOptions.audience, "myapp"); if (audience) { validatedSignOptions.audience = audience; } return jwt.sign(payload, util_1.getValueOrDefault(signOptions.privateKey, privateKey), validatedSignOptions); }; const login = (payload, shouldSucceed = true) => __awaiter(this, void 0, void 0, function* () { const promise = superagent.post(`${server.url}/auth`).send(payload); if (shouldSucceed) { const result = yield chai_1.assert.isFulfilled(promise); return result; } const error = yield chai_1.assert.isRejected(promise); return error; }); const loginRefresh = (token, shouldSucceed = true) => __awaiter(this, void 0, void 0, function* () { return login({ data: token, path: "/~/foo", provider: "realm" }, shouldSucceed); }); before(function () { return __awaiter(this, void 0, void 0, function* () { this.timeout(30000); const key = new NodeRSA({ b: 2048 }); privateKey = key.exportKey("pkcs8-private-pem"); publicKey = key.exportKey("pkcs8-public-pem"); server = new TestServer_1.TestServer(); yield server.start({ authProviders: [ new auth.PasswordAuthProvider({ autoCreateAdminUser: true, iterations: 1 }), new auth.AnonymousAuthProvider(), ], https: true, httpsKeyPath: path.join(__dirname, "..", "..", "fixtures", "https.key"), httpsCertChainPath: path.join(__dirname, "..", "..", "fixtures", "https.crt"), logLevel: "off", refreshTokenValidators: [{ algorithms: ["RS256"], audience: "myapp", issuer: "myissuer", publicKey, isAdminQuery: { path: "$.isAdmin", value: true } }, { publicKey, issuer: "defaults", }] }); }); }); after(function () { return __awaiter(this, void 0, void 0, function* () { if (server) { yield server.shutdown(); } }); }); describe("/auth", function () { it("authenticates non-existing user", () => __awaiter(this, void 0, void 0, function* () { const userId = uuid.v4(); const token = signToken({ userId }); const response = yield loginRefresh(token); const accessToken = response.body.access_token; chai_1.assert.isString(accessToken.token); chai_1.assert.equal(accessToken.token_data.identity, userId); chai_1.assert.equal(accessToken.token_data.path, `/${userId}/foo`); })); it("authenticates an existing user", () => __awaiter(this, void 0, void 0, function* () { const anonResponse = yield login({ provider: "anonymous" }); const userId = anonResponse.body.refresh_token.token_data.identity; const token = signToken({ userId }); const customResponse = yield loginRefresh(token); const accessToken = customResponse.body.access_token; chai_1.assert.isString(accessToken.token); chai_1.assert.equal(accessToken.token_data.identity, userId); })); it("authenticates an admin user", () => __awaiter(this, void 0, void 0, function* () { const token = signToken({ isAdmin: true }); const response = yield login({ provider: "realm", data: token, path: "/this-is-in-root" }); const accessToken = response.body.access_token; chai_1.assert.deepEqual(accessToken.token_data.access, ["download", "upload", "manage"]); })); }); describe("invalid options", function () { it("rejects mismatching issuers", () => __awaiter(this, void 0, void 0, function* () { const token = signToken({}, { issuer: "rogueIssuer" }); const error = yield loginRefresh(token, false); chai_1.assert.equal(error.status, 401); })); it("rejects mismatching audience", () => __awaiter(this, void 0, void 0, function* () { const token = signToken({}, { audience: "some-other-app" }); const error = yield loginRefresh(token, false); chai_1.assert.equal(error.status, 401); })); it("rejects invalid private key", () => __awaiter(this, void 0, void 0, function* () { const token = signToken({}, { privateKey: new NodeRSA({ b: 2048 }).exportKey("pkcs8-private-pem") }); const error = yield loginRefresh(token, false); chai_1.assert.equal(error.status, 401); })); it("rejects expired tokens", () => __awaiter(this, void 0, void 0, function* () { const token = signToken({}, { expiresIn: -1 }); const error = yield loginRefresh(token, false); chai_1.assert.equal(error.status, 401); })); }); describe("/revoke", function () { it("revokes a token", () => __awaiter(this, void 0, void 0, function* () { const userId = uuid.v4(); const token = signToken({ userId }); yield loginRefresh(token); yield chai_1.assert.isFulfilled(superagent.post(`${server.url}/auth/revoke`) .set({ Authorization: token }) .send({ token, })); yield loginRefresh(token, false); const newToken = signToken({ userId }); yield loginRefresh(newToken); })); }); describe("permissions", function () { const getPermissions = (token) => __awaiter(this, void 0, void 0, function* () { const response = yield chai_1.assert.isFulfilled(superagent.get(`${server.url}/permissions`) .set({ Authorization: token }).send()); return response.body.permissions; }); it("can see granted permissions", () => __awaiter(this, void 0, void 0, function* () { const token = signToken(); const permissions = yield getPermissions(token); chai_1.assert.equal(permissions.length, 1); yield loginRefresh(token); const newPermissions = yield getPermissions(token); chai_1.assert.equal(newPermissions.length, 2); chai_1.assert.isOk(newPermissions.find(p => p.path.endsWith("/foo"))); })); it("can grant permissions", () => __awaiter(this, void 0, void 0, function* () { const grantorId = uuid.v4(); const grantorToken = signToken({ userId: grantorId }); yield loginRefresh(grantorToken); const granteeId = uuid.v4(); const granteeToken = signToken({ userId: granteeId }); yield loginRefresh(granteeToken); let granteePerms = yield getPermissions(granteeToken); chai_1.assert.equal(granteePerms.length, 2); yield chai_1.assert.isFulfilled(superagent.post(`${server.url}/permissions/apply`) .set({ Authorization: grantorToken }) .send({ realmPath: `/${grantorId}/foo`, accessLevel: "write", condition: { userId: granteeId } })); granteePerms = yield getPermissions(granteeToken); chai_1.assert.equal(granteePerms.length, 3); const grantorFooPermission = granteePerms.find(p => p.path === `/${grantorId}/foo`); chai_1.assert.isOk(grantorFooPermission); chai_1.assert.equal(grantorFooPermission.accessLevel, "write"); })); }); describe("defaults", function () { const testLogin = (options) => __awaiter(this, void 0, void 0, function* () { const userId = uuid.v4(); const token = signToken({ userId }, Object.assign({ issuer: "defaults" }, options)); const response = yield loginRefresh(token); chai_1.assert.equal(response.body.access_token.token_data.identity, userId); return response.body.access_token.token_data; }); it("accepts RS512 tokens", () => __awaiter(this, void 0, void 0, function* () { yield testLogin({ algorightm: "RS512" }); })); it("accepts missing audience", () => __awaiter(this, void 0, void 0, function* () { yield testLogin({ audience: null }); })); it("accepts random audience", () => __awaiter(this, void 0, void 0, function* () { yield testLogin({ audience: "my-shady-app" }); })); it("cannot login an admin", () => __awaiter(this, void 0, void 0, function* () { const userId = uuid.v4(); const token = signToken({ userId, isAdmin: true }, { issuer: "defaults" }); const error = yield login({ provider: "realm", data: token, path: "/this-is-in-root" }, false); chai_1.assert.equal(error.status, 403); })); }); }); //# sourceMappingURL=custom-refresh-integration-tests.spec.js.map