Skip to content

Commit

Permalink
feat: auto-create Hydra client on startup
Browse files Browse the repository at this point in the history
Signed-off-by: Eric Dobbertin <eric@dairystatedesigns.com>
  • Loading branch information
aldeed committed Dec 13, 2019
1 parent d2590c8 commit 052a330
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 103 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ ENABLE_SPA_ROUTING=true
EXTERNAL_GRAPHQL_URL=http://localhost:3000/graphql-beta
INTERNAL_GRAPHQL_URL=http://api.api.reaction.localhost:3000/graphql-beta
OAUTH2_ADMIN_PORT=4445
OAUTH2_ADMIN_URL=http://hydra.auth.reaction.localhost:4445
OAUTH2_AUTH_URL=http://localhost:4444/oauth2/auth
OAUTH2_CLIENT_ID=example-storefront
OAUTH2_CLIENT_SECRET=CHANGEME
Expand Down
78 changes: 0 additions & 78 deletions bin/create-hydra-client.js

This file was deleted.

4 changes: 3 additions & 1 deletion bin/start
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ IFS="$(printf "\n\t")"

cd "$(dirname "$0")/.."
yarn install
./bin/create-hydra-client.sh
printf "Waiting for Hydra service... "
./bin/wait-for.sh "${OAUTH2_HOST}:${OAUTH2_ADMIN_PORT}"
printf "Hydra service found!\n"
yarn start:dev
13 changes: 0 additions & 13 deletions bin/start-prod.sh

This file was deleted.

1 change: 1 addition & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ version: '3.4'
services:
web:
image: reactioncommerce/node-dev:10.16.3-v2
command: "./bin/start"
volumes:
- .:/usr/local/src/app
- web-yarn:/home/node/.cache/yarn
Expand Down
9 changes: 0 additions & 9 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,10 @@ networks:
services:
web:
image: reactioncommerce/example-storefront:release-v3.0.0
# The only reason we need to override the command is to auto-create
# the Hydra client if it doesn't exist. In the future, we plan to
# make this logic part of the codebase, at which point this can be
# removed.
command: "./bin/start-prod.sh"
env_file:
- ./.env
networks:
api:
auth:
ports:
- 4000:4000
volumes:
# This volume is needed only to run the `command` above.
# When the command is removed, this volume can also be removed.
- ./bin:/usr/local/src/app/bin
1 change: 1 addition & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ if (process.env.IS_BUILDING_NEXTJS) {
EXTERNAL_GRAPHQL_URL: url(),
INTERNAL_GRAPHQL_URL: url(),
NODE_ENV: str({ choices: ["development", "test", "jesttest", "production"], default: "production" }),
OAUTH2_ADMIN_URL: str(),
OAUTH2_AUTH_URL: url(),
OAUTH2_CLIENT_ID: str(),
OAUTH2_CLIENT_SECRET: str(),
Expand Down
3 changes: 2 additions & 1 deletion src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const { useStaticRendering } = require("mobx-react");
const config = require("./config");
const logger = require("./lib/logger");
const router = require("./routes");
const { configureAuthForServer } = require("./serverAuth");
const { configureAuthForServer, createHydraClientIfNecessary } = require("./serverAuth");
const { sitemapRoutesHandler } = require("./sitemapRoutesHandler");

if (config.isDev) {
Expand All @@ -26,6 +26,7 @@ useStaticRendering(true);

app
.prepare()
.then(createHydraClientIfNecessary)
.then(() => {
const server = express();

Expand Down
54 changes: 53 additions & 1 deletion src/serverAuth.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,56 @@ function configureAuthForServer(server) {
});
}

module.exports = { configureAuthForServer };
/**
* @summary Calls Hydra's endpoint to create an OAuth client for storefront
* if one does not already exist. This works because the Hydra admin port
* is exposed on the internal network. Ensure that it is not exposed to the
* public Internet in production.
* @returns {Promise<undefined>} Nothing
*/
async function createHydraClientIfNecessary() {
/* eslint-disable camelcase */
const bodyEncoded = JSON.stringify({
client_id: config.OAUTH2_CLIENT_ID,
client_secret: config.OAUTH2_CLIENT_SECRET,
grant_types: [
"authorization_code",
"refresh_token"
],
jwks: {},
redirect_uris: [config.OAUTH2_REDIRECT_URL],
response_types: ["token", "code"],
scope: "offline",
subject_type: "public",
token_endpoint_auth_method: "client_secret_post"
});
/* eslint-enable camelcase */

let adminUrl = config.OAUTH2_ADMIN_URL;
if (!adminUrl.endsWith("/")) adminUrl = `${adminUrl}/`;

logger.info("Creating Hydra client...");

const response = await fetch(`${adminUrl}clients`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: bodyEncoded
});

switch (response.status) {
case 200:
// intentional fallthrough!
// eslint-disable-line no-fallthrough
case 201:
logger.info("OK: Hydra client created");
break;
case 409:
logger.info("OK: Hydra client already exists");
break;
default:
logger.error(await response.text());
throw new Error(`Could not create Hydra client [${response.status}]`);
}
}

module.exports = { configureAuthForServer, createHydraClientIfNecessary };

0 comments on commit 052a330

Please sign in to comment.