Skip to content

Commit

Permalink
Merge pull request #3 from hammerframework/pp-add-auth0
Browse files Browse the repository at this point in the history
Use Auth0 for authentication.
  • Loading branch information
peterp authored Jul 13, 2019
2 parents e0b2c67 + 4f7c675 commit aa0480f
Show file tree
Hide file tree
Showing 23 changed files with 960 additions and 117 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ dist
yarn-error.log
.docz
*/.env
.env
.DS_Store

api/failed-*.md
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ Browse to `http://localhost:8910` to see the web app. Lambda functions run on
`yarn hammer generate component MyShinyComponent` will create a component
and place it under `web/src/components/MyShinyComponent`

### .ENV

Auth0 requires a few environmental variables, none of those are private,
so just go ahead and use these:

```
AUTH0_DOMAIN=p4p8.eu.auth0.com
AUTH0_CLIENT_ID=b7vN4sVz6yjGrq82ctXJW9NRTvlWzkFU
AUTH0_AUDIENCE=BILLABLE_API
```

### Transpiling packages

There are a bunch of packages in this repository that will eventually be published
Expand Down
3 changes: 3 additions & 0 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
"dependencies": {
"@hammerframework/hammer-api": "0.0.0",
"apollo-server-lambda": "^2.6.2",
"dotenv": "^8.0.0",
"express-jwt": "^5.3.1",
"graphql": "^14.3.1",
"jwks-rsa": "^1.5.1",
"nexus": "^0.11.7",
"require-dir": "^1.2.0"
},
Expand Down
2 changes: 2 additions & 0 deletions api/src/functions/graphql.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { graphQLServerlessFunction } from "@hammerframework/hammer-api";

export const SERVERLESS_FUNCTION_TYPE = "aws";

export const handler = graphQLServerlessFunction();
41 changes: 41 additions & 0 deletions api/src/functions/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// // https://www.netlify.com/blog/2018/09/13/how-to-run-express.js-apps-with-netlify-functions/
// // https://github.com/dougmoscrop/serverless-http

import jwt from "express-jwt";
import jwksRsa from "jwks-rsa";

import dotenv from "dotenv";

// hammer base dir.
dotenv.config("../../.env");

// Set up Auth0 configuration
const authConfig = {
domain: process.env.AUTH0_DOMAIN,
audience: process.env.AUTH0_AUDIENCE
};

// Define middleware that validates incoming bearer tokens
// using JWKS from p4p8.eu.auth0.com
const checkJwt = jwt({
secret: jwksRsa.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://${authConfig.domain}/.well-known/jwks.json`
}),

audience: authConfig.audience,
issuer: `https://${authConfig.domain}/`,
algorithm: ["RS256"]
});

export const SERVERLESS_FUNCTION_TYPE = "express";

export const handler = (req, res, next) => {
checkJwt(req, res, next);

res.send({
msg: "Your Access Token was successfully validated!"
});
};
76 changes: 42 additions & 34 deletions packages/hammer-dev-server/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ app.all("/", (req, res) => {
`);
});

app.all("/:routeName", (req, res) => {
app.all("/:routeName", (req, res, next) => {
const { routeName } = req.params;

const lambdaFunction = lambdaFunctions[routeName];
Expand All @@ -82,44 +82,52 @@ app.all("/:routeName", (req, res) => {
return res.sendStatus(404);
}

const { handler } = lambdaFunction;
// We _really_ only want to support express js type functions, but until then
// we have to deal with figuring out who you're trying to target.

const { handler, SERVERLESS_FUNCTION_TYPE = "aws" } = lambdaFunction;

if (typeof handler !== "function") {
console.warn(`"${routeName}" does not export a function named "handler"`);
return res.sendStatus(500);
}

const event = {
httpMethod: req.method,
headers: req.headers,
path: req.path,
queryStringParameters: qs.parse(req.url.split(/\?(.+)/)[1]),
...parseBody(req.body) // adds `body` and `isBase64Encoded`
};

const handlerCallback = response => (
error,
{ statusCode, body, headers = {} }
) => {
// TODO: Deal with errors
if (error) {
console.log("----------");
console.log(error);
console.log("----------");
}

Object.keys(headers).forEach(header => {
response.setHeader(header, headers[header]);
});
response.statusCode = statusCode;
return response.end(body);
};

// TODO: Add support for promises.
handler(
event,
{}, // TODO: Support context
handlerCallback(res)
);
if (SERVERLESS_FUNCTION_TYPE === "aws") {
const event = {
httpMethod: req.method,
headers: req.headers,
path: req.path,
queryStringParameters: qs.parse(req.url.split(/\?(.+)/)[1]),
...parseBody(req.body) // adds `body` and `isBase64Encoded`
};

const handlerCallback = response => (
error,
{ statusCode, body, headers = {} }
) => {
// TODO: Deal with errors
if (error) {
console.log("----------");
console.log(error);
console.log("----------");
}

Object.keys(headers).forEach(header => {
response.setHeader(header, headers[header]);
});
response.statusCode = statusCode;
return response.end(body);
};

// TODO: Add support for promises.
handler(
event,
{}, // TODO: Support context
handlerCallback(res)
);
} else if (SERVERLESS_FUNCTION_TYPE === "express") {
handler(req, res, next);
}
});

app.listen(PORT, () =>
Expand Down
1 change: 1 addition & 0 deletions web/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
]
],
"plugins": [
"@babel/plugin-transform-runtime",
[
"babel-plugin-module-resolver",
{
Expand Down
11 changes: 9 additions & 2 deletions web/config/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,26 @@ const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const DirectoryNamedWebpackPlugin = require("directory-named-webpack-plugin");
const Dotenv = require("dotenv-webpack");

console.log(path.resolve(__dirname, "../../.env"));

module.exports = {
entry: {
app: path.resolve(__dirname, "../src/App.js")
app: path.resolve(__dirname, "../src/index.js")
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/template.html"
template: "./src/index.html"
}),
new webpack.ProvidePlugin({
React: "react",
PropTypes: "prop-types",
gql: ["@hammerframework/hammer-web", "gql"]
}),
new Dotenv({
// billable base-directory
path: path.resolve(__dirname, "../../.env")
})
],
module: {
Expand Down
5 changes: 5 additions & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,28 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@auth0/auth0-spa-js": "^1.0.2",
"@babel/runtime": "^7.5.1",
"@hammerframework/hammer-web": "0.0.0",
"immer": "^3.1.3",
"prop-types": "^15.7.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-router-dom": "^5.0.1",
"react-textarea-autosize": "^7.1.0",
"rebass": "^3.1.1",
"rebass-extend": "^1.0.1",
"styled-components": "^4.3.2",
"styled-system": "^5.0.12"
},
"devDependencies": {
"@babel/plugin-transform-runtime": "^7.5.0",
"babel-loader": "^8.0.6",
"babel-plugin-module-resolver": "^3.2.0",
"babel-plugin-styled-components": "^1.10.6",
"css-loader": "^3.0.0",
"directory-named-webpack-plugin": "^4.0.1",
"dotenv-webpack": "^1.7.0",
"file-loader": "^4.0.0",
"html-webpack-plugin": "^3.2.0",
"style-loader": "^0.23.1",
Expand Down
17 changes: 0 additions & 17 deletions web/src/App.js

This file was deleted.

60 changes: 43 additions & 17 deletions web/src/components/AppBar.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,49 @@
import { Box } from "src/lib/primitives";
import { Flex, Box, Button } from "src/lib/primitives";
import { useAuth0 } from "src/lib/auth0";
import { Link } from "react-router-dom";

export default () => (
<Box
bg="blue"
css={`
height: 64px;
`}
>
export default () => {
const { isAuthenticated, loginWithRedirect, logout } = useAuth0();

return (
<Box
color="white"
fontSize={5}
pl="8px"
m="auto"
bg="blue"
css={`
width: 800px;
line-height: 64px;
height: 64px;
`}
>
Billable
<Flex
flexDirection="row"
color="white"
fontSize={5}
pl="8px"
m="auto"
css={`
width: 800px;
line-height: 64px;
`}
>
Billable
<Box
ml="auto"
css={`
display: flex;
align-items: center;
`}
>
{!isAuthenticated && (
<>
<Button onClick={() => loginWithRedirect({})}>Log in</Button>
<Button onClick={() => loginWithRedirect({})}>Sign up</Button>
</>
)}
{isAuthenticated && (
<>
<Button onClick={() => logout()}>Log out</Button>
</>
)}
</Box>
</Flex>
</Box>
</Box>
);
);
};
25 changes: 0 additions & 25 deletions web/src/components/Help/Help.js

This file was deleted.

File renamed without changes.
File renamed without changes.
28 changes: 28 additions & 0 deletions web/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import ReactDOM from "react-dom";
import { GraphQLProvider } from "@hammerframework/hammer-web";
import { ThemeProvider } from "styled-components";

import { Auth0Provider } from "src/lib/auth0";

import theme from "src/lib/theme";
import Routes from "src/pages/Routes";

import "./index.css";

ReactDOM.render(
<GraphQLProvider>
<ThemeProvider theme={theme}>
<Auth0Provider
config={{
domain: process.env.AUTH0_DOMAIN,
client_id: process.env.AUTH0_CLIENT_ID,
audience: process.env.AUDIENCE,
redirect_uri: window.location.origin
}}
>
<Routes />
</Auth0Provider>
</ThemeProvider>
</GraphQLProvider>,
document.getElementById("hammer-app")
);
Loading

0 comments on commit aa0480f

Please sign in to comment.