UNPKG

6.9 kBJavaScriptView Raw
1"use strict";
2var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 if (k2 === undefined) k2 = k;
4 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5}) : (function(o, m, k, k2) {
6 if (k2 === undefined) k2 = k;
7 o[k2] = m[k];
8}));
9var __exportStar = (this && this.__exportStar) || function(m, exports) {
10 for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
11};
12var __importDefault = (this && this.__importDefault) || function (mod) {
13 return (mod && mod.__esModule) ? mod : { "default": mod };
14};
15Object.defineProperty(exports, "__esModule", { value: true });
16exports.AuthX = void 0;
17const koa_body_1 = __importDefault(require("koa-body"));
18const uuid_1 = require("uuid");
19const graphql_playground_middleware_koa_1 = __importDefault(require("graphql-playground-middleware-koa"));
20const koa_router_1 = __importDefault(require("koa-router"));
21const graphql_api_koa_1 = require("graphql-api-koa");
22const auth_header_1 = require("auth-header");
23const pg_1 = require("pg");
24const x_1 = __importDefault(require("./x"));
25const oauth2_1 = __importDefault(require("./oauth2"));
26const Config_1 = require("./Config");
27const graphql_1 = require("./graphql");
28const getAuthorization_1 = require("./util/getAuthorization");
29const StrategyCollection_1 = require("./StrategyCollection");
30const errors_1 = require("./errors");
31const explanations_1 = require("./explanations");
32const loader_1 = require("./loader");
33__exportStar(require("./x"), exports);
34__exportStar(require("./errors"), exports);
35__exportStar(require("./loader"), exports);
36__exportStar(require("./model"), exports);
37__exportStar(require("./graphql"), exports);
38__exportStar(require("./Strategy"), exports);
39__exportStar(require("./StrategyCollection"), exports);
40__exportStar(require("./Config"), exports);
41__exportStar(require("./Context"), exports);
42__exportStar(require("./util/validateIdFormat"), exports);
43class AuthX extends koa_router_1.default {
44 constructor(config) {
45 Config_1.assertConfig(config);
46 super(config);
47 const explanations = explanations_1.createAuthXExplanations({ [config.realm]: "AuthX" });
48 const strategies = config.strategies instanceof StrategyCollection_1.StrategyCollection
49 ? config.strategies
50 : new StrategyCollection_1.StrategyCollection(config.strategies);
51 // create a database pool
52 this.pool = new pg_1.Pool(config.pg);
53 // define the context middleware
54 const contextMiddleware = async (ctx, next) => {
55 const tx = await this.pool.connect();
56 try {
57 let authorization = null;
58 const auth = ctx.request.header.authorization
59 ? auth_header_1.parse(ctx.request.header.authorization)
60 : null;
61 // HTTP Basic Authorization
62 const basic = auth && auth.scheme === "Basic" && typeof auth.token === "string"
63 ? auth.token
64 : null;
65 if (basic) {
66 authorization = await getAuthorization_1.fromBasic(tx, basic);
67 // Invoke the authorization. Because the resource validates basic
68 // tokens by making a GraphQL request here, each request can be
69 // considered an invocation.
70 await authorization.invoke(tx, {
71 id: uuid_1.v4(),
72 format: "basic",
73 createdAt: new Date()
74 });
75 }
76 // Bearer Token Authorization
77 const bearer = auth && auth.scheme === "Bearer" && typeof auth.token === "string"
78 ? auth.token
79 : null;
80 if (bearer) {
81 authorization = await getAuthorization_1.fromBearer(tx, config.publicKeys, bearer);
82 // There is no need to invoke this authorization here, since it was
83 // invoked when the bearer token was generated.
84 }
85 // An authorization header exists, but did not match a known format.
86 if (ctx.request.header.authorization && !authorization) {
87 throw new Error("An authorization header must be of either HTTP Basic or Bearer format.");
88 }
89 const context = {
90 ...ctx[x_1.default],
91 ...config,
92 authorization,
93 explanations: explanations,
94 executor: new loader_1.DataLoaderExecutor(this.pool, strategies)
95 };
96 ctx[x_1.default] = context;
97 }
98 finally {
99 tx.release();
100 }
101 await next();
102 };
103 // GraphQL
104 // =======
105 // The GraphQL endpoint is the primary API for interacting with AuthX.
106 this.post("/graphql", graphql_api_koa_1.errorHandler(), contextMiddleware,
107 // The GraphQL endpoint only accepts JSON. This helps protect against CSRF
108 // attacks that send urlenceded data via HTML forms.
109 async (ctx, next) => {
110 if (!ctx.is("json"))
111 throw new errors_1.UnsupportedMediaTypeError("Requests to the AuthX GraphQL endpoint MUST specify a Content-Type of `application/json`.");
112 await next();
113 }, koa_body_1.default({ multipart: false, urlencoded: false, text: false, json: true }), graphql_api_koa_1.execute({
114 schema: config.processSchema
115 ? config.processSchema(graphql_1.createSchema(strategies))
116 : graphql_1.createSchema(strategies),
117 override: (ctx) => {
118 const contextValue = ctx[x_1.default];
119 return {
120 contextValue
121 };
122 }
123 }));
124 // GraphiQL
125 // ========
126 // This is a graphical (get it, graph-i-QL) interface to the AuthX API.
127 this.all("/graphiql", graphql_playground_middleware_koa_1.default({ endpoint: "/graphql" }));
128 // OAuth
129 // =====
130 // The core AuthX library supports the following OAuth2 grant types:
131 //
132 // - `authorization_code`
133 // - `refresh_token`
134 //
135 // Because it involves presentation elements, the core AuthX library does
136 // **not** implement the `code` grant type. Instead, a compatible reference
137 // implementation of this flow is provided by the `authx-interface` NPM
138 // package.
139 this.post("/", contextMiddleware, koa_body_1.default({ multipart: false, urlencoded: true, text: false, json: true }), oauth2_1.default);
140 }
141}
142exports.AuthX = AuthX;
143exports.default = AuthX;
144//# sourceMappingURL=index.js.map
\No newline at end of file