diff --git a/.circleci/config.yml b/.circleci/config.yml index 86da94da..7d3b7e53 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,7 +9,7 @@ version: 2.1 orbs: node: circleci/node@5.0.2 docker: circleci/docker@2.0.3 - + jobs: checkout: docker: @@ -29,8 +29,7 @@ jobs: - AUTH0_CFG: Sample-01/src/auth_config.json - SAMPLE_PATH: Sample-01 steps: - - node/install: - install-yarn: true + - node/install - attach_workspace: at: ~/ - run: @@ -50,13 +49,13 @@ jobs: sleep 10 docker run --network host --rm appropriate/curl --retry 8 --retry-connrefused -v localhost:3000 - node/install-packages: - pkg-manager: yarn + pkg-manager: npm app-dir: Sample-01 - run: name: Run unit tests command: | cd Sample-01 - yarn test + npm test - run: name: Run integration tests command: | diff --git a/.gitignore b/.gitignore index 3697dfd2..c8fb5699 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ .DS_Store node_modules .env +.env.local **/auth0-variables.js +**/build +**/dist npm-debug.log +yarn-error.log .editorconfig diff --git a/Sample-01/.env.example b/Sample-01/.env.example new file mode 100644 index 00000000..4d93d0c8 --- /dev/null +++ b/Sample-01/.env.example @@ -0,0 +1,6 @@ +AUTH0_DOMAIN={yourDomain} +AUTH0_CLIENT_ID={yourClientId} +# AUTH0_AUDIENCE={yourApiIdentifier} + +# APP_BASE_URL=https://your-app.com +# API_BASE_URL=https://your-api-server.com \ No newline at end of file diff --git a/Sample-01/Dockerfile b/Sample-01/Dockerfile index e2f8a1ab..36cdf360 100644 --- a/Sample-01/Dockerfile +++ b/Sample-01/Dockerfile @@ -1,4 +1,4 @@ -FROM node:lts-alpine3.14 as build +FROM node:lts-alpine3.20 AS build RUN apk update && \ apk upgrade && \ @@ -10,19 +10,28 @@ WORKDIR /app COPY package.json . -RUN npm install -g --force npm@latest typescript@latest yarn@latest +RUN npm install -g --force npm@latest -RUN yarn install +RUN npm install COPY . . -RUN yarn build +ARG AUTH0_DOMAIN +ARG AUTH0_CLIENT_ID +ARG AUTH0_AUDIENCE +ARG API_BASE_URL + +RUN AUTH0_DOMAIN=${AUTH0_DOMAIN} \ + AUTH0_CLIENT_ID=${AUTH0_CLIENT_ID} \ + AUTH0_AUDIENCE=${AUTH0_AUDIENCE} \ + API_BASE_URL=${API_BASE_URL} \ + npm run build # --------------- -FROM node:lts-alpine3.14 +FROM node:lts-alpine3.20 -RUN mkdir -p /app/build +RUN mkdir -p /app/dist RUN apk update && \ apk upgrade && \ @@ -32,10 +41,9 @@ WORKDIR /app COPY --from=build /app/package.json . -RUN yarn install --production +RUN npm install --omit=dev -COPY --from=build /app/build ./build -COPY --from=build /app/src/auth_config.json ./src/auth_config.json +COPY --from=build /app/dist ./dist COPY --from=build /app/server.js . COPY --from=build /app/api-server.js . @@ -44,6 +52,6 @@ EXPOSE 3001 ENV SERVER_PORT=3000 ENV API_PORT=3001 -ENV NODE_ENV production +ENV NODE_ENV=production -CMD ["yarn", "prod"] +CMD ["npm", "run", "prod"] diff --git a/Sample-01/README.md b/Sample-01/README.md index dc0f197c..40274075 100644 --- a/Sample-01/README.md +++ b/Sample-01/README.md @@ -1,6 +1,6 @@ # Auth0 React SDK Sample Application -This sample demonstrates the integration of [Auth0 React SDK](https://github.com/auth0/auth0-react) into a React application created using [create-react-app](https://reactjs.org/docs/create-a-new-react-app.html). The sample is a companion to the [Auth0 React SDK Quickstart](https://auth0.com/docs/quickstart/spa/react). +This sample demonstrates the integration of [Auth0 React SDK](https://github.com/auth0/auth0-react) into a React application created using [Vite](https://reactjs.org/docs/create-a-new-react-app.html). The sample is a companion to the [Auth0 React SDK Quickstart](https://auth0.com/docs/quickstart/spa/react). This sample demonstrates the following use cases: @@ -12,37 +12,36 @@ This sample demonstrates the following use cases: ## Project setup -Use `yarn` to install the project dependencies: +Use `npm` to install the project dependencies: ```bash -yarn install +npm install ``` ## Configuration ### Create an API -For the ["call an API"](https://auth0.com/docs/quickstart/spa/react/02-calling-an-api) page to work, you will need to [create an API](https://auth0.com/docs/apis) using the [management dashboard](https://manage.auth0.com/#/apis). This will give you an API identifier that you can use in the `audience` configuration field below. +For the ["call an API"](https://auth0.com/docs/quickstart/spa/react/02-calling-an-api) page to work, you will need to [create an API](https://auth0.com/docs/apis) using the [management dashboard](https://manage.auth0.com/#/apis). This will give you an API identifier that you can use as the `AUTH0_AUDIENCE` environment variable below. -If you do not wish to use an API or observe the API call working, you should not specify the `audience` value in the next step. Otherwise, you will receive a "Service not found" error when trying to authenticate. +If you do not wish to use an API or observe the API call working, you should not specify the `AUTH0_AUDIENCE` environment variable in the next step. Otherwise, you will receive a "Service not found" error when trying to authenticate. ### Configure credentials The project needs to be configured with your Auth0 domain and client ID in order for the authentication flow to work. -To do this, first copy `src/auth_config.json.example` into a new file in the same folder called `src/auth_config.json`, and replace the values with your own Auth0 application credentials, and optionally the base URLs of your application and API: +To do this, first copy `.env.example` into a new file in the same folder called `.env.local`, and replace the values with your own Auth0 application credentials, and optionally the base URLs of your application and API: -```json -{ - "domain": "{YOUR AUTH0 DOMAIN}", - "clientId": "{YOUR AUTH0 CLIENT ID}", - "audience": "{YOUR AUTH0 API_IDENTIFIER}", - "appOrigin": "{OPTIONAL: THE BASE URL OF YOUR APPLICATION (default: http://localhost:3000)}", - "apiOrigin": "{OPTIONAL: THE BASE URL OF YOUR API (default: http://localhost:3001)}" -} +```bash +AUTH0_DOMAIN=your-tenant.us.auth0.com +AUTH0_CLIENT_ID=your-client-id +# AUTH0_AUDIENCE=your-api-identifier # optional, only needed for the External API feature + +# APP_BASE_URL=https://your-app.com # optional, defaults work fine for local development +# API_BASE_URL=https://your-api-server.com # optional, defaults work fine for local development ``` -**Note**: Do not specify a value for `audience` here if you do not wish to use the API part of the sample. +**Note**: Do not specify a value for `AUTH0_AUDIENCE` here if you do not wish to use the API part of the sample. ## Run the sample @@ -51,7 +50,7 @@ To do this, first copy `src/auth_config.json.example` into a new file in the sam This compiles and serves the React app and starts the backend API server on port 3001. ```bash -yarn run dev +npm run dev ``` ## Deployment @@ -59,7 +58,7 @@ yarn run dev ### Compiles and minifies for production ```bash -yarn run build +npm run build ``` ### Docker build @@ -69,7 +68,7 @@ To build and run the Docker image, run `exec.sh`, or `exec.ps1` on Windows. ### Run your tests ```bash -yarn run test +npm test ``` ## Frequently Asked Questions @@ -80,12 +79,12 @@ If you're having issues running the sample applications, including issues such a Auth0 helps you to: -* Add authentication with [multiple sources](https://auth0.com/docs/identityproviders), either social identity providers such as **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce** (amongst others), or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS, or any SAML Identity Provider**. -* Add authentication through more traditional **[username/password databases](https://auth0.com/docs/connections/database/custom-db)**. -* Add support for **[linking different user accounts](https://auth0.com/docs/users/user-account-linking)** with the same user. -* Support for generating signed [JSON Web Tokens](https://auth0.com/docs/tokens/json-web-tokens) to call your APIs and **flow the user identity** securely. -* Analytics of how, when, and where users are logging in. -* Pull data from other sources and add it to the user profile through [JavaScript rules](https://auth0.com/docs/rules). +- Add authentication with [multiple sources](https://auth0.com/docs/identityproviders), either social identity providers such as **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce** (amongst others), or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS, or any SAML Identity Provider**. +- Add authentication through more traditional **[username/password databases](https://auth0.com/docs/connections/database/custom-db)**. +- Add support for **[linking different user accounts](https://auth0.com/docs/users/user-account-linking)** with the same user. +- Support for generating signed [JSON Web Tokens](https://auth0.com/docs/tokens/json-web-tokens) to call your APIs and **flow the user identity** securely. +- Analytics of how, when, and where users are logging in. +- Pull data from other sources and add it to the user profile through [JavaScript rules](https://auth0.com/docs/rules). ## Create a Free Auth0 Account diff --git a/Sample-01/__mocks__/fileMock.js b/Sample-01/__mocks__/fileMock.js new file mode 100644 index 00000000..514c5822 --- /dev/null +++ b/Sample-01/__mocks__/fileMock.js @@ -0,0 +1,3 @@ +// Exports empty object since Jest can't interpret CSS syntax + +module.exports = {} diff --git a/Sample-01/api-server.js b/Sample-01/api-server.js index 888e3bf4..057b746c 100644 --- a/Sample-01/api-server.js +++ b/Sample-01/api-server.js @@ -1,23 +1,26 @@ +require('dotenv').config({ path: '.env.local' }) + const express = require("express"); const cors = require("cors"); const morgan = require("morgan"); const helmet = require("helmet"); const { auth } = require("express-oauth2-jwt-bearer"); -const authConfig = require("./src/auth_config.json"); const app = express(); const port = process.env.API_PORT || 3001; const appPort = process.env.SERVER_PORT || 3000; -const appOrigin = authConfig.appOrigin || `http://localhost:${appPort}`; +const appOrigin = process.env.APP_BASE_URL || `http://localhost:${appPort}`; +const domain = process.env.AUTH0_DOMAIN; +const audience = process.env.AUTH0_AUDIENCE; if ( - !authConfig.domain || - !authConfig.audience || - authConfig.audience === "{API_IDENTIFIER}" + !domain || + !audience || + audience === "{yourApiIdentifier}" ) { console.log( - "Exiting: Please make sure that auth_config.json is in place and populated with valid domain and audience values" + "Exiting API Server: Please make sure AUTH0_DOMAIN and AUTH0_AUDIENCE environment variables are set" ); process.exit(); @@ -28,8 +31,8 @@ app.use(helmet()); app.use(cors({ origin: appOrigin })); const checkJwt = auth({ - audience: authConfig.audience, - issuerBaseURL: `https://${authConfig.domain}/`, + audience, + issuerBaseURL: `https://${domain}/`, algorithms: ["RS256"], }); diff --git a/Sample-01/babel.config.js b/Sample-01/babel.config.js new file mode 100644 index 00000000..6183f4ea --- /dev/null +++ b/Sample-01/babel.config.js @@ -0,0 +1,6 @@ +module.exports = { + presets: [ + ['@babel/preset-env', { targets: { node: 'current' } }], + ['@babel/preset-react', { runtime: 'automatic' }], + ], +} diff --git a/Sample-01/exec.ps1 b/Sample-01/exec.ps1 index 988695e0..e1172f95 100644 --- a/Sample-01/exec.ps1 +++ b/Sample-01/exec.ps1 @@ -1,2 +1,19 @@ -docker build --rm -t auth0-react-01-login . -docker run --init -p 3000:3000 -p 3001:3001 -it auth0-react-01-login +if (-not (Test-Path .env.local)) { + Write-Error "Error: .env.local not found. Copy .env.example to .env.local and fill in your credentials." + exit 1 +} + +$envVars = @{} +Get-Content .env.local | Where-Object { $_ -notmatch '^#' -and $_ -notmatch '^\s*$' } | ForEach-Object { + $parts = $_ -split '=', 2 + $envVars[$parts[0].Trim()] = $parts[1].Trim() +} + +docker build ` + --build-arg "AUTH0_DOMAIN=$($envVars['AUTH0_DOMAIN'])" ` + --build-arg "AUTH0_CLIENT_ID=$($envVars['AUTH0_CLIENT_ID'])" ` + --build-arg "AUTH0_AUDIENCE=$($envVars['AUTH0_AUDIENCE'])" ` + --build-arg "API_BASE_URL=$($envVars['API_BASE_URL'])" ` + -t auth0-react-01-login . + +docker run --init -p 3000:3000 -p 3001:3001 --env-file .env.local -it auth0-react-01-login \ No newline at end of file diff --git a/Sample-01/exec.sh b/Sample-01/exec.sh old mode 100644 new mode 100755 index 34d71160..f92ee80b --- a/Sample-01/exec.sh +++ b/Sample-01/exec.sh @@ -1,3 +1,16 @@ #!/usr/bin/env bash -docker build -t auth0-react-02-calling-an-api . -docker run --init -p 3000:3000 -p 3001:3001 -it auth0-react-02-calling-an-api \ No newline at end of file +if [ ! -f .env.local ]; then + echo "Error: .env.local not found. Copy .env.example to .env.local and fill in your credentials." + exit 1 +fi + +export $(grep -v '^#' .env.local | grep -v '^$' | xargs) + +docker build \ + --build-arg AUTH0_DOMAIN="$AUTH0_DOMAIN" \ + --build-arg AUTH0_CLIENT_ID="$AUTH0_CLIENT_ID" \ + --build-arg AUTH0_AUDIENCE="$AUTH0_AUDIENCE" \ + --build-arg API_BASE_URL="$API_BASE_URL" \ + -t auth0-react-02-calling-an-api . + +docker run --init -p 3000:3000 -p 3001:3001 --env-file .env.local -it auth0-react-02-calling-an-api \ No newline at end of file diff --git a/Sample-01/public/index.html b/Sample-01/index.html similarity index 51% rename from Sample-01/public/index.html rename to Sample-01/index.html index cd627705..a2480876 100644 --- a/Sample-01/public/index.html +++ b/Sample-01/index.html @@ -2,7 +2,7 @@
- + - - - + + diff --git a/Sample-01/jest.config.js b/Sample-01/jest.config.js new file mode 100644 index 00000000..4a205816 --- /dev/null +++ b/Sample-01/jest.config.js @@ -0,0 +1,11 @@ +module.exports = { + testEnvironment: 'jsdom', + setupFilesAfterEnv: ['
You can't call the API at the moment because your application does
not have any configuration for audience, or it is
@@ -153,23 +154,22 @@ export const ExternalApiComponent = () => {
src/index.js file
+ by exposing the AUTH0_AUDIENCE environment variable to the application
auth_config.json file (see
- the auth_config.json.example file for an example of
- where it should go)
+ by setting AUTH0_AUDIENCE in your .env.local file
+ (see .env.example for reference)
- Once you have configured the value for audience,
+ Once you have configured the value for AUTH0_AUDIENCE,
please restart the app and try to use the "Ping API" button below.