@graphql-yoga/plugin-jwt
Version:
jwt plugin for GraphQL Yoga.
105 lines (104 loc) • 3.44 kB
JavaScript
import { createGraphQLError } from 'graphql-yoga';
import { JwksClient } from 'jwks-rsa';
import '@whatwg-node/server-plugin-cookies';
import { handleMaybePromise } from '@whatwg-node/promise-helpers';
export function extractFromHeader(options) {
return ({ request }) => {
if (!request) {
return;
}
const header = request.headers.get(options.name);
if (header == null) {
return;
}
if (!options.prefix) {
const parts = header.split(' ').map(s => s.trim());
const [prefix, token] = parts.length === 1 ? [undefined, parts[0]] : parts;
if (!token) {
throw badRequestError(`Authentication header was set, but token is missing.`);
}
return {
prefix,
token,
};
}
const [prefix, token] = header.split(' ').map(s => s.trim());
if (prefix !== options.prefix) {
throw badRequestError(`Invalid JWT authentication token prefix.`);
}
if (!token) {
throw badRequestError(`Authentication header was set, but token is missing.`);
}
return {
prefix,
token,
};
};
}
export function extractFromCookie(options) {
return ({ request }) => {
if (!request) {
return;
}
const cookieStore = request.cookieStore;
if (!cookieStore) {
throw new Error('Cookie store is not available on request. Please make sure to configure the cookie plugin.');
}
return handleMaybePromise(() => cookieStore.get(options.name), cookie => {
if (!cookie) {
return;
}
return {
prefix: undefined,
token: cookie.value,
};
});
};
}
export function extractFromConnectionParams(options) {
return ({ serverContext }) => {
if (typeof serverContext?.['connectionParams'] === 'object' &&
serverContext['connectionParams'] != null &&
options.name in serverContext['connectionParams'] &&
typeof serverContext['connectionParams'] === 'object' &&
serverContext['connectionParams'] != null &&
options.name in serverContext['connectionParams']) {
// @ts-expect-error - TS doesn't understand the type guard above
const token = serverContext['connectionParams'][options.name];
if (typeof token === 'string') {
return {
prefix: undefined,
token,
};
}
}
return;
};
}
export function badRequestError(message, options) {
return createGraphQLError(message, {
extensions: {
http: {
status: 400,
},
},
...options,
});
}
export function unauthorizedError(message, options) {
return createGraphQLError(message, {
extensions: {
http: {
status: 401,
},
},
...options,
});
}
export function createInlineSigningKeyProvider(signingKey) {
return () => signingKey;
}
export function createRemoteJwksSigningKeyProvider(jwksClientOptions) {
const client = new JwksClient(jwksClientOptions);
return kid => client.getSigningKey(kid)?.then(r => r.getPublicKey());
}