Skip to content

Commit

Permalink
authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
n1ru4l committed Aug 27, 2021
1 parent f0bd697 commit 87b2b1f
Show file tree
Hide file tree
Showing 8 changed files with 1,681 additions and 0 deletions.
3 changes: 3 additions & 0 deletions examples/complex/.env.sample
@@ -0,0 +1,3 @@
AUTH0_CLIENT_ID=
AUTH0_AUDIENCE=http://localhost:3000/graphql
AUTH0_DOMAIN=dream-watch.eu.auth0.com
1 change: 1 addition & 0 deletions examples/complex/README.md
@@ -0,0 +1 @@
# TODO
29 changes: 29 additions & 0 deletions examples/complex/package.json
@@ -0,0 +1,29 @@
{
"name": "@envelop-examples/example",
"private": true,
"version": "1.0.0",
"main": "index.js",
"author": "Laurin Quast",
"license": "MIT",
"dependencies": {
"@envelop/auth0": "1.0.0",
"@envelop/core": "1.0.4-alpha-5276a31.0",
"@graphql-tools/schema": "8.1.2",
"dotenv": "10.0.0",
"envalid": "7.2.1",
"fastify": "3.20.2",
"graphql": "experimental-stream-defer",
"graphql-helix": "1.7.0"
},
"devDependencies": {
"@envelop/apollo-tracing": "1.0.3",
"@types/node": "15.6.1",
"ts-node": "10.0.0",
"ts-node-dev": "1.1.8",
"typescript": "4.3.5"
},
"scripts": {
"start": "ts-node -r dotenv/config src/index.ts",
"start:dev": "ts-node-dev -r dotenv/config src/index.ts"
}
}
124 changes: 124 additions & 0 deletions examples/complex/src/index.ts
@@ -0,0 +1,124 @@
/* eslint-disable no-console */
import fastify from 'fastify';
import { getGraphQLParameters, processRequest, renderGraphiQL, shouldRenderGraphiQL } from 'graphql-helix';
import { envelop, useSchema } from '@envelop/core';
import { useAuth0 } from '@envelop/auth0';
import * as envalid from 'envalid';
import { handleHelixResult } from './util';
import { schema } from './schema';

const env = envalid.cleanEnv(process.env, {
AUTH0_CLIENT_ID: envalid.str(),
AUTH0_AUDIENCE: envalid.str(),
AUTH0_DOMAIN: envalid.str(),
});

const auth0Config = {
domain: env.AUTH0_DOMAIN,
audience: env.AUTH0_AUDIENCE,
clientId: env.AUTH0_CLIENT_ID,
};

const getEnveloped = envelop({
plugins: [
useSchema(schema),
useAuth0({
domain: auth0Config.domain,
audience: auth0Config.audience,
preventUnauthenticatedAccess: false, // If you need to have unauthenticated parts on your schema, make sure to disable that by setting it to `false` and the check it in your resolvers.
extendContextField: 'auth0', // The name of the field injected to your `context`
tokenType: 'Bearer', // Type of token to expect in the header
}),
],
});

const app = fastify();

app.route({
method: 'GET',
url: '/',
async handler(req, res) {
res.header('Content-Type', 'text/html; charset=UTF-8');
res.send(/* HTML */ `
<!DOCTYPE html />
<html>
<head>
<script src="https://cdn.auth0.com/js/auth0-spa-js/1.12/auth0-spa-js.production.js"></script>
</head>
<body>
<script>
createAuth0Client({
domain: '${auth0Config.domain}',
client_id: '${auth0Config.clientId}',
audience: '${auth0Config.audience}',
}).then(async auth0 => {
const isAuthenticated = await auth0.isAuthenticated();
await auth0.loginWithPopup();
const accessToken = await auth0.getTokenSilently();
window.document.body.innerText = accessToken;
});
</script>
</body>
</html>
`);
},
});

const graphiqlContent = /* GraphQL */ `
query isAuthenticated {
isAuthenticated
}
`;

app.route({
method: ['GET', 'POST'],
url: '/graphql',
async handler(req, res) {
const { parse, validate, contextFactory, execute, schema } = getEnveloped({ req });
const request = {
body: req.body,
headers: req.headers,
method: req.method,
query: req.query,
};

if (shouldRenderGraphiQL(request)) {
res.type('text/html');
res.send(
renderGraphiQL({
defaultQuery: graphiqlContent
.split('\n')
.slice(1)
.map(line => line.replace(' ', ''))
.join('\n'),
})
);
} else {
const request = {
body: req.body,
headers: req.headers,
method: req.method,
query: req.query,
};
const { operationName, query, variables } = getGraphQLParameters(request);

const result = await processRequest({
operationName,
query,
variables,
request,
schema,
parse,
validate,
execute,
contextFactory,
});

await handleHelixResult(result, req, res);
}
},
});

app.listen(3000, () => {
console.log(`GraphQL server is running on http://localhost:3000/graphql`);
});
24 changes: 24 additions & 0 deletions examples/complex/src/schema.ts
@@ -0,0 +1,24 @@
import { makeExecutableSchema } from '@graphql-tools/schema';

export const schema = makeExecutableSchema({
typeDefs: /* GraphQL */ `
type AuthenticationInfo {
sub: String!
}
type Query {
isAuthenticated: Boolean
authInfo: AuthenticationInfo
}
`,
resolvers: {
Query: {
isAuthenticated: (_, __, context) => {
return context.auth0 != null;
},
authInfo: (_, __, context) => {
return context.auth0;
},
},
},
});
53 changes: 53 additions & 0 deletions examples/complex/src/util.ts
@@ -0,0 +1,53 @@
import { FastifyReply, FastifyRequest } from 'fastify';
import { ProcessRequestResult } from 'graphql-helix';

export async function handleHelixResult(
result: ProcessRequestResult<any, any>,
req: FastifyRequest,
res: FastifyReply
): Promise<void> {
if (result.type === 'RESPONSE') {
res.statusCode = result.status;
res.send(result.payload);
} else if (result.type === 'MULTIPART_RESPONSE') {
res.raw.writeHead(200, {
Connection: 'keep-alive',
'Content-Type': 'multipart/mixed; boundary="-"',
'Transfer-Encoding': 'chunked',
});

req.raw.on('close', () => {
result.unsubscribe();
});

res.raw.write('---');

await result.subscribe(result => {
const chunk = Buffer.from(JSON.stringify(result), 'utf8');
const data = ['', 'Content-Type: application/json; charset=utf-8', 'Content-Length: ' + String(chunk.length), '', chunk];

if (result.hasNext) {
data.push('---');
}

res.raw.write(data.join('\r\n'));
});

res.raw.write('\r\n-----\r\n');
res.raw.end();
} else {
res.raw.writeHead(200, {
'Content-Type': 'text/event-stream',
Connection: 'keep-alive',
'Cache-Control': 'no-cache',
});

req.raw.on('close', () => {
result.unsubscribe();
});

await result.subscribe(result => {
res.raw.write(`data: ${JSON.stringify(result)}\n\n`);
});
}
}
26 changes: 26 additions & 0 deletions examples/complex/tsconfig.json
@@ -0,0 +1,26 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"target": "es2020",
"lib": ["es2020"],
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"outDir": "dist",
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"alwaysStrict": true,
"noImplicitAny": false,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"importHelpers": true,
"skipLibCheck": true
},
"include": ["./src"],
"exclude": ["node_modules"]
}

0 comments on commit 87b2b1f

Please sign in to comment.