diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b45a5214f5..e3491a7df1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,5 +2,5 @@ # If you need to add codeowners to the repository please add them to the CODEOWNERS file in the scripts/files directory at # https://github.com/FusionAuth/fusionauth-public-repos/ -* @fusionauth/owners @fusionauth/platform @FusionAuth/developer-relations-admins @FusionAuth/website-admins @FusionAuth/developer-relations @FusionAuth/developers @FusionAuth/customer-support +* @fusionauth/owners @fusionauth/platform @FusionAuth/developer-relations-admins @FusionAuth/website-admins @FusionAuth/developer-relations @FusionAuth/developers @FusionAuth/customer-support @FusionAuth/marketing .github/ @fusionauth/owners @fusionauth/platform @FusionAuth/website-admins diff --git a/.github/workflows/dev-astro.yml b/.github/workflows/dev-astro.yml index af3abbd023..192cb55c87 100644 --- a/.github/workflows/dev-astro.yml +++ b/.github/workflows/dev-astro.yml @@ -1,6 +1,5 @@ -# Sample workflow for building and deploying an Astro site to GitHub Pages # -# To get started with Astro see: https://docs.astro.build/en/getting-started/ +# Build the astro-based artifacts and deploy them to the dev website S3 bucket # name: Dev astro deployment env: @@ -9,11 +8,15 @@ env: AWS_REGION: "us-east-2" on: # Runs on pushes targeting the default branch - push: - branches: ["release/1.53.0"] + # push: + # branches: ["release/1.53.0"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: + inputs: + branch: + required: true + type: string permissions: id-token: write # Used to get an access token, which is then used to assume an AWS IAM role @@ -36,8 +39,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v2 + uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ env.PUBLISHER_ROLE_ARN }} role-session-name: site_publisher_session @@ -53,8 +58,4 @@ jobs: - name: CloudFront request handler and cache invalidation working-directory: . run: | - CLOUDFRONT_FUNCTION_ETAG=$(aws cloudfront describe-function --name fusionauth-website-request-handler --query 'ETag' --output text) - CLOUDFRONT_FUNCTION_ETAG=$(aws cloudfront update-function --name fusionauth-website-request-handler --function-code fileb://src/cloudfront/functions/fusionauth-website-request-handler.js --function-config Comment="Request handler for the FusionAuth website",Runtime="cloudfront-js-1.0" --if-match ${CLOUDFRONT_FUNCTION_ETAG} --query 'ETag' --output text) - aws cloudfront publish-function --name fusionauth-website-request-handler --if-match ${CLOUDFRONT_FUNCTION_ETAG} aws cloudfront create-invalidation --distribution-id ${{ secrets.DEV_DISTRIBUTION_ID }} --paths "/*" - diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml deleted file mode 100644 index 8938119639..0000000000 --- a/.github/workflows/spellcheck.yml +++ /dev/null @@ -1,30 +0,0 @@ -# This is workflow for spell checking using PySpelling lib (https://pypi.org/project/pyspelling/) -name: spellcheck_website -on: - # run 2 weekdays at ~noon MT - schedule: - - cron: '31 17 * * 2,4' - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on - runs-on: ubuntu-latest - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - - uses: actions/checkout@v4 - - name: Install astro modules - run: cd astro && npm ci - # commenting these out because for now we aren't using compress to compress images. When we go back to that, we'll need to uncomment these - #- name: Uninstall astro-compress to reduce build time , saves about 66% of time - #run: cd astro && npm uninstall astro-compress - #- name: Unconfigure compress - #run: sed '/import compress from "astro-compress";/d' astro/astro.config.mjs |sed '/compress(),/d' > tmpconfig && mv tmpconfig astro/astro.config.mjs - - name: Build astro site - run: cd astro && npm run build - # Spellcheck - - uses: igsekor/pyspelling-any@v1.0.4 - name: Spellcheck diff --git a/.github/workflows/vale.yml b/.github/workflows/vale.yml index e8bdef6667..8e66b2c156 100644 --- a/.github/workflows/vale.yml +++ b/.github/workflows/vale.yml @@ -9,5 +9,5 @@ jobs: - uses: actions/checkout@v4 - uses: errata-ai/vale-action@reviewdog with: - files: '["astro/src/content"]' - fail_on_error: false + files: '["astro/src/components","astro/src/content"]' + fail_on_error: true diff --git a/.spellcheck.yaml b/.spellcheck.yaml deleted file mode 100644 index 29163c8552..0000000000 --- a/.spellcheck.yaml +++ /dev/null @@ -1,23 +0,0 @@ -matrix: -- name: Markdown - sources: - - 'astro/dist/**/*.html|!astro/dist/blog/tag*' - default_encoding: utf-8 - spellchecker: hunspell - dictionary: - encoding: utf-8 - wordlists: - - config/vale/styles/config/vocabularies/FusionAuth/accept.txt - pipeline: - - pyspelling.filters.url: - - pyspelling.filters.html: - comments: false - attributes: - - title - - alt - ignores: - - :matches(code, pre) - - :matches(.spellcheck-ignore) - - :matches(.blog-tag) - - :matches(button[data-widget]) - - :matches(.mermaid-diagram) diff --git a/.vale.ini b/.vale.ini index 3f50db5454..d7ab007dff 100644 --- a/.vale.ini +++ b/.vale.ini @@ -11,14 +11,31 @@ astro = md BasedOnStyles = Vale, write-good BlockIgnores = ]+)?/> TokenIgnores = (?m)^import .+ from [^\n]+$, \ -(?m)^export const .+, \ +(?m)^export const.*, \ +(?m)^image: .*oauth.*, \ +(?m)^tags: .*oauth.*, \ +(?m)^tags: .*ciam.*, \ +(?m)\[[^]]*\]\(.*/apis/.*\), \ +(?m)\[[^]]*\]\(.*-apis-.*\), \ +(?m)\[[^]]*\]\(.*/oauth/.*\), \ +class="[^"]*", \ +img src=\{.*supabase.*\}, \ ]+)?>, \ , \ [^<]+<\/InlineField>, \ [^<]+<\/InlineUIElement>, \ ]+)?/>, \ ]+)?/>, \ +]+)?/>, \ +]+)?/>, \ +]+)?/>, \ ]+)?/>, \ ]+)?/>, \ ]+)?>[^<]+<\/APIField>, \ +{[^}]+}, \ +\s\s+mtls:.*, \ +```[^`]*```, \ +(+?), \ ]+)?>[^<]+<\/APIURI> + + diff --git a/DocsDevREADME.md b/DocsDevREADME.md index c2027e3323..7ef418aa4f 100644 --- a/DocsDevREADME.md +++ b/DocsDevREADME.md @@ -1,4 +1,4 @@ -## Running builds +# Running builds Almost all of the content for site now lives under the [astro](./astro) directory and is built by astro. You can run the site by cd-ing into the astro directory and running npm scripts from there or by running savant targets from the top level. The build targets are @@ -456,10 +456,11 @@ The main configuration file is located at [`.vale.ini`](./.vale.ini), where we s - Right now, we're using [`write-good`](./config/vale/styles/write-good), a collection of simple rules to avoid common mistakes and awkward sentences. - We also have a custom vocabulary at [`config/vale/styles/config/vocabularies/FusionAuth/accept.txt`](./config/vale/styles/config/vocabularies/FusionAuth/accept.txt) with known words. - Note that this file can use regular expressions to match words in a case-insensitive manner, as described [in their docs](https://vale.sh/docs/topics/vocab/). +- Anything marked as code (with backticks) is ignored, so if you have a UUID or config string, surrounding it with backticks is a good way to satisfy vale. ### GitHub Actions -There's [a GitHub Action](./.github/workflows/vale.yml) that runs Vale on added/modified files when opening a pull request. It'll only cover files located at `astro/src/content`, but it won't block merging the PR, as we currently have lots of errors to fix. So, use it as a guide to improve what you are writing. +There's [a GitHub Action](./.github/workflows/vale.yml) that runs Vale on added/modified files when opening a pull request. It'll only cover files located at `astro/src/content` and `astro/src/components`. It will block merging the PR. ### Running locally diff --git a/astro/package-lock.json b/astro/package-lock.json index 64993a3440..2bf2c6d806 100644 --- a/astro/package-lock.json +++ b/astro/package-lock.json @@ -26,6 +26,9 @@ "puppeteer": "^18.0.2", "semver": "^7.5.4", "tailwindcss": "^3.2.7" + }, + "devDependencies": { + "@vvago/vale": "^3.7.1" } }, "node_modules/@algolia/autocomplete-core": { @@ -2309,6 +2312,96 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, + "node_modules/@vvago/vale": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@vvago/vale/-/vale-3.7.1.tgz", + "integrity": "sha512-TVpUtFPilUCq2GyO3j7+fYH4Fd50RIdlFTc85daJv6JePaXlYmYsz5q020bwo395kOOGWWW61nXWmmVkCqHG9A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "axios": "^1.4.0", + "rimraf": "^5.0.0", + "tar": "^6.1.15", + "unzipper": "^0.10.14" + }, + "bin": { + "vale": "bin/vale" + } + }, + "node_modules/@vvago/vale/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vvago/vale/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vvago/vale/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/@vvago/vale/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vvago/vale/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -3003,6 +3096,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, "node_modules/autoprefixer": { "version": "10.4.17", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", @@ -3039,6 +3138,17 @@ "postcss": "^8.1.0" } }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", @@ -3085,6 +3195,28 @@ } ] }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "dev": true, + "dependencies": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3093,6 +3225,12 @@ "node": ">=8" } }, + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "dev": true + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -3215,6 +3353,24 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "node_modules/buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "dev": true, + "engines": { + "node": ">=0.2.0" + } + }, "node_modules/camel-case": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", @@ -3271,6 +3427,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "dev": true, + "dependencies": { + "traverse": ">=0.3.0 <0.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -3484,6 +3652,18 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -3524,6 +3704,12 @@ "node": ">= 0.6" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, "node_modules/cose-base": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", @@ -4098,6 +4284,15 @@ "robust-predicates": "^3.0.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -4238,6 +4433,45 @@ "node": ">=4" } }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -4589,6 +4823,26 @@ "node": ">=8" } }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -4604,6 +4858,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -4621,6 +4889,36 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4639,6 +4937,47 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/fstream/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/fstream/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -5513,6 +5852,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -5836,6 +6181,12 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "node_modules/listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", + "dev": true + }, "node_modules/lite-youtube-embed": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/lite-youtube-embed/-/lite-youtube-embed-0.2.0.tgz", @@ -7230,6 +7581,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -7252,14 +7624,66 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "engines": { "node": ">=16 || 14 >=14.17" } }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -7565,6 +7989,12 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, "node_modules/pagefind": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.1.0.tgz", @@ -7677,27 +8107,24 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/path-to-regexp": { "version": "6.2.2", @@ -7995,6 +8422,12 @@ "node": ">=6" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -8975,6 +9408,12 @@ "node": ">=10" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, "node_modules/sharp": { "version": "0.33.3", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.3.tgz", @@ -9515,6 +9954,23 @@ "node": ">=4" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -9574,6 +10030,30 @@ "ieee754": "^1.1.13" } }, + "node_modules/tar/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/terser": { "version": "5.31.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", @@ -9644,6 +10124,15 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -9920,6 +10409,54 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unzipper": { + "version": "0.10.14", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", + "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "node_modules/unzipper/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/unzipper/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/unzipper/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -11871,6 +12408,71 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, + "@vvago/vale": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@vvago/vale/-/vale-3.7.1.tgz", + "integrity": "sha512-TVpUtFPilUCq2GyO3j7+fYH4Fd50RIdlFTc85daJv6JePaXlYmYsz5q020bwo395kOOGWWW61nXWmmVkCqHG9A==", + "dev": true, + "requires": { + "axios": "^1.4.0", + "rimraf": "^5.0.0", + "tar": "^6.1.15", + "unzipper": "^0.10.14" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + } + }, + "jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "requires": { + "glob": "^10.3.7" + } + } + } + }, "acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -12293,6 +12895,12 @@ "astro-index-pages": { "version": "file:src/integrations/astro-index-pages" }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, "autoprefixer": { "version": "10.4.17", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", @@ -12306,6 +12914,17 @@ "postcss-value-parser": "^4.2.0" } }, + "axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dev": true, + "requires": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "axobject-query": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", @@ -12334,11 +12953,33 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "dev": true + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "dev": true, + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "dev": true + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -12419,6 +13060,18 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "dev": true + }, "camel-case": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", @@ -12448,6 +13101,15 @@ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==" }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "dev": true, + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -12592,6 +13254,15 @@ "simple-swizzle": "^0.2.2" } }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, "comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -12622,6 +13293,12 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, "cose-base": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", @@ -13040,6 +13717,12 @@ "robust-predicates": "^3.0.0" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true + }, "dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -13143,6 +13826,47 @@ "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==" }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -13399,6 +14123,12 @@ "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==" }, + "follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "dev": true + }, "foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -13408,6 +14138,17 @@ "signal-exit": "^4.0.1" } }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -13418,6 +14159,32 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -13429,6 +14196,38 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "optional": true }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -14037,6 +14836,12 @@ "is-inside-container": "^1.0.0" } }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -14192,6 +14997,12 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", + "dev": true + }, "lite-youtube-embed": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/lite-youtube-embed/-/lite-youtube-embed-0.2.0.tgz", @@ -15133,6 +15944,21 @@ "picomatch": "^2.3.1" } }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, "mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -15146,10 +15972,49 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true }, "mkdirp-classic": { "version": "0.5.3", @@ -15348,6 +16213,12 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, "pagefind": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.1.0.tgz", @@ -15439,18 +16310,18 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "dependencies": { "lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==" + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" } } }, @@ -15639,6 +16510,12 @@ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==" }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -16343,6 +17220,12 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==" }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, "sharp": { "version": "0.33.3", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.3.tgz", @@ -16738,6 +17621,40 @@ } } }, + "tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -16839,6 +17756,12 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "dev": true + }, "trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -17033,6 +17956,56 @@ "unist-util-is": "^6.0.0" } }, + "unzipper": { + "version": "0.10.14", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", + "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", + "dev": true, + "requires": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", diff --git a/astro/package.json b/astro/package.json index 1f13b755cb..fde6eb46a4 100644 --- a/astro/package.json +++ b/astro/package.json @@ -9,7 +9,9 @@ "dev-build": "DEV=true astro build", "postbuild": "pagefind", "preview": "astro preview", - "astro": "astro" + "astro": "astro", + "vale": "./node_modules/@vvago/vale/bin/vale", + "spellcheck": "npm run vale src/content src/components" }, "dependencies": { "@astro-community/astro-embed-youtube": "^0.4.1", @@ -30,5 +32,8 @@ "puppeteer": "^18.0.2", "semver": "^7.5.4", "tailwindcss": "^3.2.7" + }, + "devDependencies": { + "@vvago/vale": "^3.7.1" } } diff --git a/astro/public/img/articles/try-before-buy/fusionauth-free-trial.png b/astro/public/img/articles/try-before-buy/fusionauth-free-trial.png new file mode 100644 index 0000000000..c91cc030a7 Binary files /dev/null and b/astro/public/img/articles/try-before-buy/fusionauth-free-trial.png differ diff --git a/astro/public/img/blogs/2024-hacktoberfest/hacktoberfest-2024.png b/astro/public/img/blogs/2024-hacktoberfest/hacktoberfest-2024.png new file mode 100644 index 0000000000..d2ea6f64b7 Binary files /dev/null and b/astro/public/img/blogs/2024-hacktoberfest/hacktoberfest-2024.png differ diff --git a/astro/public/img/blogs/release-1-53/fusionauth-1-53-0.png b/astro/public/img/blogs/release-1-53/fusionauth-1-53-0.png new file mode 100644 index 0000000000..5fc134b9b6 Binary files /dev/null and b/astro/public/img/blogs/release-1-53/fusionauth-1-53-0.png differ diff --git a/astro/public/img/blogs/release-1-53/llama.jpg b/astro/public/img/blogs/release-1-53/llama.jpg new file mode 100644 index 0000000000..b613b3b6ea Binary files /dev/null and b/astro/public/img/blogs/release-1-53/llama.jpg differ diff --git a/astro/public/img/blogs/self-hostable-application/building-a-self-hostable-product.png b/astro/public/img/blogs/self-hostable-application/building-a-self-hostable-product.png new file mode 100644 index 0000000000..6a6f6f017a Binary files /dev/null and b/astro/public/img/blogs/self-hostable-application/building-a-self-hostable-product.png differ diff --git a/astro/public/img/blogs/self-hostable-application/control.png b/astro/public/img/blogs/self-hostable-application/control.png new file mode 100644 index 0000000000..c715c7bfef Binary files /dev/null and b/astro/public/img/blogs/self-hostable-application/control.png differ diff --git a/astro/public/img/blogs/self-hostable-application/hits-different.png b/astro/public/img/blogs/self-hostable-application/hits-different.png new file mode 100644 index 0000000000..e3218ca58c Binary files /dev/null and b/astro/public/img/blogs/self-hostable-application/hits-different.png differ diff --git a/astro/public/img/blogs/self-hostable-application/running-product.png b/astro/public/img/blogs/self-hostable-application/running-product.png new file mode 100644 index 0000000000..89c7bed222 Binary files /dev/null and b/astro/public/img/blogs/self-hostable-application/running-product.png differ diff --git a/astro/public/img/blogs/self-hostable-application/show-me-business-model.png b/astro/public/img/blogs/self-hostable-application/show-me-business-model.png new file mode 100644 index 0000000000..159f60ac8f Binary files /dev/null and b/astro/public/img/blogs/self-hostable-application/show-me-business-model.png differ diff --git a/astro/public/img/blogs/self-hostable-application/two-paths.png b/astro/public/img/blogs/self-hostable-application/two-paths.png new file mode 100644 index 0000000000..9e9198efb8 Binary files /dev/null and b/astro/public/img/blogs/self-hostable-application/two-paths.png differ diff --git a/astro/public/img/blogs/self-hostable-application/users-find-way.png b/astro/public/img/blogs/self-hostable-application/users-find-way.png new file mode 100644 index 0000000000..ca242838ee Binary files /dev/null and b/astro/public/img/blogs/self-hostable-application/users-find-way.png differ diff --git a/astro/public/img/blogs/session-management-options/session-management-options.png b/astro/public/img/blogs/session-management-options/session-management-options.png new file mode 100644 index 0000000000..3249b632c7 Binary files /dev/null and b/astro/public/img/blogs/session-management-options/session-management-options.png differ diff --git a/astro/public/img/blogs/video-auth-code-grant/1-video-auth-code-grant.png b/astro/public/img/blogs/video-auth-code-grant/1-video-auth-code-grant.png new file mode 100644 index 0000000000..36afb94814 Binary files /dev/null and b/astro/public/img/blogs/video-auth-code-grant/1-video-auth-code-grant.png differ diff --git a/astro/public/img/blogs/video-auth-code-grant/authorization-code-grant-simple.png b/astro/public/img/blogs/video-auth-code-grant/authorization-code-grant-simple.png new file mode 100644 index 0000000000..c6e75b3aff Binary files /dev/null and b/astro/public/img/blogs/video-auth-code-grant/authorization-code-grant-simple.png differ diff --git a/astro/public/img/docs/extend/events-and-webhooks/manage-webhook-event-source.png b/astro/public/img/docs/extend/events-and-webhooks/manage-webhook-event-source.png new file mode 100644 index 0000000000..db10240519 Binary files /dev/null and b/astro/public/img/docs/extend/events-and-webhooks/manage-webhook-event-source.png differ diff --git a/astro/public/img/docs/extend/events-and-webhooks/manage-webhook-event.png b/astro/public/img/docs/extend/events-and-webhooks/manage-webhook-event.png new file mode 100644 index 0000000000..dc31ad3789 Binary files /dev/null and b/astro/public/img/docs/extend/events-and-webhooks/manage-webhook-event.png differ diff --git a/astro/public/img/docs/extend/events-and-webhooks/webhook-attempt.png b/astro/public/img/docs/extend/events-and-webhooks/webhook-attempt.png new file mode 100644 index 0000000000..5bbbbba7f6 Binary files /dev/null and b/astro/public/img/docs/extend/events-and-webhooks/webhook-attempt.png differ diff --git a/astro/public/img/docs/extend/events-and-webhooks/webhook-event-log-list.png b/astro/public/img/docs/extend/events-and-webhooks/webhook-event-log-list.png new file mode 100644 index 0000000000..57de656d2f Binary files /dev/null and b/astro/public/img/docs/extend/events-and-webhooks/webhook-event-log-list.png differ diff --git a/astro/public/img/docs/extend/events-and-webhooks/webhook-event-log-settings.png b/astro/public/img/docs/extend/events-and-webhooks/webhook-event-log-settings.png new file mode 100644 index 0000000000..ea62d8e048 Binary files /dev/null and b/astro/public/img/docs/extend/events-and-webhooks/webhook-event-log-settings.png differ diff --git a/astro/public/img/docs/get-started/core-concepts/tenant-configuration-extId-durations.png b/astro/public/img/docs/get-started/core-concepts/tenant-configuration-extId-durations.png index 2ca161aecf..b01bfb5fa6 100644 Binary files a/astro/public/img/docs/get-started/core-concepts/tenant-configuration-extId-durations.png and b/astro/public/img/docs/get-started/core-concepts/tenant-configuration-extId-durations.png differ diff --git a/astro/public/img/docs/get-started/download-and-install/n-servers-external-db.png b/astro/public/img/docs/get-started/download-and-install/n-servers-external-db.png old mode 100755 new mode 100644 index 77dcc472b6..c2763a323c Binary files a/astro/public/img/docs/get-started/download-and-install/n-servers-external-db.png and b/astro/public/img/docs/get-started/download-and-install/n-servers-external-db.png differ diff --git a/astro/public/img/docs/get-started/download-and-install/single-server.png b/astro/public/img/docs/get-started/download-and-install/single-server.png old mode 100755 new mode 100644 index e54abd3ffc..7cbaed19cb Binary files a/astro/public/img/docs/get-started/download-and-install/single-server.png and b/astro/public/img/docs/get-started/download-and-install/single-server.png differ diff --git a/astro/public/img/docs/get-started/download-and-install/two-servers-external-db.png b/astro/public/img/docs/get-started/download-and-install/two-servers-external-db.png old mode 100755 new mode 100644 index 1426f61af1..1fbcbf90f7 Binary files a/astro/public/img/docs/get-started/download-and-install/two-servers-external-db.png and b/astro/public/img/docs/get-started/download-and-install/two-servers-external-db.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/offboard/databaseDiagram.erd b/astro/public/img/docs/lifecycle/migrate-users/offboard/databaseDiagram.erd new file mode 100644 index 0000000000..029a2c4b54 --- /dev/null +++ b/astro/public/img/docs/lifecycle/migrate-users/offboard/databaseDiagram.erd @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/astro/public/img/docs/lifecycle/migrate-users/offboard/databaseDiagram.svg b/astro/public/img/docs/lifecycle/migrate-users/offboard/databaseDiagram.svg new file mode 100644 index 0000000000..27399f84eb --- /dev/null +++ b/astro/public/img/docs/lifecycle/migrate-users/offboard/databaseDiagram.svg @@ -0,0 +1 @@ +application_rolesid: uuidapplications_id: uuiddescription: varchar(255)insert_instant: int8is_default: boolis_super_role: boollast_update_instant: int8name: varchar(191) applicationsid: uuidaccess_token_populate_lambdas_id: uuidaccess_token_signing_keys_id: uuidactive: booladmin_registration_forms_id: uuiddata: textemail_update_email_templates_id: uuidemail_verification_email_templates_id: uuidemail_verified_email_templates_id: uuidforgot_password_email_templates_id: uuidforms_id: uuidid_token_populate_lambdas_id: uuidid_token_signing_keys_id: uuidinsert_instant: int8last_update_instant: int8login_id_in_use_on_create_email_templates_id: uuidlogin_id_in_use_on_update_email_templates_id: uuidlogin_new_device_email_templates_id: uuidlogin_suspicious_email_templates_id: uuidmulti_factor_email_message_templates_id: uuidmulti_factor_sms_message_templates_id: uuidname: varchar(191)passwordless_email_templates_id: uuidpassword_update_email_templates_id: uuidpassword_reset_success_email_templates_id: uuidsamlv2_default_verification_keys_id: uuidsamlv2_issuer: varchar(191)samlv2_keys_id: uuidsamlv2_logout_keys_id: uuidsamlv2_logout_default_verification_keys_id: uuidsamlv2_populate_lambdas_id: uuidsamlv2_single_logout_keys_id: uuidself_service_registration_validation_lambdas_id: uuidself_service_user_forms_id: uuidset_password_email_templates_id: uuidtenants_id: uuidthemes_id: uuidtwo_factor_method_add_email_templates_id: uuidtwo_factor_method_remove_email_templates_id: uuidui_ip_access_control_lists_id: uuiduserinfo_populate_lambdas_id: uuidverification_email_templates_id: uuid consentsid: uuidconsent_email_templates_id: uuiddata: textinsert_instant: int8last_update_instant: int8name: varchar(191)email_plus_email_templates_id: uuid email_templatesid: uuiddefault_from_name: varchar(255)default_html_template: textdefault_subject: varchar(255)default_text_template: textfrom_email: varchar(255)insert_instant: int8last_update_instant: int8localized_from_names: textlocalized_html_templates: textlocalized_subjects: textlocalized_text_templates: textname: varchar(191) group_application_rolesapplication_roles_id: uuidgroups_id: uuid group_membersid: uuidgroups_id: uuiddata: textinsert_instant: int8users_id: uuid groupsid: uuiddata: textinsert_instant: int8last_update_instant: int8name: varchar(191)tenants_id: uuid identitiesid: bigserialbreached_password_last_checked_instant: int8breached_password_status: int2connectors_id: uuidemail: varchar(191)encryption_scheme: varchar(255)factor: int4insert_instant: int8last_login_instant: int8last_update_instant: int8password: varchar(255)password_change_reason: int2password_change_required: boolpassword_last_update_instant: int8salt: varchar(255)status: int2tenants_id: uuidusername: varchar(191)username_index: varchar(191)username_status: int2users_id: uuidverified: boolverified_instant: int8 identity_provider_linksdata: textidentity_providers_id: uuididentity_providers_user_id: varchar(191)insert_instant: int8last_login_instant: int8tenants_id: uuidusers_id: uuid identity_providersid: uuiddata: textenabled: boolinsert_instant: int8last_update_instant: int8name: varchar(191)type: varchar(255)keys_id: uuidrequest_signing_keys_id: uuidreconcile_lambdas_id: uuid identity_providers_applicationsapplications_id: uuiddata: textenabled: boolidentity_providers_id: uuidkeys_id: uuid identity_providers_tenantstenants_id: uuiddata: textidentity_providers_id: uuid tenantsid: uuidaccess_token_signing_keys_id: uuidadmin_user_forms_id: uuidclient_credentials_access_token_populate_lambdas_id: uuidconfirm_child_email_templates_id: uuiddata: textemail_update_email_templates_id: uuidemail_verified_email_templates_id: uuidfailed_authentication_user_actions_id: uuidfamily_request_email_templates_id: uuidforgot_password_email_templates_id: uuidid_token_signing_keys_id: uuidinsert_instant: int8last_update_instant: int8login_id_in_use_on_create_email_templates_id: uuidlogin_id_in_use_on_update_email_templates_id: uuidlogin_new_device_email_templates_id: uuidlogin_suspicious_email_templates_id: uuidmulti_factor_email_message_templates_id: uuidmulti_factor_sms_message_templates_id: uuidmulti_factor_sms_messengers_id: uuidname: varchar(191)password_reset_success_email_templates_id: uuidpassword_update_email_templates_id: uuidparent_registration_email_templates_id: uuidpasswordless_email_templates_id: uuidscim_client_entity_types_id: uuidscim_enterprise_user_request_converter_lambdas_id: uuidscim_enterprise_user_response_converter_lambdas_id: uuidscim_group_request_converter_lambdas_id: uuidscim_group_response_converter_lambdas_id: uuidscim_server_entity_types_id: uuidscim_user_request_converter_lambdas_id: uuidscim_user_response_converter_lambdas_id: uuidset_password_email_templates_id: uuidthemes_id: uuidtwo_factor_method_add_email_templates_id: uuidtwo_factor_method_remove_email_templates_id: uuidui_ip_access_control_lists_id: uuidverification_email_templates_id: uuid user_commentsid: uuidcomment: textcommenter_id: uuidinsert_instant: int8users_id: uuid user_consentsid: uuidconsents_id: uuiddata: textgiver_users_id: uuidinsert_instant: int8last_update_instant: int8users_id: uuid user_consents_email_plusid: bigserialnext_email_instant: int8user_consents_id: uuid user_registrationsid: uuidapplications_id: uuidauthentication_token: varchar(255)clean_speak_id: uuiddata: textinsert_instant: int8last_login_instant: int8last_update_instant: int8timezone: varchar(255)username: varchar(191)username_status: int2users_id: uuidverified: boolverified_instant: int8 user_registrations_application_rolesapplication_roles_id: uuiduser_registrations_id: uuid usersid: uuidactive: boolbirth_date: bpchar(10)clean_speak_id: uuiddata: textexpiry: int8first_name: varchar(255)full_name: varchar(255)image_url: textinsert_instant: int8last_name: varchar(255)last_update_instant: int8middle_name: varchar(255)mobile_phone: varchar(255)parent_email: varchar(255)tenants_id: uuidtimezone: varchar(255) \ No newline at end of file diff --git a/astro/public/img/docs/lifecycle/migrate-users/offboard/offboardDBeaver.png b/astro/public/img/docs/lifecycle/migrate-users/offboard/offboardDBeaver.png new file mode 100644 index 0000000000..f98af36e39 Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/offboard/offboardDBeaver.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/generic/authorised-redirect.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/generic/authorised-redirect.png new file mode 100644 index 0000000000..2aa2e92ecb Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/generic/authorised-redirect.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/generic/find-login-url.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/generic/find-login-url.png new file mode 100644 index 0000000000..fbf6158293 Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/generic/find-login-url.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/generic/list-users.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/generic/list-users.png new file mode 100644 index 0000000000..6dc6a782e3 Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/generic/list-users.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/slack/running-fusionauth-in-docker.png b/astro/public/img/docs/operate/secure-and-monitor/slack/running-fusionauth-in-docker.png new file mode 100644 index 0000000000..afe5ee6eac Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/slack/running-fusionauth-in-docker.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/slack/tiny-service-monitor-fusionauth.png b/astro/public/img/docs/operate/secure-and-monitor/slack/tiny-service-monitor-fusionauth.png new file mode 100644 index 0000000000..3297437175 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/slack/tiny-service-monitor-fusionauth.png differ diff --git a/astro/public/img/guides/organizations/account-select.png b/astro/public/img/guides/organizations/account-select.png index 30c9b8711b..2cadd01d9c 100644 Binary files a/astro/public/img/guides/organizations/account-select.png and b/astro/public/img/guides/organizations/account-select.png differ diff --git a/astro/public/img/guides/organizations/entity-type.png b/astro/public/img/guides/organizations/entity-type.png index 8a50bf087b..e7ebc7c5f0 100644 Binary files a/astro/public/img/guides/organizations/entity-type.png and b/astro/public/img/guides/organizations/entity-type.png differ diff --git a/astro/public/sitemap.xml b/astro/public/sitemap.xml index ba30bc5edb..67bb8e4667 100644 --- a/astro/public/sitemap.xml +++ b/astro/public/sitemap.xml @@ -124,7 +124,7 @@ https://fusionauth.io/glossary/multi-factor-authentication - https://fusionauth.io/security-data-compliance + https://fusionauth.io/security https://fusionauth.io/customers-partners @@ -200,6 +200,9 @@ https://fusionauth.io/guides/keycloak-alternatives + + + https://fusionauth.io/guides/stytch-alternatives https://fusionauth.io/guides/what-is-a-passkey diff --git a/astro/src/components/GitHubEdit.astro b/astro/src/components/GitHubEdit.astro index 2b84e4ee27..b12dd18779 100644 --- a/astro/src/components/GitHubEdit.astro +++ b/astro/src/components/GitHubEdit.astro @@ -54,7 +54,7 @@ export function getGithubEditUrl(Astro: Readonly) { target="_blank" class="block border-l border-transparent pl-4 text-slate-700 text-sm -ml-px dark:text-slate-400 dark:hover:border-slate-400 dark:group-[.active]:border-indigo-400 dark:group-[.active]:text-indigo-400 group-[.active]:border-indigo-600 group-[.active]:font-semibold group-[.active]:text-indigo-600 hover:border-slate-900/50" > - Edit on Github + Edit on GitHub diff --git a/astro/src/components/Head.astro b/astro/src/components/Head.astro index ee821c01f0..ce23bf908b 100644 --- a/astro/src/components/Head.astro +++ b/astro/src/components/Head.astro @@ -21,11 +21,20 @@ if (!canonical) { } else if (!canonical.startsWith('http')) { canonical = new URL(canonical, Astro.url).href; } + +if (canonical.endsWith('index.html')) { + canonical = canonical.slice(0, canonical.indexOf('index.html')); + if (!canonical.endsWith('/')) { + canonical += '/'; + } +} else if (canonical.endsWith('.html')) { + canonical = canonical.slice(0, canonical.indexOf('.html')); +} --- - + {/* TODO: Implement favicons by following this blog post https://dev.to/masakudamatsu/favicon-nightmare-how-to-maintain-sanity-3al7 */} { canonical && } diff --git a/astro/src/components/api/AvailableSince.astro b/astro/src/components/api/AvailableSince.astro index 0804c9574d..755f36d4da 100644 --- a/astro/src/components/api/AvailableSince.astro +++ b/astro/src/components/api/AvailableSince.astro @@ -1,12 +1,11 @@ --- interface Props { - since: string; + since: string } const { since }: Props = Astro.props; - if (!since) { throw new Error("No since field"); } --- -Available since {since} +Available since {since} diff --git a/astro/src/components/api/BeforeVersion.astro b/astro/src/components/api/BeforeVersion.astro new file mode 100644 index 0000000000..1e31352d58 --- /dev/null +++ b/astro/src/components/api/BeforeVersion.astro @@ -0,0 +1,18 @@ +--- +interface Props { + version: string; +} + +const { version }: Props = Astro.props; +if (!version) { + throw new Error("No version field"); +} +const hasContent = Astro.slots.has("default"); +--- +{ version && Before version {version} + + {hasContent && +
+ } +
+} diff --git a/astro/src/components/api/DeprecatedSince.astro b/astro/src/components/api/DeprecatedSince.astro index e517a295e6..d0d0018699 100644 --- a/astro/src/components/api/DeprecatedSince.astro +++ b/astro/src/components/api/DeprecatedSince.astro @@ -1,8 +1,15 @@ --- interface Props { - since: string; + since: string } const { since }: Props = Astro.props; +const hasContent = Astro.slots.has("default"); --- -{ since && Deprecated since {since} } +{ since && Deprecated since {since} + + {hasContent && +
+ } +
+} diff --git a/astro/src/components/api/RemovedSince.astro b/astro/src/components/api/RemovedSince.astro index 1ac1255e28..13a1d3d621 100644 --- a/astro/src/components/api/RemovedSince.astro +++ b/astro/src/components/api/RemovedSince.astro @@ -1,8 +1,15 @@ --- interface Props { - since: string; + since: string } const { since }: Props = Astro.props; +const hasContent = Astro.slots.has("default"); --- -{ since && Removed in {since} } +{ since && Removed in {since} + +{hasContent && +
+} +
+} diff --git a/astro/src/components/docs/operate/secure-and-monitor/slackDiagram1.astro b/astro/src/components/docs/operate/secure-and-monitor/slackDiagram1.astro deleted file mode 100644 index 5398d39d02..0000000000 --- a/astro/src/components/docs/operate/secure-and-monitor/slackDiagram1.astro +++ /dev/null @@ -1,34 +0,0 @@ ---- -import Diagram from 'src/components/mermaid/FlowchartDiagram.astro'; - -const { alt } = Astro.props; - -//language=Mermaid -const code = ` -graph LR - subgraph I[Your server] - direction TB - subgraph G[Docker] - H[(PostgreSQL)] - end - subgraph C[Docker] - A(FusionAuth) - end - subgraph E[Docker] - F(Your app) - end - end - D(User) - D --> F - D --> A - C --> G - F --> A - style I fill:#999 -`; ---- - - \ No newline at end of file diff --git a/astro/src/components/docs/operate/secure-and-monitor/slackDiagram2.astro b/astro/src/components/docs/operate/secure-and-monitor/slackDiagram2.astro deleted file mode 100644 index 87fa22f8e6..0000000000 --- a/astro/src/components/docs/operate/secure-and-monitor/slackDiagram2.astro +++ /dev/null @@ -1,43 +0,0 @@ ---- -import Diagram from 'src/components/mermaid/FlowchartDiagram.astro'; - -const { alt } = Astro.props; - -//language=Mermaid -const code = ` -graph LR - X(Slack) - subgraph I[Your server] - subgraph G[Docker] - H[(PostgreSQL)] - end - subgraph C[Docker] - A(FusionAuth) - end - subgraph E[Docker] - B(Custom monitoring service) - end - subgraph J[Docker] - F(Your app) - end - end - D(User) - K(Administrator) - D --> F - D --> A - C --> G - F --> A - B --> |API call| C - B --> |API call| X - K --> X - style I fill:#999 - style E fill:#944 - style X fill:#944 -`; ---- - - \ No newline at end of file diff --git a/astro/src/components/docs/release-notes/ReleaseNoteIssueResolvedVia.astro b/astro/src/components/docs/release-notes/ReleaseNoteIssueResolvedVia.astro new file mode 100644 index 0000000000..2cd051716e --- /dev/null +++ b/astro/src/components/docs/release-notes/ReleaseNoteIssueResolvedVia.astro @@ -0,0 +1,16 @@ +--- +export interface Props { + resolvedIn: string; + viaIssue: string; +} + +const { resolvedIn, viaIssue } = Astro.props as Props; +--- + + + + diff --git a/astro/src/components/docs/release-notes/ReleaseNotesIssue.astro b/astro/src/components/docs/release-notes/ReleaseNotesIssue.astro new file mode 100644 index 0000000000..5698989a3d --- /dev/null +++ b/astro/src/components/docs/release-notes/ReleaseNotesIssue.astro @@ -0,0 +1,15 @@ +--- +export interface Props { + issue: string; +} + +const { issue } = Astro.props as Props; +--- + + + + diff --git a/astro/src/components/nav/BlogNav.astro b/astro/src/components/nav/BlogNav.astro index 0ab0023902..4c202b27c0 100644 --- a/astro/src/components/nav/BlogNav.astro +++ b/astro/src/components/nav/BlogNav.astro @@ -9,7 +9,6 @@ const categoryItems = [ {name: 'Community', href: '/blog/category/community/'}, {name: 'Education', href: '/blog/category/education/'}, {name: 'News', href: '/blog/category/news/'}, - {name: 'Tech Docs', href: '/docs/v1/tech/'}, ]; const moreItems = [ diff --git a/astro/src/content/articles/authentication/login-failures.md b/astro/src/content/articles/authentication/login-failures.md index fdeadf9e82..073cb42528 100644 --- a/astro/src/content/articles/authentication/login-failures.md +++ b/astro/src/content/articles/authentication/login-failures.md @@ -124,7 +124,7 @@ All things in software (and life) have tradeoffs, and tracking login failures i Once you implement tracking, you may determine that you want to do something to improve your login failure rates. Here are some ideas for how to increase successful logins. -1. **Provide automated help to anyone struggling to log in.** Present tailored advice or reminders in the user experience based on the problem they’re experiencing. An example of this is offering to send a password reset email with one click after a certain number of failed login attempts. Or, if you’re noticing that legitimate-looking users are failing at the captcha step frequently, consider a [CAPTCHA alternative](https://www.w3.org/WAI/GL/wiki/Captcha_Alternatives_and_thoughts). +1. **Provide automated help to anyone struggling to log in.** Present tailored advice or reminders in the user experience based on the problem they’re experiencing. An example of this is offering to send a password reset email with one click after a certain number of failed login attempts. Or, if you’re noticing that legitimate-looking users are failing at the CAPTCHA step frequently, consider a [CAPTCHA alternative](https://www.w3.org/WAI/GL/wiki/Captcha_Alternatives_and_thoughts). 2. **Give secure options for account credentials reset.** Once a problem has been detected, offer a login with a security code. Once the user is authenticated, allow them to modify their credentials so that they can remember them. For an added layer of security, send the user an email any time their username or password changes. In case it wasn’t them, they can be alerted of a possible malicious actor and take further steps such as changing their credentials or locking their account. diff --git a/astro/src/content/articles/authentication/mfa-compliance-fusionauth.mdx b/astro/src/content/articles/authentication/mfa-compliance-fusionauth.mdx index 56e3520399..738a5e6e5d 100644 --- a/astro/src/content/articles/authentication/mfa-compliance-fusionauth.mdx +++ b/astro/src/content/articles/authentication/mfa-compliance-fusionauth.mdx @@ -7,7 +7,7 @@ tags: mfa compliance icon: /img/icons/compliance.svg darkIcon: /img/icons/compliance-dark.svg --- -[Multifactor authentication](/articles/authentication/multi-factor-authentication), or MFA, is an approach to application security that requires a user to present two or more credentials ("factors") to log in to an application. Factors are normally selected from different categories: +[Multi-factor authentication](/articles/authentication/multi-factor-authentication), or MFA, is an approach to application security that requires a user to present two or more credentials ("factors") to log in to an application. Factors are normally selected from different categories: - Something the user knows (PIN or password) diff --git a/astro/src/content/articles/authentication/multi-factor-authentication.md b/astro/src/content/articles/authentication/multi-factor-authentication.md index 9dce5b73aa..ccae9b7441 100644 --- a/astro/src/content/articles/authentication/multi-factor-authentication.md +++ b/astro/src/content/articles/authentication/multi-factor-authentication.md @@ -276,7 +276,7 @@ As a developer, avoid this factor. If you must implement it, let the user provid Like all factors, you could use this option as part of defense in depth solution, in combination with other factors. -Counsel your users to answer these questions wisely. Frankly, they should pick fake answers. For example, if a question is "what was your first pet's name", and their first pet's name was Fluffy, pick anything other than "Fluffy". Anything. Perhaps "fido" or "killer". +Counsel your users to answer these questions wisely. Frankly, they should pick fake answers. For example, if a question is "what was your first pet's name", and their first pet's name was Fluffy, pick anything other than "Fluffy". Anything. Perhaps "spot" or "killer". If the user is saving these answers in a password manager, I would even suggest "h941TphXOL3h0ws7M0U2" or "relevance-middle-yellow-horoscope". The goal is to prevent someone from learning the name of a childhood pet from a Facebook post and using that information to gain illicit access. diff --git a/astro/src/content/articles/authentication/user-experience-ux-mfa.mdx b/astro/src/content/articles/authentication/user-experience-ux-mfa.mdx index 32f893aa77..74bfc85c36 100644 --- a/astro/src/content/articles/authentication/user-experience-ux-mfa.mdx +++ b/astro/src/content/articles/authentication/user-experience-ux-mfa.mdx @@ -12,7 +12,7 @@ Saying *[cyberattacks](https://www.ibm.com/topics/cyber-attack) are becoming inc Even though the days are gone when a somewhat decent password would thwart [unauthorized access](/blog/breached-password-detection), end users still struggle with creating strong passwords---despite the extensive security training many organizations conduct for employees. Many users continue to fall for ploys to get their passwords, like [phishing attacks](/articles/authentication/why-passwordless-authentication-matters), resulting in [significant financial losses](https://www.upguard.com/blog/cost-of-data-breach) for companies. -[Multifactor authentication](/glossary/multi-factor-authentication), or MFA, allows you to protect your users from the security issues that plague passwords. Instead of focusing so much on [strong passwords](https://support.microsoft.com/en-us/windows/create-and-use-strong-passwords-c5cebb49-8c53-4f5e-2bc4-fe357ca048eb) and keeping those passwords safe, MFA adds an extra layer of authentication to the login process. This means that even if users' passwords are intercepted, MFA can prevent most cases of unauthorized access. +[Multi-factor authentication](/glossary/multi-factor-authentication), or MFA, allows you to protect your users from the security issues that plague passwords. Instead of focusing so much on [strong passwords](https://support.microsoft.com/en-us/windows/create-and-use-strong-passwords-c5cebb49-8c53-4f5e-2bc4-fe357ca048eb) and keeping those passwords safe, MFA adds an extra layer of authentication to the login process. This means that even if users' passwords are intercepted, MFA can prevent most cases of unauthorized access. The only downside is that MFA introduces an additional step in the login process, which raises concerns about user experience (UX). diff --git a/astro/src/content/articles/authentication/webauthn.mdx b/astro/src/content/articles/authentication/webauthn.mdx index 18de891db1..20694de763 100644 --- a/astro/src/content/articles/authentication/webauthn.mdx +++ b/astro/src/content/articles/authentication/webauthn.mdx @@ -50,9 +50,9 @@ You may have guided many a user through the ritual of password resets, only to w You've witnessed family members enter their Google account password on a phishing site that has the logos of four different tech companies in stretched aspect ratios and a big green padlock. -### Multifactor Authentication +### Multi-factor Authentication -While [Multifactor Authentication](/articles/authentication/multi-factor-authentication) (MFA) has put up a good fight, patching some holes in the password paradigm, it's often the last pick during the cybersecurity kickball game. It is an absolute chore. Users dread that extra step almost as much as changing passwords, leaving MFA adoption to be driven more by mandate than by choice. When left to their own devices (ugh) users typically won't bother with MFA, even though it can be the one thing standing between them and someone taking over their Gmail to buy high-end umbrellas in London using someone else's stolen credit card. Yes, this is a real example. +While [Multi-factor Authentication](/articles/authentication/multi-factor-authentication) (MFA) has put up a good fight, patching some holes in the password paradigm, it's often the last pick during the cybersecurity kickball game. It is an absolute chore. Users dread that extra step almost as much as changing passwords, leaving MFA adoption to be driven more by mandate than by choice. When left to their own devices (ugh) users typically won't bother with MFA, even though it can be the one thing standing between them and someone taking over their Gmail to buy high-end umbrellas in London using someone else's stolen credit card. Yes, this is a real example. ### The digital threat landscape diff --git a/astro/src/content/articles/authentication/why-passwordless-authentication-matters.md b/astro/src/content/articles/authentication/why-passwordless-authentication-matters.md index f49a29c2e7..ceaa1354d7 100644 --- a/astro/src/content/articles/authentication/why-passwordless-authentication-matters.md +++ b/astro/src/content/articles/authentication/why-passwordless-authentication-matters.md @@ -19,7 +19,7 @@ At its core, WebAuthn is an API that builds upon the [FIDO2 specification](/blog The importance of moving towards passwordless authentication cannot be stressed enough. It eliminates the inherent risks associated with the username and password combinations we're accustomed to using today. One of the largest advantages of a passwordless internet is the eradication of the common practice of reusing passwords. -WebAuthn isn't just an innovation. It acts as a wall of protection against one of the most pervasive and damaging forms of cyber-attacks—phishing. Phishing attacks are notorious for [exploiting human error](/articles/security/steps-secure-your-authentication-system), relying on deception to harvest login credentials. But WebAuthn flips the script. It safeguards against phishing by using asymmetric cryptography and eliminating passwords. Even if someone tricks you into revealing your authentication data, you're still protected because you can't share the key on your device. It also protects against phishing because the prompt to authenticate is tied to the domain of the website, so users are not vulnerable to [unicode domain attacks](https://www.thesslstore.com/blog/unicode-domain-phishing/). +WebAuthn isn't just an innovation. It acts as a wall of protection against one of the most pervasive and damaging forms of cyber-attacks—phishing. Phishing attacks are notorious for [exploiting human error](/articles/security/steps-secure-your-authentication-system), relying on deception to harvest login credentials. But WebAuthn flips the script. It safeguards against phishing by using asymmetric cryptography and eliminating passwords. Even if someone tricks you into revealing your authentication data, you're still protected because you can't share the key on your device. It also protects against phishing because the prompt to authenticate is tied to the domain of the website, so users are not vulnerable to [Unicode domain attacks](https://www.thesslstore.com/blog/unicode-domain-phishing/). ## WebAuthn Key Components diff --git a/astro/src/content/articles/gaming-entertainment/cross-platform-game-accounts.md b/astro/src/content/articles/gaming-entertainment/cross-platform-game-accounts.md index 4845ca767e..03ba03f320 100644 --- a/astro/src/content/articles/gaming-entertainment/cross-platform-game-accounts.md +++ b/astro/src/content/articles/gaming-entertainment/cross-platform-game-accounts.md @@ -146,7 +146,7 @@ You need to enter the following: Click "Submit". -> If you do encounter the error ***Exception in thread main java.lang.NoClassDefFoundError: com/inversoft/mysql/MySQLHelper***, make sure you've [installed the MySQL driver](/docs/get-started/download-and-install/database#install-mysql-connector). +> If you do encounter the error `Exception in thread main java.lang.NoClassDefFoundError: com/inversoft/mysql/MySQLHelper`, make sure you've [installed the MySQL driver](/docs/get-started/download-and-install/database#install-mysql-connector). ### Complete the Setup Wizard diff --git a/astro/src/content/articles/identity-basics/passwordless-regulatory-compliance.mdx b/astro/src/content/articles/identity-basics/passwordless-regulatory-compliance.mdx index dcf76a8cc9..31ad39f7ce 100644 --- a/astro/src/content/articles/identity-basics/passwordless-regulatory-compliance.mdx +++ b/astro/src/content/articles/identity-basics/passwordless-regulatory-compliance.mdx @@ -89,9 +89,7 @@ More importantly, mobile-based authentication methods are at the forefront of ac If passwordless authentication still seems like a risky innovation, consider that major tech players, like Microsoft, have recognized the importance of investing in alternative authentication methods that improve on password-based ones. Microsoft's [endorsement and integration](https://www.microsoft.com/en-us/security/business/solutions/passwordless-authentication) of passwordless authentication signal a possible shift for other organizations to do likewise, enhancing the likelihood that passwordless authentication will achieve compliance. -Other tech giants ha - -ve also made significant contributions to include passwordless in the regulatory compliance space. Google and Apple have incorporated biometric authentication into their ecosystems and are experimenting with more [passwordless features](https://blog.google/technology/safety-security/the-beginning-of-the-end-of-the-password/). +Other tech giants have also made significant contributions to include passwordless in the regulatory compliance space. Google and Apple have incorporated biometric authentication into their ecosystems and are experimenting with more [passwordless features](https://blog.google/technology/safety-security/the-beginning-of-the-end-of-the-password/). The collective efforts of these industry leaders indicate a shift towards a future where compliance and user-friendly authentication can coexist. diff --git a/astro/src/content/articles/identity-basics/registration-best-practices.md b/astro/src/content/articles/identity-basics/registration-best-practices.md index ebfec29e1c..506c40263e 100644 --- a/astro/src/content/articles/identity-basics/registration-best-practices.md +++ b/astro/src/content/articles/identity-basics/registration-best-practices.md @@ -69,7 +69,7 @@ If a form field is optional, clearly mark it so. Even better, don't ask for opti Provide clear error messages when data fails to validate. Use both client side validation, which is faster, and server side validation, which is tamper proof. On the topic of tampering, ensure any form is submitted over TLS. You want to keep submitted information confidential and secure. -Make use of the full suite of HTML elements. Dropdowns and radio buttons are powerful, but number and email input fields leverage browsers' built-in validation and should be used as well. If you aren't sure what's supported, use tools like [caniuse.com](https://caniuse.com/) to verify compatibility. +Make use of the full suite of HTML elements. Dropdowns and radio buttons are powerful, but number and email input fields leverage browsers' built-in validation and should be used as well. If you aren't sure what's supported, use tools like [Caniuse](https://caniuse.com/) to verify compatibility. ### Registration forms are unique diff --git a/astro/src/content/articles/identity-basics/try-before-you-buy.md b/astro/src/content/articles/identity-basics/try-before-you-buy.md index e2b043a280..776531f71d 100644 --- a/astro/src/content/articles/identity-basics/try-before-you-buy.md +++ b/astro/src/content/articles/identity-basics/try-before-you-buy.md @@ -54,7 +54,7 @@ Developers can be a particularly stubborn group when it comes to efforts like th And if the development team is split as to which solution they think is best, a free trial like this can help opinions converge around the best solution in practice, rather than wasting time on arguments of opinion. One common attempt to resolve a split between solutions is to just have more demo meetings from vendors and opinion-charged internal meetings. This often leads to frustration and the vendor selection process stalling out all together. As an alternative, consider dividing the development team based on who backs which solution and having each side develop a small prototype to demo to the team. This will quickly bring to light any challenges with one solution or the other and allow for much more productive conversations after the trial is over. - +[![FusionAuth free trial](/img/articles/try-before-buy/fusionauth-free-trial.png)](/download) ## How To Effectively Trial Software It's not enough to simply have a free trial of a potential authentication solution. For your trial to be useful, you need to run it effectively in order to be sure that you've tested for all of your potential use cases and gotten all the information you need to make a more informed decision. diff --git a/astro/src/content/articles/identity-basics/what-is-oidc.mdx b/astro/src/content/articles/identity-basics/what-is-oidc.mdx index 163224c6f1..bbfded907c 100644 --- a/astro/src/content/articles/identity-basics/what-is-oidc.mdx +++ b/astro/src/content/articles/identity-basics/what-is-oidc.mdx @@ -124,7 +124,7 @@ There are also user profile claims. Here's an incomplete list: * `phone_number`, the user's preferred telephone number. * `updated_at`, the time the user's information was last updated. -All times are numbers representing the number of seconds since the unix epoch. The `iss`, `sub`, `aud`, `exp`, and `iat` claims are required and will be present in every Id token. Every other claim is optional, though some are required if the RP requests them or the OP is configured in certain ways. +All times are numbers representing the number of seconds since the UNIX epoch. The `iss`, `sub`, `aud`, `exp`, and `iat` claims are required and will be present in every Id token. Every other claim is optional, though some are required if the RP requests them or the OP is configured in certain ways. You can see that an RP can get a decent amount of information about a user and the authentication from the OP. It's all transmitted in the Id token, which must be validated to ensure that there's no funny business going on. diff --git a/astro/src/content/articles/login-authentication-workflows/authentication-workflows-overview.md b/astro/src/content/articles/login-authentication-workflows/authentication-workflows-overview.md index 8bcf9050fb..887e77a2c2 100644 --- a/astro/src/content/articles/login-authentication-workflows/authentication-workflows-overview.md +++ b/astro/src/content/articles/login-authentication-workflows/authentication-workflows-overview.md @@ -52,4 +52,4 @@ Native mobile applications are usually installed via a store and installed on th Native applications often call APIs to handle user interactions and input. For example, if a user clicks a button or submits a form, the application might call an API on the server. This API might be called via HTTP or some other type of protocol. Often, native applications use various libraries for making API calls simpler. -Some experts recommend that native applications (including mobile apps) use OAuth's authorization code grant. This method works fine with many IdPs, including FusionAuth, but is not listed in this section because it is covered in the SPA and WebApp sections above. The only difference is that at the end of the OAuth workflow, the native application pulls the JWT and refresh tokens from the web-view. +Some experts recommend that native applications (including mobile apps) use OAuth's authorization code grant. This method works fine with many IdPs, including FusionAuth, but is not listed in this section because it is covered in the Single Page Application and Traditional Web Application sections above. The only difference is that at the end of the OAuth workflow, the native application pulls the JWT and refresh tokens from the web-view. diff --git a/astro/src/content/articles/oauth/complete-list-oauth-grants.md b/astro/src/content/articles/oauth/complete-list-oauth-grants.md index 2ecde99e8b..4744387d50 100644 --- a/astro/src/content/articles/oauth/complete-list-oauth-grants.md +++ b/astro/src/content/articles/oauth/complete-list-oauth-grants.md @@ -143,7 +143,7 @@ The Device Code grant type works well for devices that don’t support an easy d - `user_code`, which is the code the user enters once they’ve authorized with the Authorization Server. - `device_code`, which is the unique Id assigned to the Client. - `interval`, which is the polling time in seconds at which the client should poll the server for an access token. -3. The Client keeps attempting to acquire an access token every few seconds (at a rate specified by interval) by `POST`ing to the access token endpoint on the Authorization Server: +3. The Client keeps attempting to acquire an access token every few seconds (at a rate specified by interval) by `POST`-ing to the access token endpoint on the Authorization Server: - `grant_type`, with the value `urn:ietf:params:oauth:grant-type:device_code`. - `client_id`, which is the code the user enters once they’ve authenticated with the Authorization Server. - `code`, which is the value of the `device_code` from the JSON response in the previous request. diff --git a/astro/src/content/articles/oauth/modern-guide-to-oauth.mdx b/astro/src/content/articles/oauth/modern-guide-to-oauth.mdx index 3842c4c480..f3ffa528b0 100644 --- a/astro/src/content/articles/oauth/modern-guide-to-oauth.mdx +++ b/astro/src/content/articles/oauth/modern-guide-to-oauth.mdx @@ -320,7 +320,7 @@ Rather than point the anchor tag directly at the OAuth server, we'll point it at Login ``` -Next, we need to write the controller for `/login` in the application. Here's a JavaScript snippet using NodeJS/Express that accomplishes this: +Next, we need to write the controller for `/login` in the application. Here's a JavaScript snippet using Node.js/Express that accomplishes this: ```javascript router.get('/login', function(req, res, next) { @@ -891,7 +891,7 @@ At this point, the application backend has redirected the browser to the user's The `id_token` is treated less securely than the `access_token` and `refresh_token` for a reason. The `id_token` should never be used to access protected resources; it is simply a way for the application to obtain read-only information about the user. If, for example, you want your SPA to update the user interface to greet the user by name, the `id_token` is available. -These cookies also act as our session. Once the cookies disappear or become invalid, our application knows that the user is no longer logged in. Let's take a look at how we use these tokens to make an authorized API call. You can also have server side html generated based on the `access_token`, but we'll leave that as an exercise for the reader. +These cookies also act as our session. Once the cookies disappear or become invalid, our application knows that the user is no longer logged in. Let's take a look at how we use these tokens to make an authorized API call. You can also have server side HTML generated based on the `access_token`, but we'll leave that as an exercise for the reader. This API retrieves the user's ToDos from the database. We'll then generate the user interface in browser side code. @@ -1083,7 +1083,7 @@ function buildClickHandler() { } ``` -Since the `refresh_token` is an `HTTPOnly` cookie, JavaScript can't call a refresh endpoint to get a new access token. Our client side JavaScript would have to have access to the refresh token value to do so, but we don't allow that because of cross site scripting concerns. Instead, the client calls a server-side route, which will then try to refresh the tokens using the cookie value; it has access to that value. After that, the server will send down the new values as cookies, and the browser code can retry the API calls. +Since the `refresh_token` is an `HttpOnly` cookie, JavaScript can't call a refresh endpoint to get a new access token. Our client side JavaScript would have to have access to the refresh token value to do so, but we don't allow that because of cross site scripting concerns. Instead, the client calls a server-side route, which will then try to refresh the tokens using the cookie value; it has access to that value. After that, the server will send down the new values as cookies, and the browser code can retry the API calls. Here's the `refresh` server side route, which accesses the refresh token and tries to, well, refresh the access and Id tokens. @@ -1590,7 +1590,7 @@ Access tokens must be kept private, both in transit and at rest. Passing the tok ### Client Ids -OAuth 2.0 typically requires static, out of band initial configuration. For example, before an application can call the WUPHF API to retrieve information on behalf of a user, it must first receive approval from Wuphf. This process is called "Client Registration" and can be done manually or, in certain circumstances, programmatically. +OAuth 2.0 typically requires static, out of band initial configuration. For example, before an application can call the WUPHF API to retrieve information on behalf of a user, it must first receive approval from WUPHF. This process is called "Client Registration" and can be done manually or, in certain circumstances, programmatically. During Client registration, the third party application provides information like the client type, a redirect URL where the authorization code can be sent, and other related information including a website and description. The Authorization Server then generates a client Id and a client secret. diff --git a/astro/src/content/articles/oauth/oauth-device-authorization.mdx b/astro/src/content/articles/oauth/oauth-device-authorization.mdx index 1ee168e31b..ed96cae3a1 100644 --- a/astro/src/content/articles/oauth/oauth-device-authorization.mdx +++ b/astro/src/content/articles/oauth/oauth-device-authorization.mdx @@ -1,6 +1,6 @@ --- title: OAuth Device Authorization -description: How to implement OAuth Device Authorization for set-top devices like Roku, AppleTV, and XBox and more. +description: How to implement OAuth Device Authorization for set-top devices like Roku, AppleTV, and Xbox and more. image: advice/oauth-device-authorization-article.png author: Matthew Altman & Trevor Smith section: OAuth @@ -11,7 +11,7 @@ darkIcon: /img/icons/oauth-device-authorization-dark.svg --- import Diagram from "../../../diagrams/articles/oauth/oauth-device-authorization-workflow.astro"; -If you have a modern entertainment device like a Roku, AppleTV, XBox, Playstation, etc., there's a good chance that at some point you will connect it to subscription services such as Netflix, Amazon, Pandora, or HBO. In theory it should be easy. It's your device and you've already purchased a subscription to the service. So, just turn it on and go right? Sadly, no. +If you have a modern entertainment device like a Roku, AppleTV, Xbox, PlayStation, etc., there's a good chance that at some point you will connect it to subscription services such as Netflix, Amazon, Pandora, or HBO. In theory it should be easy. It's your device and you've already purchased a subscription to the service. So, just turn it on and go right? Sadly, no. We've all gone through it, and the reality is it's not the best way to start off an evening of relaxation. Depending on the device and the service, you're almost guaranteed to hit a broad range of usability issues. Most of these services require you to log into your account and this means typing in your username and password. TV remotes and game controllers were never designed to handle this kind of text input. However, there is a simpler and standard way to accomplish this task. It's called the OAuth Device Authorization Grant and we will cover it here. @@ -19,7 +19,7 @@ We've all gone through it, and the reality is it's not the best way to start off ## The Problem -We login to accounts all the time using our phones and computers, so it shouldn't be that difficult on another device, right? The problem is Internet connected boxes like XBox and AppleTV don't have a built-in keyboard or tap input system. Suddenly, usability becomes a big issue. Fumbling your way through an on-screen keyboard to enter your username and password using a D-pad on a game controller or the arrow keys on a remote control can be a nightmare. And since most services ask you to enter very long, complex keycodes with all sorts of special characters and mixed-case letters, it's highly likely you will accidentally enter it wrong and have to start all over again. +We login to accounts all the time using our phones and computers, so it shouldn't be that difficult on another device, right? The problem is Internet connected boxes like Xbox and AppleTV don't have a built-in keyboard or tap input system. Suddenly, usability becomes a big issue. Fumbling your way through an on-screen keyboard to enter your username and password using a D-pad on a game controller or the arrow keys on a remote control can be a nightmare. And since most services ask you to enter very long, complex keycodes with all sorts of special characters and mixed-case letters, it's highly likely you will accidentally enter it wrong and have to start all over again.
## The Solution diff --git a/astro/src/content/articles/oauth/oauth-token-storage.mdx b/astro/src/content/articles/oauth/oauth-token-storage.mdx index f4669770e9..719cf69afe 100644 --- a/astro/src/content/articles/oauth/oauth-token-storage.mdx +++ b/astro/src/content/articles/oauth/oauth-token-storage.mdx @@ -63,13 +63,13 @@ If you've decided to use an OAuth grant, you need to store the resulting tokens. The first option is to store the access token and refresh token on the client, whether that is a browser, desktop or native application. Only the access token is presented to APIs or protected resources. The refresh token should be presented to the authorization server, but that workflow will be covered in more detail below. If the refresh token cookie is sent to a resource server, it can be safely ignored. -When using a browser, store these as `HTTPOnly`, secure cookies with a `SameSite` value of `Lax` or `Strict`. +When using a browser, store these as `HttpOnly`, secure cookies with a `SameSite` value of `Lax` or `Strict`. If you choose this option, the browser, whether a simple HTML page with some JavaScript or a complicated single page application (SPA), makes requests against APIs; the access token is then taken along for the ride. This works great as long as APIs and the server setting the token cookies live on a domain with shared cookies. For example, the code which gets the tokens can live at `auth.example.com` and if you set the cookie domain to `.example.com`, APIs living at `api.example.com`, `todo.example.com`, or any other host under `.example.com`, will receive the token. - + When using a native app, store these tokens in a secure location, such as the [iOS Keychain](https://developer.apple.com/documentation/security/keychain_services) or [Android internal data](https://developer.android.com/topic/security/best-practices#safe-data). This protects these credentials from any other applications running on your device. Retrieve them and append them to the proper header before making API requests. @@ -102,7 +102,7 @@ Checking other claims is business logic and can be handled by the API developer. If the access token doesn't meet the criteria above, you can introspect the token by presenting it to the authorization server. With this process, the validity of the token is confirmed by the token issuing software. - + A successful introspection request returns JSON. Claims in this response still need to be checked: @@ -128,7 +128,7 @@ When the access token expires, the client can present the refresh token to the a If you use client stored tokens, you gain horizontal scalability, since each API can take requests directly from every client. As mentioned above, this approach is a great fit for a single page JavaScript application using data from multiple APIs on the same domain. -Using secure `HTTPOnly` cookies protects you from cross-site scripting (XSS) attacks. XSS is a common way for attackers to gain access to tokens. When they gain the tokens, they can make requests masquerading as the user for whom the token was granted. Secure `HTTPOnly` cookies, however, are not available to JavaScript running on the page, and therefore can't be accessed by malicious scripts. +Using secure `HttpOnly` cookies protects you from cross-site scripting (XSS) attacks. XSS is a common way for attackers to gain access to tokens. When they gain the tokens, they can make requests masquerading as the user for whom the token was granted. Secure `HttpOnly` cookies, however, are not available to JavaScript running on the page, and therefore can't be accessed by malicious scripts. If your APIs are on multiple domains, or on domains different than what can set a token cookie, you have two options: diff --git a/astro/src/content/articles/security/adaptive-mfa-user-experience.mdx b/astro/src/content/articles/security/adaptive-mfa-user-experience.mdx index 7c7c77099f..26a83d10dc 100644 --- a/astro/src/content/articles/security/adaptive-mfa-user-experience.mdx +++ b/astro/src/content/articles/security/adaptive-mfa-user-experience.mdx @@ -7,7 +7,7 @@ darkIcon: /img/icons/adaptive-mfa-dark.svg section: Security --- -Security measures often feel like they're just making life harder for end users. Meanwhile, attackers are out there finding clever ways to bypass these tools. They love it when users get frustrated because it makes [phishing campaigns](/articles/authentication/why-passwordless-authentication-matters) and stealing those long, complex passwords a breeze. [Multifactor authentication (MFA)](/articles/authentication/multi-factor-authentication) stepped in to stop these criminals from effectively accessing company resources using stolen passwords. But if users are already triggered by complex password policies, adding yet another step to the authentication process makes the matter go from bad to worse---in their eyes, at least. +Security measures often feel like they're just making life harder for end users. Meanwhile, attackers are out there finding clever ways to bypass these tools. They love it when users get frustrated because it makes [phishing campaigns](/articles/authentication/why-passwordless-authentication-matters) and stealing those long, complex passwords a breeze. [Multi-factor authentication (MFA)](/articles/authentication/multi-factor-authentication) stepped in to stop these criminals from effectively accessing company resources using stolen passwords. But if users are already triggered by complex password policies, adding yet another step to the authentication process makes the matter go from bad to worse---in their eyes, at least. But the future is here, and it's called adaptive MFA. While there are some consumer applications, the real power of adaptive MFA is in protecting the workforce, so we're seeing increased adoption in the enterprise. It's designed for security pros and IT teams who need to keep organizational resources safe. By adjusting authentication requirements based on real-time risk, it offers strong security without the hassle. This version maintains a conversational and engaging tone, emphasizing the adoption of adaptive MFA in the enterprise context and aligning with the intended audience of security professionals and IT teams. diff --git a/astro/src/content/articles/security/guide-to-user-data-security.mdx b/astro/src/content/articles/security/guide-to-user-data-security.mdx index dda10ee260..a7eaf98d00 100644 --- a/astro/src/content/articles/security/guide-to-user-data-security.mdx +++ b/astro/src/content/articles/security/guide-to-user-data-security.mdx @@ -534,7 +534,7 @@ COMMIT A complete explanation of the IPTables rule file format is out of scope for this guide however we will cover some of the basics so that you can configure your file to suit your needs. IPTables rule files are broken down into Tables. Tables are defined using an asterisk character followed by the table name. Everything after the table definition is included in that table's rules until the `COMMIT` command is hit. -The `filter` table is the most important table above, but the nat table is also used and we'll cover that shortly. The filter table defined like this: +The `filter` table is the most important table above, but the NAT table is also used and we'll cover that shortly. The filter table defined like this: ```ini *filter @@ -544,7 +544,7 @@ COMMIT We'll ignore the `raw`, `security` and `mangle` tables for now. You can find more information about them online if you are interested. -A table can hold one or more chains. There are a number of predefined chains in each table, but for the filter table the three chains are `INPUT`, `OUTPUT` and `FORWARD`. In the nat table, we will use the `PREROUTING` chain as well. Here are the definitions of these chains: +A table can hold one or more chains. There are a number of predefined chains in each table, but for the filter table the three chains are `INPUT`, `OUTPUT` and `FORWARD`. In the NAT table, we will use the `PREROUTING` chain as well. Here are the definitions of these chains: * `INPUT` - this chain is used when packets are sent from an external source to the server * `OUTPUT` - this chain is used when packets are sent from the server to an external source @@ -608,9 +608,9 @@ The final rules are setup for each of the protocols you are interested in. By de These rules read like this, "for TCP packets (`-A TCP -p tcp`), on port 22 (`--dport 22`), accept them (`-j ACCEPT`)". There is a separate rule for each port that should be open on the server. You'll notice that the server listens on the standard HTTP and HTTPS ports, but also port 3000 and 3003, which are the ports our example application will be listening on. -In addition to the `filter` table, the configuration above also makes use of the `nat` table. The `nat` table is used because later in this guide, you will run your application as a non-privileged user (i.e. not the root user). This is to ensure that breaches to the application won't allow hackers full access to the server. Linux servers don't allow non-privileged users to bind ports below 1000. Therefore, the IPTables configuration forwards traffic on port 80 to port 3000 and traffic on port 443 to port 3003. To accomplish this port forwarding, we make use of the `PREROUTING` chain in the `nat` table. +In addition to the `filter` table, the configuration above also makes use of the NAT table. The NAT table is used because later in this guide, you will run your application as a non-privileged user (i.e. not the root user). This is to ensure that breaches to the application won't allow hackers full access to the server. Linux servers don't allow non-privileged users to bind ports below 1000. Therefore, the IPTables configuration forwards traffic on port 80 to port 3000 and traffic on port 443 to port 3003. To accomplish this port forwarding, we make use of the `PREROUTING` chain in the NAT table. -Under the `nat` table, there are two rules defined: +Under the NAT table, there are two rules defined: ```ini -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000 @@ -734,7 +734,7 @@ This file states that Monit should watch the file `/var/log/auth.log` and if it You can also whitelist certain IP addresses by uncommenting the ignore match line and creating the file `/etc/monit/whitelist_ips.regex`. This file would contain regular expressions for each whitelisted IP on a separate line. -The last step to configuring Monit is to edit the file `/etc/monit/monitrc`. Add the lines below to configure Monit to send email alerts to you. This configuration will vary depending on your SMTP mail server, the authentication required for your SMTP server and your email address. Our examples use Sendgrid for sending emails and my email address. +The last step to configuring Monit is to edit the file `/etc/monit/monitrc`. Add the lines below to configure Monit to send email alerts to you. This configuration will vary depending on your SMTP mail server, the authentication required for your SMTP server and your email address. Our examples use SendGrid for sending emails and my email address. ```ini set mailserver smtp.sendgrid.net port 587 username "" password "" using tlsv12 @@ -1330,7 +1330,7 @@ It is interesting to note that the PBKDF2 algorithm takes the salt as a paramete ### SQL Injections -SQL injection is an application level vulnerability that is caused when an application builds SQL queries (or any type of database query) directly from user input. The XKCD comic strip illustrates this principle: +SQL injection is an application level vulnerability that is caused when an application builds SQL queries (or any type of database query) directly from user input. The xkcd comic strip illustrates this principle: ![SQL Injection](/img/articles/guide-to-user-data-security/sql-injection.png) diff --git a/astro/src/content/articles/tokens/jwt-components-explained.md b/astro/src/content/articles/tokens/jwt-components-explained.md index f04310ef2d..05ee37dbfb 100644 --- a/astro/src/content/articles/tokens/jwt-components-explained.md +++ b/astro/src/content/articles/tokens/jwt-components-explained.md @@ -133,7 +133,7 @@ When code is presented with a JWT, it should verify certain claims. At a minimum * `iss` identifies the issuer of the JWT. It doesn't matter exactly what this string is (UUID, domain name, URL or something else) as long as the issuer and consumer of the JWT agree on valid values, and that the consumer validates the claim matches a known good value. * `aud` identifies the audience of the token, that is, who should be consuming it. `aud` may be a scalar or an array value. Again, the issuer and the consumer of the JWT should agree on the specific values considered acceptable. -* `nbf` and `exp`. These claims determine the timeframe for which the token is valid. The `nbf` claim can be useful if you are issuing a token for future use. The `exp` claim, a time beyond which the JWT is no longer valid, should always be set. Unlike other claims, these have a defined value format: seconds since the unix epoch. +* `nbf` and `exp`. These claims determine the timeframe for which the token is valid. The `nbf` claim can be useful if you are issuing a token for future use. The `exp` claim, a time beyond which the JWT is no longer valid, should always be set. Unlike other claims, these have a defined value format: seconds since the UNIX epoch. In addition to these, verify business domain specific claims. For instance, someone consuming the above JWT could deny access when `authenticationType` is an unknown value. diff --git a/astro/src/content/blog/2023-hacktoberfest.mdx b/astro/src/content/blog/2023-hacktoberfest.mdx index 1cd9af298a..f396f7c904 100644 --- a/astro/src/content/blog/2023-hacktoberfest.mdx +++ b/astro/src/content/blog/2023-hacktoberfest.mdx @@ -10,7 +10,7 @@ excerpt_separator: "{/* more */}" --- import {RemoteCode} from '@fusionauth/astro-components'; -We're excited to announce FusionAuth's participation in this year's Hacktoberfest! Hacktoberfest is a global event that takes place every October, during which developers are encouraged to contribute to open-source projects like FusionAuth. The goal is to foster a vibrant open-source community, celebrate shared knowledge, and make the world of coding more accessible to all. You can find other participating repositories by searching the hacktoberfest topic on github. +We're excited to announce FusionAuth's participation in this year's Hacktoberfest! Hacktoberfest is a global event that takes place every October, during which developers are encouraged to contribute to open-source projects like FusionAuth. The goal is to foster a vibrant open-source community, celebrate shared knowledge, and make the world of coding more accessible to all. You can find other participating repositories by searching the hacktoberfest topic on GitHub. {/* more */} @@ -31,13 +31,13 @@ This year for the Hacktoberfest we choose to focus on all of our JavaScript repo * [Consents](https://github.com/FusionAuth/fusionauth-example-express-consents)- Example using advanced registration forms and consents * [Deeplinking](https://github.com/FusionAuth/fusionauth-example-node-deeplink)- Example returning users to the same page they logged in on * [Device grant](https://github.com/fusionauth/fusionauth-example-device-grant)- An example of the Device Authorization grant -* [Express API](https://github.com/FusionAuth/fusionauth-example-express-api)- Express api which uses the Cookie Access Token +* [Express API](https://github.com/FusionAuth/fusionauth-example-express-api)- Express API which uses the Cookie Access Token * [Family management](https://github.com/fusionauth/fusionauth-example-family)- Family management and consent creation * [FusionAuth SSO](https://github.com/FusionAuth/fusionauth-example-node-sso)- Example of SSO between two different custom applications * [Gaming and device grant](https://github.com/FusionAuth/fusionauth-example-gaming-device-grant)- Example using the Device Authorization grant to provide authentication to a game. * [Gatsby OAuth](https://github.com/fusionauth/fusionauth-example-gatsby)- An example of using Gatsby with the Authorization Code grant and PKCE * [JWT Auth and a Microservices gateway](https://github.com/FusionAuth/fusionauth-example-node-services-gateway-jwtauth)- API gateway and microservices secured using JWT auth -* [Javascript JWT](https://github.com/fusionauth/fusionauth-example-javascript-jwt)- JWT creation and decoding examples with javascript +* [JavaScript JWT](https://github.com/fusionauth/fusionauth-example-javascript-jwt)- JWT creation and decoding examples with JavaScript * [Magic links login](https://github.com/FusionAuth/fusionauth-example-nextjs-magic-links)- nextjs app which uses magic links for authentication * [Microservices gateway](https://github.com/FusionAuth/fusionauth-example-node-services-gateway)- API gateway and microservices * [Multi-tenant application](https://github.com/FusionAuth/fusionauth-example-node-multi-tenant)- Two nodejs applications in different tenants, living in different domains. diff --git a/astro/src/content/blog/2024-hacktoberfest.mdx b/astro/src/content/blog/2024-hacktoberfest.mdx new file mode 100644 index 0000000000..cad04ef777 --- /dev/null +++ b/astro/src/content/blog/2024-hacktoberfest.mdx @@ -0,0 +1,52 @@ +--- +publish_date: 2024-09-23 +title: Hacktoberfest 2024 with FusionAuth +description: FusionAuth joins in the Hacktoberfest event in 2024 +authors: Alex Patterson +image: /img/blogs/2024-hacktoberfest/hacktoberfest-2024.png +categories: News +tags: github, hackathon, open source, hacktoberfest, javascript +excerpt_separator: "{/* more */}" +--- +import {RemoteCode} from '@fusionauth/astro-components'; + +We're excited to announce FusionAuth's participation in this year's Hacktoberfest! Hacktoberfest is a global event that takes place every Autumn, during which developers are encouraged to contribute to open-source projects like FusionAuth. The goal is to foster a vibrant open-source community, celebrate shared knowledge, and make the world of coding more accessible to all. You can find other participating repositories by searching GitHub or GitLab. + +{/* more */} + +## Getting Started + +The first step is to register for Hacktoberfest. Once you've registered, any PRs submitted to FusionAuth (or any other repo with the label #Hacktoberfest) will count towards your participation in the event! + +## Contributing + +If you haven't participated before make sure to read the Hacktoberfest Participation Guide. + +To see all of FusionAuth's issues in one place see the [full issue search](https://github.com/search?q=user%3AFusionAuth+label%3Ahacktoberfest+state%3Aopen&type=Issues&ref=advsearch&l=&l=). + +This year for the Hacktoberfest we chose to focus on all of our JavaScript and Mobile repositories. I have added the tag `hacktoberfest` to each one of the following repositories and even added an issue for simply updating the packages to their latest version. + +### JavaScript + +* [Angular](https://github.com/fusionauth/fusionauth-quickstart-javascript-angular-web)- The Authorization Code grant using the Angular framework +* [Consents](https://github.com/FusionAuth/fusionauth-example-express-consents)- Example using advanced registration forms and consents +* [Deeplinking](https://github.com/FusionAuth/fusionauth-example-node-deeplink)- Example returning users to the same page they logged in on +* [Device grant](https://github.com/fusionauth/fusionauth-example-device-grant)- An example of the Device Authorization grant +* [Family management](https://github.com/fusionauth/fusionauth-example-family)- Family management and consent creation +* [FusionAuth SSO](https://github.com/FusionAuth/fusionauth-example-node-sso)- Example of SSO between two different custom applications +* [Gaming and device grant](https://github.com/FusionAuth/fusionauth-example-gaming-device-grant)- Example using the Device Authorization grant to provide authentication to a game. +* [Gatsby OAuth](https://github.com/fusionauth/fusionauth-example-gatsby)- An example of using Gatsby with the Authorization Code grant and PKCE +* [JWT Auth and a Microservices gateway](https://github.com/FusionAuth/fusionauth-example-node-services-gateway-jwtauth)- API gateway and microservices secured using JWT auth +* [JavaScript JWT](https://github.com/fusionauth/fusionauth-example-javascript-jwt)- JWT creation and decoding examples with JavaScript +* [Magic links login](https://github.com/FusionAuth/fusionauth-example-nextjs-magic-links)- nextjs app which uses magic links for authentication +* [Microservices gateway](https://github.com/FusionAuth/fusionauth-example-node-services-gateway)- API gateway and microservices +* [Multi-tenant application](https://github.com/FusionAuth/fusionauth-example-node-multi-tenant)- Two nodejs applications in different tenants, living in different domains. +* [React with the hosted backend](https://github.com/fusionauth/fusionauth-quickstart-javascript-react-web)- The Authorization Code grant using the React framework with the FusionAuth React SDK and the hosted backend +* [React full stack](https://github.com/FusionAuth/fusionauth-example-react-fusiondesk)- Fusion Desk example +* [Twitter login](https://github.com/FusionAuth/fusionauth-example-express-twitter)- Node/express app which uses Twitter for authentication +* [User actions example](https://github.com/FusionAuth/fusionauth-example-user-actions-guide)- Corresponds to the user actions guide tutorial +* [Vue.js](https://github.com/fusionauth/fusionauth-quickstart-javascript-vue-web)- The Authorization Code grant using the Vue.js framework + +### Mobile + +* [Expo](https://github.com/FusionAuth/fusionauth-quickstart-react-native/issues/6)- React Native Quickstart diff --git a/astro/src/content/blog/announcing-fusionauth-1-26.mdx b/astro/src/content/blog/announcing-fusionauth-1-26.mdx index 63a0ae0807..e69a618e5d 100644 --- a/astro/src/content/blog/announcing-fusionauth-1-26.mdx +++ b/astro/src/content/blog/announcing-fusionauth-1-26.mdx @@ -87,7 +87,7 @@ Some of the other enhancements included in this release are: Also, there's a new themeable FusionAuth index page so when your users accidentally arrive at `auth.example.com`, they are not forwarded to the FusionAuth admin UI login page. (To proceed to that login page when using the default theme, click the lock in the upper right.) -![The themable root page. No more users ending up on the login page..](/img/blogs/release-1-26/themable-index-page.png) +![The themeable root page. No more users ending up on the login page..](/img/blogs/release-1-26/themable-index-page.png) Like I said, this was a big release! diff --git a/astro/src/content/blog/announcing-fusionauth-1-30.mdx b/astro/src/content/blog/announcing-fusionauth-1-30.mdx index 842be4a813..07e448fcd6 100644 --- a/astro/src/content/blog/announcing-fusionauth-1-30.mdx +++ b/astro/src/content/blog/announcing-fusionauth-1-30.mdx @@ -72,8 +72,8 @@ Customizable rate limiting per user for specific requests such as: ![Example of the rate limiting settings on the admin dashboard..](/img/blogs/release-1-30/rate-limiting.png) -Captcha - Uses additional captcha to guard against brute force attacks. -- Adds a (re)captcha for login pages. +CAPTCHA - Uses additional CAPTCHA to guard against brute force attacks. +- Adds a (re)CAPTCHA for login pages. - Includes support for Google ReCaptcha v2, Google ReCaptcha v3, HCaptcha and Hcaptcha Enterprise. Location aware security diff --git a/astro/src/content/blog/announcing-fusionauth-1-36.mdx b/astro/src/content/blog/announcing-fusionauth-1-36.mdx index fda254d224..8a6a72969d 100644 --- a/astro/src/content/blog/announcing-fusionauth-1-36.mdx +++ b/astro/src/content/blog/announcing-fusionauth-1-36.mdx @@ -45,11 +45,11 @@ This will allow developers to write a subsystem that immediately notices any new A typical user scenario might go as follow: -* A user, Alice, signs in to ExampleGame using 'login with XBox' and FusionAuth. A link event is sent. +* A user, Alice, signs in to ExampleGame using 'login with Xbox' and FusionAuth. A link event is sent. * Alice plays ExampleGame for months. -* Alice sells her XBox and buys a PS5. +* Alice sells her Xbox and buys a PS5. * Alice signs into ExampleGame with 'login with PSN'. A link event is sent. -* Alice notices that there is an XBox account associated with her FusionAuth account. She unlinks the account from within the ExampleGame UX. An unlink event is sent. +* Alice notices that there is an Xbox account associated with her FusionAuth account. She unlinks the account from within the ExampleGame UX. An unlink event is sent. Documentation for this web hook is available [here](/docs/extend/events-and-webhooks/events/). diff --git a/astro/src/content/blog/announcing-fusionauth-1-39.mdx b/astro/src/content/blog/announcing-fusionauth-1-39.mdx index 36d629f8e3..8e73f72484 100644 --- a/astro/src/content/blog/announcing-fusionauth-1-39.mdx +++ b/astro/src/content/blog/announcing-fusionauth-1-39.mdx @@ -35,7 +35,7 @@ curl -H 'Authorization: '$API_KEY \ This works well for primitive values, but for arrays and objects, it's more complicated. -Suppose you have a group "Paid employees" with roles of "ceo" and "dev": +Suppose you have a group "Paid employees" with roles of `ceo` and `dev`: ![A group of employees that are paid.](/img/blogs/release-1-39/paid-employees-group.png) @@ -82,7 +82,7 @@ FusionAuth was limited in how it handled arrays and other complex data structure But now there are additional choices. The first is to use [JSON Patch (RFC 6902)](https://www.rfc-editor.org/rfc/rfc6902). Use this option by setting the `Content-Type` in your request to `application/json-patch+json`. With this choice, you have fine grained control over the JSON object. You can move, replace or add fields. -Here's how you'd update the group to only have the "ceo" role: +Here's how you'd update the group to only have the `ceo` role: ``` API_KEY=... diff --git a/astro/src/content/blog/announcing-fusionauth-1-45.mdx b/astro/src/content/blog/announcing-fusionauth-1-45.mdx index 3d1706dc4e..0c9a70cd76 100644 --- a/astro/src/content/blog/announcing-fusionauth-1-45.mdx +++ b/astro/src/content/blog/announcing-fusionauth-1-45.mdx @@ -159,7 +159,7 @@ However, a key part of the Authorization Code grant is the exchange of the Autho But we wanted to make this even easier. For some users, setting up server side code is a hassle. -FusionAuth now offers a React SDK which communicates with endpoints managed by FusionAuth which will take care of the code exchange. They'll set the access token as an `HTTPOnly`, `Secure` cookie, as well as a refresh token as a cookie if requested. +FusionAuth now offers a React SDK which communicates with endpoints managed by FusionAuth which will take care of the code exchange. They'll set the access token as an `HttpOnly`, `Secure` cookie, as well as a refresh token as a cookie if requested. The endpoints the SDK calls are documented. You can create your own custom code at the same URLs if you'd prefer, but FusionAuth is a one-stop shop for your authentication needs, no server side code needed. [Read the docs here](/docs/apis/hosted-backend). diff --git a/astro/src/content/blog/announcing-fusionauth-1-48.mdx b/astro/src/content/blog/announcing-fusionauth-1-48.mdx index 5372be692e..74833a5dca 100644 --- a/astro/src/content/blog/announcing-fusionauth-1-48.mdx +++ b/astro/src/content/blog/announcing-fusionauth-1-48.mdx @@ -45,7 +45,7 @@ Here's how it works: Then, the application which receives the webhook needs to verify the message integrity. To do so: -* Create a sha 256 hash of the payload you receive. +* Create a SHA 256 hash of the payload you receive. * Extract the JWT from the `X-FusionAuth-Signature-JWT` header. * Verify the signature of the JWT. This step is important, otherwise someone might modify the JWT in the header, and tweak the hash to match the modified payload. * Then, compare the payload hash you first calculated with the value from the `request_body_sha256` claim. @@ -56,7 +56,7 @@ But it's not just webhook signing. There were other webhook related improvements * Webhook test messages now include more information if the webhook does not succeed. * You can use [key master](/docs/operate/secure-and-monitor/key-master) to manage webhook certificates. This is the recommended solution going forward. -* A bug was fixed. Previously tenant specific webhooks were removed when `PATCH`ing a tenant, and now they are not. +* A bug was fixed. Previously tenant specific webhooks were removed when `PATCH`-ing a tenant, and now they are not. * Test messages sent using the admin UI now preserve the body payload, making it easier to develop webhooks. ## User Search diff --git a/astro/src/content/blog/announcing-fusionauth-1-52.mdx b/astro/src/content/blog/announcing-fusionauth-1-52.mdx index 578401dfa1..a32c3ebbbe 100644 --- a/astro/src/content/blog/announcing-fusionauth-1-52.mdx +++ b/astro/src/content/blog/announcing-fusionauth-1-52.mdx @@ -8,7 +8,6 @@ categories: Product tags: fusionauth, passkeys, product excerpt_separator: "{/* more */}" --- - We know that the digital world is a safer place when more companies adopt strong login and authentication practices. We also know that 10 million plus FusionAuth downloads means that we've already made an impact. But what if we could do more? What if we gave [passkeys](/guides/what-is-a-passkey) to...everyone? Sure, it means that we're giving away a high-value feature for free, but it also means that people and data are going to be safer. diff --git a/astro/src/content/blog/announcing-fusionauth-1-53.mdx b/astro/src/content/blog/announcing-fusionauth-1-53.mdx new file mode 100644 index 0000000000..4e5d7690fd --- /dev/null +++ b/astro/src/content/blog/announcing-fusionauth-1-53.mdx @@ -0,0 +1,45 @@ +--- +publish_date: 2024-09-10 +title: Announcing FusionAuth Version 1.53.0 - Webhook Logs and New Lambdas +description: Version 1.53.0 of FusionAuth introduces two requested features. You can now see a history of webhooks and their statuses, and logins now have more logic. +authors: Brad McCarty +image: /img/blogs/release-1-53/fusionauth-1-53-0.png +categories: Product +tags: lambdas, login logic, webhook logs, customer data, product +excerpt_separator: "{/* more */}" +--- + +We recently released version 1.53.0 of FusionAuth. As we [continue our work](/blog/fusionauth-inc-5000-2024) toward simplification and a better user experience, we've added some hotly-requested features. Marching forward with our animal-based naming convention, I hereby dub version 1.53.0 The Login Lambda Llama. + +FusionAuth Login Lambda Llama Meme. A llama with the caption that reads Lambda Llama is suspicious of your credentials + +## Lambda-Based Login Control + +Sometimes you need fine-grained control of an authentication. Here are some examples: + +- A person who is a member of one group, but not of another. Weekday access to an application depends on being in both groups. +- You want to require all users who are logging in to use SAMLv2 and disallow any other kinds of login. +- Users of the Hooli application must have a `hooli.com` email address, while users of the Pied Piper application can have a `hooli.com` or a `piedpiper.com` email address. + +In a scenario like these, you need more than a login failure. After all, their login information may be correct, but they just don't have access to that application. You need to be able to apply some level of logic to their authentication event. That's where login lambdas come into play. You can find a high-level overview of lambdas [inside our docs](/docs/extend/code/lambdas/). + +This is an addition to our long list of lambdas, which all add flexibility and extensibility to the FusionAuth login experience. + +In this release, there is a new lambda that runs at the moment of login. This lambda returns a list of themeable error messages. If the list is empty, the login process continues. If the list contains error messages, then the login fails and your users are presented with the error messages. + +This kind of flexibility should help developers use any kind of business logic to prevent unwanted access to their applications. When combined with [Lambda HTTP Connect](/docs/extend/code/lambdas/#using-lambda-http-connect), you can even call out to external APIs and re-use existing business logic to allow or deny access. + +## Webhook Event Logs + +If you've used FusionAuth, you know we love webhooks. With over fifty different events, you can use these to share data or affect user login or creation workflows. + +But hey, we aren't perfect! One flaw is that webhook events are not persistent within FusionAuth. This means that you couldn't view a historical record of events and their responses, which would be extremely useful for troubleshooting or reviewing history. + +Version 1.53.0 fixes this problem by adding a webhook event log. Now you can go back in time and see what webhooks fired and when. Since we haven't invented time travel, this will only go back to the date that you upgrade to version 1.53.0, but it should help you with webhook usage and debugging going forward. + +## All the Rest + +There's more! We're updating to Java 21, we've spent a lot of time optimizing FusionAuth for performance, and miscellaneous bug fixes as well. You can get all of the details about this and much more in our [Release Notes](/docs/release-notes/). + +If you're not using FusionAuth, why not? We've made it easier than ever to kick the tires. Just [choose a plan](/pricing) and enter your email. There's no credit card required to get your trial started. + diff --git a/astro/src/content/blog/anonymous-user.mdx b/astro/src/content/blog/anonymous-user.mdx index 3a92b95032..819c2801a9 100644 --- a/astro/src/content/blog/anonymous-user.mdx +++ b/astro/src/content/blog/anonymous-user.mdx @@ -94,7 +94,7 @@ You can store the Id in the following ways inside the cookie: * A signed token, such as a JWT. Checking the signature on every request costs some computational power, but avoids malicious actors probing other user Ids. * An encrypted, URL safe value. This is typically overkill for an opaque user Id, but if your user Id might leak information, such as the size of your user base because it is an integer value, then encryption might work. -This cookie can be stored as an HTTPOnly, Secure cookie since only your server-side code will be examining it. Each time the cookie is presented, the server-side code can decode it, and then update the anonymous account profile if needed. +This cookie can be stored as an HttpOnly, Secure cookie since only your server-side code will be examining it. Each time the cookie is presented, the server-side code can decode it, and then update the anonymous account profile if needed. Here's an example of code that sets a JWT with a user Id, using the [FusionAuth JWT Vend API](/docs/apis/jwt#vend-a-jwt). diff --git a/astro/src/content/blog/auth-facade-pattern.mdx b/astro/src/content/blog/auth-facade-pattern.mdx index b83b69704e..da689454e6 100644 --- a/astro/src/content/blog/auth-facade-pattern.mdx +++ b/astro/src/content/blog/auth-facade-pattern.mdx @@ -69,7 +69,7 @@ You'll want a responsive team behind the auth facade system when issues arise. Y When evaluating auth facade solutions, make sure you can deploy the system providing the facade into a variety of customer environments. This rules out any typical SaaS solutions, unless the SaaS provider deploys into their network. Being able to support air gapped or isolated networks can be a strong differentiator for your application, especially if it accesses sensitive data. -Ensure your application and the auth facade system are deployable using the same technologies. Doing so decreases installation complexity. Depending on customers' needs, you may want to deploy in a unix friendly package such as an RPM or DEB, a generic software package like a zip file, or, for the cutting edge clients using kubernetes, a container solution such as Docker. +Ensure your application and the auth facade system are deployable using the same technologies. Doing so decreases installation complexity. Depending on customers' needs, you may want to deploy in a UNIX friendly package such as an RPM or DEB, a generic software package like a zip file, or, for the cutting edge clients using kubernetes, a container solution such as Docker. Since auth is a necessary part of your application, but not a differentiator, an auth system that fades into the background is best. This should happen both in the literal sense, with a user interface that isn't recognizable as separate from your application, and the figurative sense, where your engineers minimize time spent worrying about it or maintaining it. diff --git a/astro/src/content/blog/aws-savings-plans.mdx b/astro/src/content/blog/aws-savings-plans.mdx index b82a6e1a69..b872a02402 100644 --- a/astro/src/content/blog/aws-savings-plans.mdx +++ b/astro/src/content/blog/aws-savings-plans.mdx @@ -139,7 +139,7 @@ Instead of buying the amount recommended by AWS, I bought 50% of it. In the futu This will allow us to work towards having 100% of our usage covered by a savings plan. But we'll never get there. Similar to [Achilles and the tortoise from Zeno's paradox](https://en.wikipedia.org/wiki/Zeno%27s_paradoxes) (image credit to Wikipedia). -![Achilles and the turtle, an example of Zeno's paradox. Image credit: wikipedia.](/img/blogs/aws-savings-plans/zeno-achilles-paradox.png) +![Achilles and the turtle, an example of Zeno's paradox. Image credit: Wikipedia.](/img/blogs/aws-savings-plans/zeno-achilles-paradox.png) After determining that system would work, I documented it so I wouldn't forget. This also lets others do this task if need be. Then I attached it to a recurring event in my calendar and promptly forgot about it. Every quarter or so, I get a reminder, and log into the AWS console and buy more discounted compute hours. diff --git a/astro/src/content/blog/best-practices-for-oauth-in-mobile-apps.mdx b/astro/src/content/blog/best-practices-for-oauth-in-mobile-apps.mdx index f8ccb88171..361b77cb80 100644 --- a/astro/src/content/blog/best-practices-for-oauth-in-mobile-apps.mdx +++ b/astro/src/content/blog/best-practices-for-oauth-in-mobile-apps.mdx @@ -12,7 +12,7 @@ excerpt_separator: "{/* more */}" import { YouTube } from '@astro-community/astro-embed-youtube'; import Aside from '/src/components/Aside.astro'; -Learn mobile app development & OAuth practices with Fusionauth. Improve user login experience, speed up development, and secure APIs for your applications. Dive into security & single sign-on. +Learn mobile app development & OAuth practices with FusionAuth. Improve user login experience, speed up development, and secure APIs for your applications. Dive into security & single sign-on. {/* more */} @@ -199,4 +199,4 @@ Trust me if she can see it so will you! ## Conclusion -Using OAuth and OIDC enables secure sign-on flows while accelerating development. By following the practices outlined here around protected tokens and platform-specific guidelines, native apps can build robust Id management. \ No newline at end of file +Using OAuth and OIDC enables secure sign-on flows while accelerating development. By following the practices outlined here around protected tokens and platform-specific guidelines, native apps can build robust Id management. diff --git a/astro/src/content/blog/building-fusionauth-homebrew-formula.mdx b/astro/src/content/blog/building-fusionauth-homebrew-formula.mdx index b95dd9ef3f..42405b1c6e 100644 --- a/astro/src/content/blog/building-fusionauth-homebrew-formula.mdx +++ b/astro/src/content/blog/building-fusionauth-homebrew-formula.mdx @@ -29,7 +29,7 @@ brew services start fusionauth-search brew services start fusionauth-app ``` -How's that for fast and simple? Now you can dive in and start using the API. If this is your first time, you'll need to go through [the Setup Wizard](/blog/2019/02/05/using-the-setup-wizard), and then you'll be good to create users, applications and roles. For specific details, read through our [detailed documentation](/docs/), and let us know if you have any questions on [StackOverflow](https://stackoverflow.com/questions/tagged/fusionauth "Jump to StackOverflow") or [Github](https://github.com/FusionAuth/fusionauth-issues "Jump to Github"). +How's that for fast and simple? Now you can dive in and start using the API. If this is your first time, you'll need to go through [the Setup Wizard](/blog/2019/02/05/using-the-setup-wizard), and then you'll be good to create users, applications and roles. For specific details, read through our [detailed documentation](/docs/), and let us know if you have any questions on [StackOverflow](https://stackoverflow.com/questions/tagged/fusionauth "Jump to StackOverflow") or [GitHub](https://github.com/FusionAuth/fusionauth-issues "Jump to GitHub"). ## How We Built the Homebrew Formula @@ -52,7 +52,7 @@ To solve this problem, I modified our Homebrew formula to `tar` up the `dylib`s Just one more note on this. It seems that Homebrew can't differentiate between library formulas that are meant to be linked against and dynamically loaded binaries used internally by a program. There are some good forum threads and StackOverflow questions on this, but it would be great if Homebrew allowed formula designers to specify a configuration file of `dylib`s it should ignore. -During development I was able to test this using the following command, which allowed me to test the formulas locally without constantly iterating through Github. This command is very handy and allows you to avoid the cycle of push, test, debug and repeat: +During development I was able to test this using the following command, which allowed me to test the formulas locally without constantly iterating through GitHub. This command is very handy and allows you to avoid the cycle of push, test, debug and repeat: `brew install --debug -v ./Formula/fusionauth-${app}.rb` @@ -73,7 +73,7 @@ Homebrew has its own terminology that is helpful to understand before coding. **Brew Cask:** A macOS application which is usually defined by its `.app` extension and entirely self contained. A cask is used when an application doesn't have a simple formula for installing something and already has a macOS app. Think of Adobe Photoshop and other macOS desktop applications. -**Brew Tap:** A source for getting formulas. By default the shorthand is `/` which equates to a github repo under `/homebrew-` that has a folder inside called `Formula`, which contains any number of Ruby files, each of which is an installable formula. A rough equivalent would be a `ppa` or `apt` repo. +**Brew Tap:** A source for getting formulas. By default the shorthand is `/` which equates to a GitHub repo under `/homebrew-` that has a folder inside called `Formula`, which contains any number of Ruby files, each of which is an installable formula. A rough equivalent would be a `ppa` or `apt` repo. ### The Formula Parts @@ -188,7 +188,7 @@ Logs: /usr/local/var/log/fusionauth/fusionauth-app.log Config: /usr/local/etc/fusionauth/fusionauth.properties ``` -#### The PLIST! +#### The plist! If you would like your application to run as a service, you will need to include a plist as well. Brew automatically installs a plist file in the correct location if you define a `plist` function in your formula. Similar to the `caveat` function above, the return value of the `plist` function must be a String that is the content of the file. diff --git a/astro/src/content/blog/building-profile-portal-with-flask-oauth-apis.mdx b/astro/src/content/blog/building-profile-portal-with-flask-oauth-apis.mdx index 95c3f32ecc..9aeada3dea 100644 --- a/astro/src/content/blog/building-profile-portal-with-flask-oauth-apis.mdx +++ b/astro/src/content/blog/building-profile-portal-with-flask-oauth-apis.mdx @@ -348,7 +348,7 @@ All of these build links when called, and then send a redirect to the generated > You don't need these routes. You could hard code URLs into the template. But doing this makes for a more maintainable application, as well as nicer looking URLs. -The `/login` route uses the `requests_oauthlib` library to generate a proper authorization URL. The parameters for this URL are all defined by the [RFC](https://tools.ietf.org/html/rfc6749). When the link is clicked, the end user will be shown the FusionAuth themable hosted pages, where they may log in. +The `/login` route uses the `requests_oauthlib` library to generate a proper authorization URL. The parameters for this URL are all defined by the [RFC](https://tools.ietf.org/html/rfc6749). When the link is clicked, the end user will be shown the FusionAuth themeable hosted pages, where they may log in. `/logout` deletes the user's session and calls the FusionAuth `logout` endpoint. This ensures that the systems where user state is maintained, your application and FusionAuth, have logged out the user. diff --git a/astro/src/content/blog/building-self-hostable-application.mdx b/astro/src/content/blog/building-self-hostable-application.mdx new file mode 100644 index 0000000000..1117809ddc --- /dev/null +++ b/astro/src/content/blog/building-self-hostable-application.mdx @@ -0,0 +1,437 @@ +--- +publish_date: 2024-09-25 +title: Building A Self-hostable Product +description: What do you need to consider when building and releasing a self-hostable product? +authors: Dan Moore +categories: Education +tags: download, product, architecture, air-gapping, engineering, self-host +image: /img/blogs/self-hostable-application/building-a-self-hostable-product.png +excerpt_separator: "{/* more */}" +--- + +In this article, you'll learn about the architecture, business model, and software design choices necessary to create a self-hostable developer tool. + +{/* more */} + +FusionAuth, the product, is designed to be [downloaded and run locally](/download). While you can pay FusionAuth, the company, to run FusionAuth, the product, [for you in the cloud](/docs/get-started/run-in-the-cloud/cloud) as a SaaS offering, many users run FusionAuth on their own servers or laptops. + +This article will focus on developer tools that are sold and require integration with an existing application, rather than standalone developer tools such as an IDE or products given away for free. + +Examples of the types of tools that this post applies to include: + +* a message queue +* an analytics engine +* an authorization as a service solution +* a database +* an identity provider offering authentication + +But first, why would you go down this path? + +A person choosing between building SaaS and self-hostable software. + +Doesn't the future belong to software-as-a-service (SaaS), where developers integrate functionality using APIs delivered over the Internet? Aren't self-hostable products straight out of the early 2000s, when Sourceforge.net and Freshmeat.net were how people got software? Back then, weren't they just called 'software', not 'downloadable software' or 'self-hostable software'? + +## Why Build A Self-Hostable Developer Tool + +There are a number of reasons to build a self-hostable developer tool which integrates with other applications. + +### Offer Control To Your Users + +The main reason is to allow developers more control. Developers like control, because they are responsible for the overall performance and functionality of their applications. If they can't control a critical part of their application infrastructure, when their application breaks, they can't fix it. That is extremely frustrating. + +With a SaaS solution, especially one built using a typical multi-tenant SaaS architecture, developers have a certain level of control, but it is limited. When using a SaaS offering developers cede some or all of the following aspects of their application: + +* data locality +* performance +* software versions +* availability + +As a SaaS provider, you can work around some limits. For example, [APIs can be versioned](https://stripe.com/blog/api-versioning) and you can offer data storage in multiple geographic areas. But there are limits. You are unlikely to be able to stand up a server in Greece or Zimbabwe, for example. With the typical SaaS offering, developers simply will not have as much control as they can if they self-host. Of course there's a tradeoff; more on that below. + +As a devtools provider, if you offer software that can be hosted on any Linux or Windows server, developers retain more control. Users can run the product on their own hardware, using their own datastores, in their own network. + +If there's a performance issue, they can troubleshoot it. If they want to minimize network hops between your product and their service, they configure the network. If the service or product has fallen over due to load, they can stand up more servers or throttle traffic. + +If they need to pin your product to a certain version, they can skip an upgrade, and treat the product like a library dependency. + +A Winnie the Pooh meme emphasizing control. + +#### Privacy Guarantees + +There are privacy benefits as well. The customer, by examining the network, source code, or documentation, can know exactly what data is sent to the company providing the product. By locking down external connections or preventing any data from being sent, the privacy of the data can be ensured. + +A developer can also guarantee encryption of data at rest or in transit when running software locally. + +SaaS providers can, and do, offer up legal guarantees for privacy of data. Facebook, while not a devtools company, [has fired employees for reading private messages](https://www.vice.com/en/article/bjp9zv/facebook-employees-look-at-user-data). But running the software locally makes violations impossible. + +#### Data Locality + +Data locality is an aspect of control that is increasingly important. How critical it is depends on the type of data your application holds. For customers' personally identifiable information (PII) in certain locations, such as Europe or California, you want to know exactly where the data is going. Not doing so can lead to harsh penalties due to GDPR or other regulations. + +It isn't just PII, though. If you have a product that operates on large amounts of data or highly proprietary and closely held information, it is easier to bring the product to the data, rather than entice or force the customer to bring data to the product. Building a self-hostable product enables this, by letting your customers run your application in their environment. + +#### Anonymity + +By making a developer tool self-hostable, you let developers test the product and learn how to use it without requiring them to provide any information. This lowers the level of effort required for evaluation. It is also a marketing differentiator. It can frustrate marketing teams, which are accustomed to having more information about potential users. + +**By operating a product themselves, you can offer customers control over their data.** That can be appealing to developers and customers. + +There are other benefits beyond offering control to your customers. + +### CI Simplicity + +If the entire application is self contained, you can stand it up in a CI environment, such as GitHub Actions or CircleCI. Each test can configure the installed local software to a precise, known state and independently run. + +FusionAuth solves for this use case with [Kickstart](/docs/get-started/download-and-install/development/kickstart), a custom configuration language that calls APIs on system boot. Your product can use a similar pattern or offer APIs, scripts or infrastructure as code (IaC) to allow configuration of the correct state. + +In this situation, with a number of developers running against a single account, a SaaS solution can be slower and more fragile. Developers are making requests over the network from a CI runner, which is a different environment than their laptops. Configuring a SaaS service may collide with other developers' tests. You can work around this with many accounts at the SaaS provider, but then you have to manage and/or pay for them. + +### Discovery And Distribution + +By offering a self-hostable product with developer friendly installation methods, devs can discover and integrate your product without ever talking to anybody. This lets developers evaluate your solution, using their own hardware and in their own environments, at near zero cost to you. + +Some of these installation methods include: + +* Homebrew +* Docker +* RPMs/DEBs +* Windows Installation Packages +* MacOS Disk Images +* Ruby Gems +* Maven Packages +* Hyperscaler marketplaces + +Not all of these apply to every self-hosted dev tool, but you should be thinking about these distribution and discovery methods. + +Using these free, anonymous distribution methods makes making money more complicated. The business model challenges of self-hostable software are discussed below. + +### Business Continuity + +Just as self-hostable software increases control for developers, it can do the same for businesses. Self-hosting lowers business continuity risk. If your company fails, is acquired or otherwise ceases to operate, customers can continue to run your product. + +Doing so isn't a long-term solution, since the product won't improve. But if a business depends on your solution for critical processes, they can keep it running as they evaluate alternatives. After they find a solution, they can migrate on their schedule, which will depend on integration effort, security risks, feature gaps, and other concerns. + +Contrast this with the scenario where the company behind a pure SaaS product fails or is acquired. Customers only retain access to the application or component due to the company's or acquirer's goodwill, respectively. That can be a tough pill to swallow if a component is critical. + +Finally, if a company wants to switch architectural components, self-hosting gives them options, because they have access to the data. Whereas SaaS products may or may not have full-featured export functionality. + +### Offline Or Limited Network Support + +When you have a self-hostable product, you can offer offline or limited network availability. Some use cases that benefit from this functionality include: + +* Better, more independent development environments. By using self-hostable components, developers can run the entire application, with all its components, running on their laptop without using mocks. While locations that are truly 100% offline are becoming rarer (thanks Starlink!) it is quite freeing to not rely on a remote API or service. Local services are quicker to stand up and easier to develop against. +* Locations that don't have internet connectivity or have limited internet connectivity, such as cruise ships and kiosks. +* High security scenarios handling sensitive data. + +If you have a self-hostable product that doesn't need internet connectivity to function, you can serve customers in these situations. + +### Your Customer's Budget + +If users are running a self-hostable architectural component in their own environment, they can control costs just as they do for their own application. + +This may include optimizing compute or network, turning off development environments, or scaling the solution up or down to meet their needs as they change seasonally or over time. + +### Your Budget + +Self-hostable software can also decrease your expenses. You sell the product, but they run it. The cost of operating it is borne by your customer. That control doesn't come for free, after all. + +If you have valuable functionality packaged and sold as self-hostable software, the margins can be quite nice. + +Whew. Hopefully you're convinced there's value in self-hostable software. Now, let's talk about what to consider when building a self-hostable architectural component. + +## What To Think About When Thinking About Building A Self-Hostable Product + +There's a lot to consider when building a self-hostable product. But front and center are your dependencies. + +Little girl running with text 'what does your product need to run?'. + +What dependencies does your product need to run? + +### Dependencies + +To make sure you minimize adoption friction, keep your required dependency list as small as possible. This makes your users' lives easier when deploying and operating the product. It will also make support easier. + +For instance, FusionAuth requires the following components if you are self-hosting: + +* A relational database +* An optional Elasticsearch or OpenSearch instance +* An optional proxy + +That's it. + +Let's contrast this with a SaaS application. Such applications don't carelessly incorporate unneeded components or datastores, but if the engineering team sees a need, they have flexibility to use them. It might be a remote message queue like Kafka, a specialized datastore like Pinecone, or even using S3. The tradeoff between functionality and the operational burden of these services can be evaluated and usage implemented. + +On the other hand, asking your customers to learn how to run a NoSQL datastore or message queue to use your product, imposes costs on them that they might not want to bear. Keep your required dependencies minimal. + +If you use a runtime like the JVM, bundle that as well. Doing so means you don't have to worry about version incompatibilities. FusionAuth bundles a known version of Java; nothing else is supported. Limiting the environment your application runs in will decrease support costs and increase customer satisfaction. + +If you can bundle all your dependencies with your product, that's even better. The more third party components you bundle, the tighter you can control your dependencies. + +This does come at the cost of flexibility. + +For example, consider a situation where your product depends on a relational database. If you don't bundle your database, deployment is simpler. Specify what database and versions you support and require your customer provide such a database. If they use a supported database, they can leverage database operating expertise across multiple applications. If they don't currently use a supported database, they will either not buy your product or they will expand their support. This means you want to target widely used solutions if you are not bundling. + +Which ones? Ask your potential customers. FusionAuth supports MySQL and PostgreSQL. If you are targeting enterprises, Oracle might be a better fit. If you are targeting embedded developers, SQLite is a good choice. + +With a database in particular, provide a schema management mechanism. If you support multiple databases, the schema you ship must support each one. Don't use advanced features of one database which are not available in others. You'll also want to test performance across supported versions of all databases. + +On the other hand, if you bundle the database, then you get the same benefits as bundling the runtime: more control, fewer compatibility issues, simpler installation. But the end user can't necessarily use their experience running databases for your product. + +For every third party component, think about whether you should bundle it and make life easier for your support team and your user at install time, or unbundle it to make operating your software easier for your self-hosting customer. + +#### The GPL + +If you are using any components or libraries licensed under the GPL or similar licenses, and you provide a binary to your customers, you must provide them with source code access as well. An example of this is the Java MySQL library, which is GPL. You can work around this by documenting how to download and install GPL dependencies. + +SaaS companies don't have to worry about the GPL, because they deliver features but not executable code. + +### Deployment Processes + +There is another technical hurdle when delivering self-hostable software. In contrast to SaaS, where the deployment process is often 'access this API' or 'log in to this application', with a self-hosted solution installation will be more complex. However, make installation and deployment of your product as simple as possible. + +Installation is the first experience a developer has with your software. Write detailed installation documentation. Ensure it covers all the paths you support. Above, the variety of supported distribution mechanisms was mentioned as a positive because you get free distribution of your tool via Maven, Docker, etc. Well, such methods are not totally free--the documentation you write and update to support them is the price you pay. + +The best installation experience is not documentation, it's installation scripts or other executable methods. Plan to support multiple installation paths. What particular methods on where you expect your customer to run your software, but you'll want to consider: + +* Hardware options such as virtual machines, containers and bare metal +* Operating systems, such as Windows, MacOS and Linux +* Delivery mechanisms such as Homebrew, RPMs and Docker +* Dependencies of the major components, including cloud versions + +You can sometimes abstract away hardware and operating system differences by using a VM like the JVM or a cross compiled language like golang. + +### The Network Is The Computer + +Access to the network is a dependency as well, even if it is often assumed. Unlike a SaaS solution, a self-hostable product can work without network access. + +Lean into this as a differentiator for your product. + +For technical reasons, you might require network access for some functionality. Capabilities such as retrieving a license or large amounts of data for advanced features. Downloading data to enable functionality requires network traffic. For example, FusionAuth has a corpus of breached passwords that is too large to ship as part of the self-hostable executable and is part of a paid feature. Build in robust retry logic so if a disk is full or a network is spotty, the data can still be downloaded. + +If you want to offer a true air-gapped experience, where no network access is required, then consider how to offer such features or verify a license is legitimate. + +### Tooling + +As a developer you are aware of the many tools and architectural components available to help you build a better product. These let you add easily add functionality such as: + +* understanding feature usage like HotJar +* finding bugs like Sentry +* feature flagging like LaunchDarkly +* notifications like Knock +* webhook processing like Svix + +Many of these solutions are built as SaaS products and served via APIs or SDKs expecting a network. Make sure you understand which type any tool you evaluate is. + +If it requires a network then, sorry, it is no longer an option. You can look to these tools for inspiration, but anything that expects to be used only in a SaaS is typically off-limits for a self-hostable product. + +### Releasing + +With a SaaS product, you can roll versions forward or backward relatively easily. This is often done using CI/CD. If it isn't perfectly automated, you have control over your server side code. Client side JavaScript may be cached and mobile apps will have a longer timeframe for updating, due to the review processes. Thanks Apple! + +With server side control, you can canary your changes and test in the real world. By sending a subset of users through new code paths, you can test if anything breaks without your entire user base being impacted, using tools like [GitHub scientist](https://github.com/github/scientist). With blue/green deployments you can, if your architecture and datastore support it, stand up an entirely separate application instance and shift traffic over to it, ever so gently. Or, for that matter, away from it, if the new code breaks something. + +Releasing a self-hostable product is different. + +A person with a fork and the headline 'it just hits different' and the words deployment process and dependencies above the fork. + +You have limited control over how and when your customers deploy. Remember, as a self-hostable product developer, you gave that power to them. But now you have limited ability to upgrade or downgrade the customer. + +So, when you release you need to be certain that the software has as few flaws as possible. You need rigorous testing across all the supported platforms, architectural components and deployment scenarios. This effort is above and beyond the feature and bugfix testing required of any solid software product, whether self-hostable or SaaS. + +You can work around some limitations, though. For instance, you could build in automatic upgrades like the Chrome browser. If you do this, handle network connectivity issues and ensure your users understand they are installing a self-hostable tool that will automatically upgrade. It's one thing to have that in your browser, but with a devtool like a message queue or database, it's riskier. Your developer customer must understand exactly what will happen to the components their application depends on. + +You can also build in support for upgrade rollbacks. Plan to spend time on the tooling and infrastructure to handle such changes in a robust, self-contained manner. + +An easier canarying option is offering beta or early access programs to let customers self-select into running versions of your software. These versions won't be available to the wider public nor will they be as bug-free as the generally available releases. Early access installs then happen at the discretion of your customer but still can provide valuable feedback. + +Release complexity means you must document and build systems such that your users have a clear idea of the impact of production upgrades. This is a common software problem and there are several approaches, including separating the control and data planes and maintaining strict n-1 version backwards compatibility. + +If you offer rollbacks and depend on a RDBMS, make sure schema changes don't destroy or degrade data that would make a rollback impossible. These include dropping a column or changing the column to a data type with less fidelity. + +Whatever your release strategy, don't forget the documentation! The developers who build on top of your self-hostable product will need it when they want to upgrade to take advantage of new functionality. + +### Release Communication + +In addition to the nuts and bolts of the release process and customer impact, you have to let your user base know about it. After all, if they don't know, they won't upgrade. + +You must communicate to the user that a new release of your package is available. At FusionAuth, we offer: + +* an RSS feed +* a generic new version email list +* a security focused email list +* automated or manual direct customer outreach (when appropriate) + +Another option is in-app nagging. Err, I mean reminding. Depending on how your users interact with your tool, this may be effective. However, if your tool is driven via API or command line, your thoughtful reminders may never be seen. + +Plan to spend some time building out appropriate communication mechanisms. + +### Performance + +Spend time testing performance across multiple environments before every release, to make sure there are no performance regressions. + +Dimensions to test include: + +* the amount of data in the system +* hardware variations +* dependency versions +* major architectural components you support (such as different databases) + +### Understanding Product Usage + +Ever used tooling which lets you know what features of your product are used by which users? Or which users in a new cohort are similar to users who purchased in the past? Such tooling helps SaaS vendors everywhere understand their customers better and operate more efficiently. Surprise! That tooling is not for you when you are working on a self-hostable product. Not unless you build it. + +Even if you do build it, be wary of reporting too much data, or any data that might make your customers uncomfortable. The more you report, the higher the impact on your users' privacy, and increased privacy is a valuable aspect of self-hosting. + +Capture only what you need to improve the product, be clear about what you are recording, and have a bright line between the usage data and private data stored in your system. For example, if you had a queue system with retries, recording that feature is being used is okay. But recording the entire message being retried is not. Be clear with your customers about what you are gathering and why. Offer them a chance to turn it off. + +Self-hosting customers can go beyond turning it off and block network access, which will disable usage statistics reporting. Acknowledging that up-front may lead to less data, but more trust. + +Users in the wild will have different resources and constraints than you might expect. When they run your software, they will find issues. Provide channels for manual and automated communication to capture these issues. You can then evaluate, prioritize and fix them. + +A meme with Jeff Goldblum stating 'users will find a way'. + +Some level of reporting may also be required to charge your customers, if usage based pricing is part of your business model. + +### Support + +Offering great customer support is more difficult with a self-hostable product than with a SaaS product. You are not only answering questions about how to use your product, but how to install and operate it. Some of these aspects may, as mentioned above, be niche or twist your product in unexpected ways. In fact developers often depend on undocumented but observable features; [see Hyrum's Law](https://www.hyrumslaw.com/). On top of all that, you also need to support heterogeneous deployment environments. + +In such a world, how do you stand up a testbed environment to replicate an issue? Often hopping on a call with a customer to see their deployment environment is more effective. + +The more you can bundle, the easier it is to replicate issues, because more of your product is known and in your control. + +Another wrinkle. Unless you go with the Chrome auto-upgrade model, you'll have customers and users using different versions. Think about how to support them. How old a version will you support? What if a customer is paying you a lot of money? + +#### LTS + +When a self-hostable product has enough versions, think about creating a long term support (LTS) plan similar to what Linux distributions or programming languages have. An LTS lets developers using your tool upgrade to certain versions and remain on them for a long time. Critical self-hostable products share a lot of similarities with programming languages. Your users may be hesitant to invest to regularly upgrade your product. New features can encourage upgrading, but once your product meets their needs, they won't bother. + +Since all your customers and users are not running the same version of your software, backporting bug fixes becomes a thing. Doing this increases development complexity, but offers more stability. Backports can include security fixes as well as selected bugs. + +What will you backport? What will you fix forward? Are there fixes that go only to LTSes? These are all questions you must confront at some point during your self-hostable tool journey. + +## Customer Enablement + +The above are topics you and your engineering team must consider when building a self-hostable product. But other than technical considerations, what else does your customer need to succeed? + +Operating software is difficult. That is why many people prefer SaaS solutions, which trade control for ease of operation. But often teams run segments of their application, whether in a cloud or on their own hardware. These applications operate at the scale and performance their company needs. So, for a certain subset of customers, the ability to have the control is worth the price of operating, since they are already doing it anyway. To help reduce that pain, enable your customer with great documentation. + +This includes detailed docs around: + +* installation +* scaling +* performance tuning +* monitoring +* troubleshooting +* system requirements +* infrastructure integrations +* tooling integrations +* upgrades + +Make these docs as thorough, accurate and complete as you can. They are part of the product experience. Clearly tag them with the applicable version, because capabilities and requirements change as software evolves. + +The possible combinations of how your software can be installed or operated is nearly infinite. Try to limit the effort by documenting common integrations and complementary software components. For instance, FusionAuth works with any proxy, but offers a [repository](https://github.com/fusionauth/fusionauth-contrib) with common configurations for NGINX, CloudFront, and more. + +Clearly document changes as part of release notes. You can use lo-fi methods for communicating changes such as adhering to [semantic versioning AKA SemVer](https://semver.org/) or high fidelity methods such as [old-style release notes](/docs/release-notes/). + +### Configuration Management + +Organizations that can confidently self-host critical infrastructure usually leverage configuration management or IaC. They want to configure your product or application via an API or tooling such as Terraform or Pulumi. + +Offering this functionality allows your customers to manage changes to your product in the same way they manage other changes to their application infrastructure. + +Terraform and/or OpenTofu are the biggest players in this space, but plan to have an answer to the question "how can we configure your product across environments and time"? + +### Professional Services + +Ah, the bane of every software company's gross margins. But, that aside, professional services help your customer implement your product quickly and effectively. It also can help you make money in early days, and help you understand customer problems that your product helps solve. + +If you don't want to build out your own professional services organization, build relationships with consulting companies who can. However, both parties in this experience want the other to bring them customers and make them money. These relationships can be difficult to kickstart, but can work if the time horizon is long enough and the mutual commitment is there. There's a reason value added resellers (VAR) have been a channel for software sales for decades. + +## What Kind Of Software Makes Sense + +Not every type of developer tool makes sense as a self-hostable solution. But if your product has three or more of the following attributes: + +* has an offline use case +* appeals to customers familiar with operating software +* solves a critical problem +* integrates with existing applications or components +* substitutes for an existing solution +* offers functionality used by a large number of applications + +Then a self-hostable solution might be just the ticket. + +## Monetization + +If you want to sell your self-hostable product, you have a few options. + +Jerry Maguire yelling 'show me the business model' into a telephone. + +* premium support, possibly with an SLA +* advanced features, access which can be managed by a software license +* hosting, where you run the product for the user and they consume it as a SaaS +* if your product is GPL or similar, selling the same code it under a commercial friendly license +* offering custom development or professional services, as mentioned above + +Each of these have strengths and weaknesses. + +Premium support is relatively easy to offer. You can allow customers to pay for access to a Slack channel, ticketing system or email address that has priority over other support mechanisms. However, this requires employees, hiring and training. It doesn't scale as well as other parts of a software business. For a self-hostable product, support can be complex to offer, as discussed above. + +Advanced features can scale revenue without increasing costs, but require significant upfront investment to build out. They also require a licensing system. This typically requires network access, which removes the offline benefits. You also want to make sure the core product is usable without the advanced features. Pick carefully which features are advanced and which are not. + +With hosting, a single tenant SaaS is a natural fit for a self-hostable product. You can offer customer controlled upgrades or a fully managed SaaS, depending on customer needs and integration interface stability. However, this isn't free money. You are now responsible for uptime, performance and other aspects of operating software. + +A 'you host or we host' option allows you to offer some of the benefits of SaaS without losing all the benefits of a self-hosted solution. This can be appealing for customers. They can either start out self-hosted for control or cost and migrate to SaaS when they are ready, or they can start out SaaS to get up and running quickly and migrate to self-hosted when they have a team ready to operate the software and want more control. + +Offering a more commercial friendly secondary license is a great way to make money if your license is problematic with commercial usage. It worked well for MySQL. + +Custom development and professional services offer an income stream that assists adoption and ensures customer success. But you have to hire and staff that team, and the margins, like support, are lower. + +Your business model may change as your self-hostable software improves. For instance, initially you may want to do custom development, but if you then build out a hosting offering, you might downplay the custom development in favor of the higher margin hosting business. + +Whatever you do, communicate the changes to your customers clearly. + +### What About Open Source + +A self-hostable architectural component *can* be open source software (OSS), but that is not required. OSS has many benefits: + +* increased community feedback +* bug fixes +* lower-friction adoption +* the OSS halo + +There are alternatives too. You can offer a free-as-in-beer version of your software. By doing so, you gain many of the marketing and distribution benefits of open source without business model risks. You can also use a non-OSS license, such as the Business Source License. + +The risks of offering your product as open source include: + +* others reselling your product +* forks if the community disagrees with product decisions +* limited monetization options + +On the other hand, if you are not OSS, you won't get the halo effect, you'll have a harder time building trust, you won't get as many contributions, and building a community is more difficult. + +There have been enough re-licenses recently, such as Elasticsearch and Terraform, that developers know that just because a product is open source at the beginning doesn't mean it will stay that way. Leaning into the argument that you are building a sustainable business may be enough for some users, but for others nothing short of full OSS will satisfy. + +That's okay, you don't need to build a product for everyone. Either way, be prepared to defend your decision. + +## Conclusion + +There is unique value in building a self-hostable developer tool. + +* You can serve a certain kind of customer who can and wants to operate their own infrastructure. +* There are use cases that you can meet. +* You can meet technical and business needs in a way that SaaS can't. +* There are a wider set of distribution channels available. + +There are corresponding technical challenges as well: + +* Customers need supporting tooling and documentation. +* You need to minimize dependencies, but not too much. +* Support needs to handle heterogeneous environments and older versions. +* Engineering needs to adjust to releases that can't be rolled back and more limited tooling. + +Finally, you have a variety of monetization options, with varying complexity and margins. + +Self-hosting is making a comeback for customers who value control, data locality and have the skills to operate software. + +Now you know what to think about when building robust self-hostable software. diff --git a/astro/src/content/blog/circleboom-fusionauth-single-sign-on.mdx b/astro/src/content/blog/circleboom-fusionauth-single-sign-on.mdx index 57deb87743..7657c8f664 100644 --- a/astro/src/content/blog/circleboom-fusionauth-single-sign-on.mdx +++ b/astro/src/content/blog/circleboom-fusionauth-single-sign-on.mdx @@ -24,7 +24,7 @@ Atakan Eser is a FusionAuth community member and co-founder and CTO at Circleboo We have two products on the market: * Circleboom Twitter Management Tool enables users, brands, and SMBs to grow and strengthen their Twitter Accounts. -* Circleboom Publish Tool helps you design, plan, automate and post social media posts to major networks like Linkedin, Twitter, Facebook, Instagram, and Google My Business. +* Circleboom Publish Tool helps you design, plan, automate and post social media posts to major networks like LinkedIn, Twitter, Facebook, Instagram, and Google My Business. **Dan:** Tell me about your work as a CTO at Circleboom. diff --git a/astro/src/content/blog/deactivating-reactivating-deleting-user-fusionauth-python.mdx b/astro/src/content/blog/deactivating-reactivating-deleting-user-fusionauth-python.mdx index 8f8e74a53f..5e6d2c1bc8 100644 --- a/astro/src/content/blog/deactivating-reactivating-deleting-user-fusionauth-python.mdx +++ b/astro/src/content/blog/deactivating-reactivating-deleting-user-fusionauth-python.mdx @@ -36,7 +36,7 @@ Did you know that you can deactivate, reactivate, or delete a user within your a - [FusionAuth-Client Python Library](/docs/sdks/python) - [Python](https://www.python.org/downloads/) (this tutorial uses Python 3.7.1) - [Python PIP Package Manager](https://pypi.org/project/pip/) -- [Python3 VENV Virtual Environment Package](https://docs.python.org/3/library/venv.html) +- [Python3 venv Virtual Environment Package](https://docs.python.org/3/library/venv.html) - Text Editor or [Favorite Python IDE](https://atom.io/) - Terminal Access - Web Browser @@ -51,11 +51,11 @@ Today we will be exploring three FusionAuth-Client functions: `deactivate_user`, ## Verifying server applications, libraries, and dependencies -If you completed our first FusionAuth Python tutorial, you should already have FusionAuth, Python, PIP, VENV, and the FusionAuth Python client library already installed and running. If you're unsure or new to FusionAuth, let's verify that these are working before we get started. +If you completed our first FusionAuth Python tutorial, you should already have FusionAuth, Python, pip, venv, and the FusionAuth Python client library already installed and running. If you're unsure or new to FusionAuth, let's verify that these are working before we get started. ## FusionAuth server UI -Open up a web browser and go to http://localhost:9011 or the web address pointing to your FusionAuth installation. If it's not running, start the Fusionauth Search and Application services. You can do this on DEB or RPM Linux servers with: +Open up a web browser and go to http://localhost:9011 or the web address pointing to your FusionAuth installation. If it's not running, start the FusionAuth Search and Application services. You can do this on DEB or RPM Linux servers with: ```zsh sudo service fusionauth-search start @@ -64,7 +64,7 @@ sudo service fusionauth-app start _Read our documentation for [installation details](/docs/get-started/download-and-install/fast-path) for other platforms._ -For this tutorial I'm going to use [VENV](https://docs.python.org/3/library/venv.html), Python's virtual environment library, for app development and testing. If you have VENV installed in a folder called `venv` on your server like we did in the last tutorial, you can browse to the folder and start the virtual environment server with: +For this tutorial I'm going to use [venv](https://docs.python.org/3/library/venv.html), Python's virtual environment library, for app development and testing. If you have venv installed in a folder called `venv` on your server like we did in the last tutorial, you can browse to the folder and start the virtual environment server with: ```zsh source venv/bin/activate @@ -327,7 +327,7 @@ Didn't find your error here? Visit [the User API docs](/docs/apis/users) for mor ## Summary -This was a quick introduction to user management in FusionAuth with Python. We explored how to deactivate, reactivate, and delete a user with some examples of client responses that our application can call from the FusionAuth API. Be sure to check out some of our [other quickstarts](/docs/quickstarts/), explore our repos on [Github](https://github.com/FusionAuth/), and take a look at what else you can do with FusionAuth's [RESTful APIs](/docs/apis/). +This was a quick introduction to user management in FusionAuth with Python. We explored how to deactivate, reactivate, and delete a user with some examples of client responses that our application can call from the FusionAuth API. Be sure to check out some of our [other quickstarts](/docs/quickstarts/), explore our repos on [GitHub](https://github.com/FusionAuth/), and take a look at what else you can do with FusionAuth's [RESTful APIs](/docs/apis/). ## Learn more about FusionAuth diff --git a/astro/src/content/blog/dealcloser-saves-developer-time-with-fusionauth.mdx b/astro/src/content/blog/dealcloser-saves-developer-time-with-fusionauth.mdx index f200bdcc97..395c898e30 100644 --- a/astro/src/content/blog/dealcloser-saves-developer-time-with-fusionauth.mdx +++ b/astro/src/content/blog/dealcloser-saves-developer-time-with-fusionauth.mdx @@ -14,7 +14,7 @@ Alex Trauzzi is a Developer & Software Architect building dealcloser, a transact {/* more */} -[dealcloser](https://www.dealcloser.com/) was originally using Auth0 to authenticate internal and external users, but they needed a solution that better fit their enterprise needs and they didn't want to build it inhouse. They were also faced with a unique situation: many of their users needed to connect to their application without internet access. But dealcloser wanted to leverage existing standards such as OpenID Connect (OIDC). +[dealcloser](https://www.dealcloser.com/) was originally using Auth0 to authenticate internal and external users, but they needed a solution that better fit their enterprise needs and they didn't want to build it in-house. They were also faced with a unique situation: many of their users needed to connect to their application without internet access. But dealcloser wanted to leverage existing standards such as OpenID Connect (OIDC). > "[While we were looking for a solution], [a]irgapping was the main driver. [The] biggest thing was to preserve that OpenID Connect compatibility." diff --git a/astro/src/content/blog/disclosure-conference-report.mdx b/astro/src/content/blog/disclosure-conference-report.mdx index 53ead09abc..b87350055e 100644 --- a/astro/src/content/blog/disclosure-conference-report.mdx +++ b/astro/src/content/blog/disclosure-conference-report.mdx @@ -13,7 +13,7 @@ Disclosure is an annual, vendor agnostic security conference. I attended the 202 {/* more */} -Here's the [agenda for the 2020 conference](https://www.disclosureconference.com/#agenda). All the videos are available on [youtube](https://www.youtube.com/playlist?list=PLshTZo9V1-aF-rS-TyCYgApAEAQI4q2qe). +Here's the [agenda for the 2020 conference](https://www.disclosureconference.com/#agenda). All the videos are available on [YouTube](https://www.youtube.com/playlist?list=PLshTZo9V1-aF-rS-TyCYgApAEAQI4q2qe). There were two tracks; one for developers and one for security folks. Being a developer, I watched videos on the former track. diff --git a/astro/src/content/blog/dotnet-templates.mdx b/astro/src/content/blog/dotnet-templates.mdx index 5003fd5d88..d4dfa35880 100644 --- a/astro/src/content/blog/dotnet-templates.mdx +++ b/astro/src/content/blog/dotnet-templates.mdx @@ -15,7 +15,7 @@ Reduce the overhead associated with customer authentication and authorization wh {/* more */} ## Introduction -*Templates for nothin' and your security for free.* +*Templates for nothing and your security for free.* Literally. The [FusionAuth Templates for Microsoft .NET](https://marketplace.visualstudio.com/items?itemName=FusionAuth.FusionAuthVSTemplates) are free to use and so is the self-hosted [Community Plan](/pricing?step=plan&hosting=self-hosting) of FusionAuth. diff --git a/astro/src/content/blog/download-install-linux-tutorial.mdx b/astro/src/content/blog/download-install-linux-tutorial.mdx index a8cc54df9c..dd51e64065 100644 --- a/astro/src/content/blog/download-install-linux-tutorial.mdx +++ b/astro/src/content/blog/download-install-linux-tutorial.mdx @@ -35,7 +35,7 @@ The easiest way to get up and running on Linux will be to use the Linux [Fast Pa The Fast Path installation may not be right for everyone, it is generally the most useful to get up and running quickly in a development environment. In this article we will be performing a manual installation using the Debian package. This installation method may be more suitable for a production instance of FusionAuth. -If you're using an RPM based Linux distribution, the steps will be nearly identical, you may follow this guide and substitute the RPM package for the debian using the `rpm -i` installation command instead of the `dpkg -i` used in this example. +If you're using an RPM based Linux distribution, the steps will be nearly identical, you may follow this guide and substitute the RPM package for the Debian using the `rpm -i` installation command instead of the `dpkg -i` used in this example. FusionAuth may also be run in a Docker container or a Kubernetes cluster, review our installation guide for more information. If you're still on board for a package based Linux installation, then let's do this. diff --git a/astro/src/content/blog/download-install-mac-tutorial.mdx b/astro/src/content/blog/download-install-mac-tutorial.mdx index 9a436a39a2..b0f26ad4f6 100644 --- a/astro/src/content/blog/download-install-mac-tutorial.mdx +++ b/astro/src/content/blog/download-install-mac-tutorial.mdx @@ -9,7 +9,7 @@ tags: macos, fusionauth, download excerpt_separator: "{/* more */}" --- -Designed to save developer time and effort, there are only a few simple steps to download and install FusionAuth in your test or production environment. The following tutorial will explain how to install FusionAuth on your Macbook and be up and running in just a few minutes. This is one aspect that makes FusionAuth unique. Most existing identity technologies have a complex hierarchy of realms, principals, and distinguished names that restricts where they can be installed and requires extensive configuration. FusionAuth will install and run on a wide variety of systems including: +Designed to save developer time and effort, there are only a few simple steps to download and install FusionAuth in your test or production environment. The following tutorial will explain how to install FusionAuth on your MacBook and be up and running in just a few minutes. This is one aspect that makes FusionAuth unique. Most existing identity technologies have a complex hierarchy of realms, principals, and distinguished names that restricts where they can be installed and requires extensive configuration. FusionAuth will install and run on a wide variety of systems including: {/* more */} @@ -22,7 +22,7 @@ Designed to save developer time and effort, there are only a few simple steps to Before you start installing onto macOS, do a quick check on your system to make sure it meets the minimum requirements. You will need: -- A Macbook running macOS 10.8 or newer +- A MacBook running macOS 10.8 or newer - A MySQL or PostgreSQL database It is not necessary that the database be installed locally, as long as you can connect using a JDBC URL, FusionAuth will be able to utilize the database. diff --git a/astro/src/content/blog/easy-integration-fusionauth-nodejs.mdx b/astro/src/content/blog/easy-integration-fusionauth-nodejs.mdx index 863d51c554..496d49e152 100644 --- a/astro/src/content/blog/easy-integration-fusionauth-nodejs.mdx +++ b/astro/src/content/blog/easy-integration-fusionauth-nodejs.mdx @@ -14,7 +14,7 @@ There are a variety of strategies for authentication in Node.js apps, but none p {/* more */} -We'll assume that you are using a unix command-line application like Power Shell on Windows, Terminal on macOS, or a standard terminal on Linux. You will also need **cURL** or some means of creating `GET` and `POST` requests to your localhost. I like REST clients such as [Insomnia](https://insomnia.rest/ "Get Insomnia") or [Postman](https://www.getpostman.com/ "Get Postman"). Let's get coding! +We'll assume that you are using a UNIX command-line application like Power Shell on Windows, Terminal on macOS, or a standard terminal on Linux. You will also need **cURL** or some means of creating `GET` and `POST` requests to your localhost. I like REST clients such as [Insomnia](https://insomnia.rest/ "Get Insomnia") or [Postman](https://www.getpostman.com/ "Get Postman"). Let's get coding! -Inside our root directory, we will create another folder named `server` and initialize a NodeJS application in it. Run the following command in your root application directory: +Inside our root directory, we will create another folder named `server` and initialize a Node.js application in it. Run the following command in your root application directory: ```shell $ mkdir server @@ -201,13 +201,13 @@ $ npm install express cors morgan nodemon dotenv axios express-session query-str We installed a lot of packages, so let's look at them: -- [cors](https://www.npmjs.com/package/cors) - This is a middleware that helps us to make cross-origin requests. -- [morgan](https://www.npmjs.com/package/morgan) - This is an HTTP request logger middleware for node.js, you can use this for production. -- [nodemon](https://www.npmjs.com/package/nodemon) - Restarting the server every time we make a change is a hassle. Nodemon automatically restarts the node application when file changes are detected. -- [dotenv](https://www.npmjs.com/package/dotenv) - This loads environment variables from an `.env` file. We will use this to secure our API key and client configuration. -- [axios](https://www.npmjs.com/package/axios) - This allows us to make HTTP requests. -- [express-session](https://www.npmjs.com/package/express-session) - This stores our access token securely. -- [query-string](https://www.npmjs.com/package/query-string) - This is used to stringify form data that we send using `axios`. +- [`cors`](https://www.npmjs.com/package/cors) - This is a middleware that helps us to make cross-origin requests. +- [`morgan`](https://www.npmjs.com/package/morgan) - This is an HTTP request logger middleware for node.js, you can use this for production. +- [`nodemon`](https://www.npmjs.com/package/nodemon) - Restarting the server every time we make a change is a hassle. `nodemon` automatically restarts the node application when file changes are detected. +- [`dotenv`](https://www.npmjs.com/package/dotenv) - This loads environment variables from an `.env` file. We will use this to secure our API key and client configuration. +- [`axios`](https://www.npmjs.com/package/axios) - This allows us to make HTTP requests. +- [`express-session`](https://www.npmjs.com/package/express-session) - This stores our access token securely. +- [`query-string`](https://www.npmjs.com/package/query-string) - This is used to stringify form data that we send using `axios`. Since we have installed `nodemon`, to use it inside `package.json` simply add the following scripts: @@ -255,7 +255,7 @@ require("dotenv").config(); We can then read environment variables by writing `process.env.` in front of the environment variable's name whenever we need them in our code. Here is the sample code for an Express server that makes use of all our installed packages: diff --git a/astro/src/content/blog/securing-asp-netcore-razor-pages-app-with-oauth.mdx b/astro/src/content/blog/securing-asp-netcore-razor-pages-app-with-oauth.mdx index c3d53a9103..d305add515 100644 --- a/astro/src/content/blog/securing-asp-netcore-razor-pages-app-with-oauth.mdx +++ b/astro/src/content/blog/securing-asp-netcore-razor-pages-app-with-oauth.mdx @@ -78,7 +78,7 @@ I can hit `control-C` to exit out of this application. I also like to open up a dotnet publish -r win-x64 && bin/Debug/netcoreapp3.1/win-x64/publish/SampleApp.exe ``` -If I visit `http://localhost:5000` I'm redirected to an https address and get a warning from my browser. While that might make sense in production, unless we terminate TLS before traffic gets to this application, we don't need this behavior in development. To avoid this, simply remove `app.UseHttpsRedirection();` from `Startup.cs`, which is the main configuration file for our web application. +If I visit `http://localhost:5000` I'm redirected to an HTTPS address and get a warning from my browser. While that might make sense in production, unless we terminate TLS before traffic gets to this application, we don't need this behavior in development. To avoid this, simply remove `app.UseHttpsRedirection();` from `Startup.cs`, which is the main configuration file for our web application. We'll also want to add a page to be secured, which we'll aptly call "Secure". Add `Secure.cshtml` and `Secure.cshtml.cs` to the `SampleApp/Pages` directory. Give them the following content: @@ -288,7 +288,7 @@ namespace SampleApp } ``` -Let's go through some of the more interesting parts. First, we're setting up our authentication including the scheme and challenge method. We'll be using cookies to store our authentication information and "oidc" for our authentication provider, which is defined further below. +Let's go through some of the more interesting parts. First, we're setting up our authentication including the scheme and challenge method. We'll be using cookies to store our authentication information and `oidc` for our authentication provider, which is defined further below. ```csharp // ... services.AddAuthentication(options => diff --git a/astro/src/content/blog/securing-golang-microservice.mdx b/astro/src/content/blog/securing-golang-microservice.mdx index a3a8c34aee..4886edc114 100644 --- a/astro/src/content/blog/securing-golang-microservice.mdx +++ b/astro/src/content/blog/securing-golang-microservice.mdx @@ -36,7 +36,7 @@ So, let's get started! ## Implementing the JWT endpoint with a go module -In this section, we will be creating an endpoint that generates a JWT and then returns it back to the client. All the code is available on [Github](https://github.com/FusionAuth/fusionauth-example-go-jwt-microservices) if you want to clone it and follow along. +In this section, we will be creating an endpoint that generates a JWT and then returns it back to the client. All the code is available on [GitHub](https://github.com/FusionAuth/fusionauth-example-go-jwt-microservices) if you want to clone it and follow along. We will be using the HMAC algorithm for encrypting the token. @@ -92,7 +92,7 @@ You'll need to set this value every time you start a new terminal and want to ru ### Generate the JWT -To generate the token, we need to create a function called `GetJWT`. In the function, we start by initializing a new instance of `JWT` using the `New` method provided by our jwt library. +To generate the token, we need to create a function called `GetJWT`. In the function, we start by initializing a new instance of `JWT` using the `New` method provided by our JWT library. We need to configure the signing method algorithm to be `HS256` while initializing the token. There are multiple different supported signing methods, but we are using HMAC, a symmetric signing algorithm, because it is the simplest to implement. @@ -377,7 +377,7 @@ import ( // ... ``` -Then, we need to wrap our index endpoint with the jwt middleware. We'll also listen on port 9001. +Then, we need to wrap our index endpoint with the JWT middleware. We'll also listen on port 9001. ```go // ... @@ -511,7 +511,7 @@ Using a token in this manner to secure microservices is widely used as it is a s ## Go further -All the code is available on [Github](https://github.com/FusionAuth/fusionauth-example-go-jwt-microservices). If you want to play around with JWTs and the golang microservices you built here, you could: +All the code is available on [GitHub](https://github.com/FusionAuth/fusionauth-example-go-jwt-microservices). If you want to play around with JWTs and the golang microservices you built here, you could: * [Set up FusionAuth in 5 minutes](/docs/quickstarts/5-minute-setup-guide) and have it generate the JWTs when a user logs in. * Learn how to [secure golang applications with OAuth](/blog/2020/10/22/securing-a-golang-app-with-oauth). diff --git a/astro/src/content/blog/securing-react-native-with-oauth.mdx b/astro/src/content/blog/securing-react-native-with-oauth.mdx index 5992741fbd..ad96be282b 100644 --- a/astro/src/content/blog/securing-react-native-with-oauth.mdx +++ b/astro/src/content/blog/securing-react-native-with-oauth.mdx @@ -24,7 +24,7 @@ This is a lot, but the ride will be fun. Ready to get going? Here's what you need to get started: -* NodeJS version >= 18.0 +* Node.js version >= 18.0 * VSCode or any other text editor * `git` * `npx` diff --git a/astro/src/content/blog/securing-your-api.mdx b/astro/src/content/blog/securing-your-api.mdx index aef5be7802..9fed7051aa 100644 --- a/astro/src/content/blog/securing-your-api.mdx +++ b/astro/src/content/blog/securing-your-api.mdx @@ -168,7 +168,7 @@ The OAuth standards can be used to implement decentralized API key verification. | ---- | ---- | ---- | | client | client | n/a | | central authority | authorization server | AS | -| api server | resource server | RS | +| API server | resource server | RS | | API key | access token | AT | For clarity, this post will continue to use the non-OAuth terms, such as API server. diff --git a/astro/src/content/blog/see-you-at-gdc.mdx b/astro/src/content/blog/see-you-at-gdc.mdx index e073aea48c..cfa4c9e2f4 100644 --- a/astro/src/content/blog/see-you-at-gdc.mdx +++ b/astro/src/content/blog/see-you-at-gdc.mdx @@ -20,7 +20,7 @@ The FusionAuth team will be among them, and we'd love to see you. While you can use FusionAuth to provide authentication, authorization and user management across many sectors (and our [customers do run the gamut](/customers-partners)), FusionAuth has specific features useful for game developers, including: * integration with [username and chat profanity filtering](https://cleanspeak.com) -* [Identity Providers](/docs/lifecycle/authenticate-users/identity-providers/) offering out of the box single sign-on with major gaming platforms such as XBox, Steam, and PS5 +* [Identity Providers](/docs/lifecycle/authenticate-users/identity-providers/) offering out of the box single sign-on with major gaming platforms such as Xbox, Steam, and PS5 * the ability to scale to millions of user profiles and thousands of logins per second We also have a number of customers in the gaming space. While it's nice to hop on a video chat with them any time to support their implementations, it'll be great to meet in person, share a beverage, and chat face to face. diff --git a/astro/src/content/blog/see-you-at-kcdc-2023.mdx b/astro/src/content/blog/see-you-at-kcdc-2023.mdx index e2c33a0e18..40a7ca6392 100644 --- a/astro/src/content/blog/see-you-at-kcdc-2023.mdx +++ b/astro/src/content/blog/see-you-at-kcdc-2023.mdx @@ -15,7 +15,7 @@ FusionAuth is excited to be attending and sponsoring the Kansas City Developers KCDC brings together developers, software engineers, UX designers, product managers, entrepreneurs, and more for a unique opportunity to network and learn from each other. It's community driven and while they accept corporate sponsors, it has that community feel. -As far as content goes, there are more than 180 technical sessions covering topics from architecture to cloud to javascript to human skills to security and UI/UX design. Whew! +As far as content goes, there are more than 180 technical sessions covering topics from architecture to cloud to JavaScript to human skills to security and UI/UX design. Whew! FusionAuth team member Dan Moore will be giving a few talks (see more below), but other interesting sessions include: diff --git a/astro/src/content/blog/single-sign-on-django-fusionauth.mdx b/astro/src/content/blog/single-sign-on-django-fusionauth.mdx index 316cb799fc..d03e2f0a7e 100644 --- a/astro/src/content/blog/single-sign-on-django-fusionauth.mdx +++ b/astro/src/content/blog/single-sign-on-django-fusionauth.mdx @@ -135,7 +135,7 @@ To test whether the Django demo SSO application is up and running as expected, o ![The initial Django application.](/img/blogs/single-sign-on-django-fusionauth/testing-django-application.png) -Now you need to terminate the running application by hitting "CTRL+C" while you are in the terminal screen running the Django application. Later in this tutorial, you'll start this Django application again after completing other setup instructions. +Now you need to terminate the running application by hitting "Ctrl+C" while you are in the terminal screen running the Django application. Later in this tutorial, you'll start this Django application again after completing other setup instructions. ### Configure FusionAuth @@ -273,7 +273,7 @@ Clicking "Login" will take you to the FusionAuth login page. Input the admin's e ![Successful single sign-on login.](/img/blogs/single-sign-on-django-fusionauth/successful-sso-based-login.png) -Now you have a working Django application that has been authenticated by the user created in FusionAuth. On successful sign-in to the integrated OAuth and identity provider, the user is automatically signed in in the Django application. +Now you have a working Django application that has been authenticated by the user created in FusionAuth. On successful sign-in to the integrated OAuth and identity provider, the user is automatically signed in to the Django application. ## Conclusion diff --git a/astro/src/content/blog/single-sign-on-laravel-fusionauth.mdx b/astro/src/content/blog/single-sign-on-laravel-fusionauth.mdx index a5f5942619..a59939ed90 100644 --- a/astro/src/content/blog/single-sign-on-laravel-fusionauth.mdx +++ b/astro/src/content/blog/single-sign-on-laravel-fusionauth.mdx @@ -188,7 +188,7 @@ Then, go to your `database/migrations` folder, where you'll find a file there wi Edit that file to add three new columns to the `users` table: `fusionauth_id`, `fusionauth_access_token` and `fusionauth_refresh_token` and allow `NULL` values in the `password` column. You'd want to save the access token in your database to make requests to the FusionAuth API or other APIs that accept FusionAuth access tokens on behalf of the user. The refresh token is used to exchange an expired access token with a new one (but you'd still have to implement this yourself, as Socialite still doesn't do it). This way, users don't need to log in again to your FusionAuth instance as long as the refresh token is still valid. - + ```php If you cloned our [GitHub repository](https://github.com/FusionAuth/fusionauth-example-laravel-single-sign-on), you can just copy the contents from [laravel/routes.php](https://github.com/FusionAuth/fusionauth-example-laravel-single-sign-on/blob/main/laravel/routes.php). + ```php If you have trouble with these settings, be sure to refer to the [official Discord documentation](https://discord.com/developers/docs/topics/oauth2). Again, these URLS have changed in the past, and may change again in the future. @@ -124,7 +124,7 @@ Click the "sign in" button, which will take you to your FusionAuth instance’s After clicking "Authorize", you’ll be taken back to the FusionAuth Example Application, where you’ll be presented with a response object containing your user data from Discord. -If you see this, you have successfully authenticated with FusionAuth via Discord. Ta-da! +If you see this, you have successfully authenticated with FusionAuth via Discord. Woo-hoo! ## Wrapping up diff --git a/astro/src/content/blog/single-sign-on-with-drupal.mdx b/astro/src/content/blog/single-sign-on-with-drupal.mdx index 4c43b1e5e2..b46a9de1f5 100644 --- a/astro/src/content/blog/single-sign-on-with-drupal.mdx +++ b/astro/src/content/blog/single-sign-on-with-drupal.mdx @@ -69,13 +69,13 @@ Once you are at the FusionAuth dashboard, navigate to "Applications" and then cl In the application creation page, change the app's name to something recognizable, for example, "Drupal". This name is displayed in the application list in the FusionAuth dashboard. -In the "OAuth" tab, enter `/openid-connect/generic` in the "Authorized redirect URL" field. Replace `` with the URL of your drupal site. Below it is `http://35.227.12.233` but that's specific to my setup. +In the "OAuth" tab, enter `/openid-connect/generic` in the "Authorized redirect URL" field. Replace `` with the URL of your Drupal site. Below it is `http://35.227.12.233` but that's specific to my setup. -![Configuring the OAuth tab of the drupal application.](/img/blogs/single-sign-on-drupal/add-application-oauth-tab.png) +![Configuring the OAuth tab of the Drupal application.](/img/blogs/single-sign-on-drupal/add-application-oauth-tab.png) By default, FusionAuth doesn't allow users to register a new account. This is useful when you have an internal tool where admins manually create the accounts. But if you want the users to be able to register an account, you need to turn on self-service registration in the "Registration" tab. You can also customize which fields are required by turning them on. -![Configuring the Registration tab of the drupal application.](/img/blogs/single-sign-on-drupal/add-application-registration-tab.png) +![Configuring the Registration tab of the Drupal application.](/img/blogs/single-sign-on-drupal/add-application-registration-tab.png) Save the application by clicking the blue "Save" button in the top right corner of the page. This redirects you back to the applications list, where you can click the tiny view button next to the newly created application. diff --git a/astro/src/content/blog/soc2-matrix.mdx b/astro/src/content/blog/soc2-matrix.mdx index 10cec96e74..a53700fc46 100644 --- a/astro/src/content/blog/soc2-matrix.mdx +++ b/astro/src/content/blog/soc2-matrix.mdx @@ -66,7 +66,7 @@ Here’s a high-level set of pros and cons for each of the vendors we evaluated | Company | Pros | Cons | |-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Trustcloud |
  • Incumbent
  • Easy to remain with
  • |
  • Integrations are not as robust as other tools
  • Not able to share evidence across controls
  • Clunky UI and navigation
  • | +| TrustCloud |
  • Incumbent
  • Easy to remain with
  • |
  • Integrations are not as robust as other tools
  • Not able to share evidence across controls
  • Clunky UI and navigation
  • | | Vanta |
  • Lots of integrations
  • Customer portal
  • |
  • Expensive relative to others
  • No way to view employee or vendor to vendor permissions
  • | | Secureframe |
  • Necessary integrations, OAuth
  • Employee and vendor access visibility
  • Customer portal
  • Ability to share evidence across controls
  • Good UI
  • Reasonable pricing
  • Slack nudges for evidence collection
  • Auto-answer vendor questionnaires
  • |
  • Missing some integrations
  • Notification of failure feature not yet released (EOY23)
  • | | Trustero |
  • Engineering-forward tool (APIs, CLI, use version control)
  • Aim to eliminate "thrash"
  • Tools to streamline audit
  • |
  • Doesn't have a lot of the integrations we'd like and pushed back on why we'd even want some of them
  • Service account integrations
  • | diff --git a/astro/src/content/blog/softozor-fusionauth-hasura-kubernetes.mdx b/astro/src/content/blog/softozor-fusionauth-hasura-kubernetes.mdx index a9443b15c1..a9b5d541dc 100644 --- a/astro/src/content/blog/softozor-fusionauth-hasura-kubernetes.mdx +++ b/astro/src/content/blog/softozor-fusionauth-hasura-kubernetes.mdx @@ -17,13 +17,13 @@ Dr. Laurent Michel is a FusionAuth community member and product owner at Softozo ------- -**Dan:** Tell me a bit about your work as a developer, software architect and product owner as well as what softozor does. +**Dan:** Tell me a bit about your work as a developer, software architect and product owner as well as what Softozor does. **Laurent:** Softozor is a very little company made up by me, my brother and a few friends. Currently, we work together in our free time. We are mostly physicists and mathematicians. My brother and I work in software development companies. Our friends are teachers. One of the goals of the Softozor company is to produce educational video games. In order to achieve that goal, we need money, which we are trying to earn with software development projects. Currently, we are developing an e-commerce platform helping craftsmen to sell their products and make them visible in the regions they are living in. A craftsman can be a farmer, a caterer, a baker, a butcher, etc. I am the company's official leader. I energize the roles of developer, architect, and product owner. I am the only one team member with the product owner role. The roles of developer and architect are taken by other members of the team. Every architectural decision is discussed in the team so that we get as much insight as possible into the possible problems that we might face during the development. This way we also spread the knowledge of everyone across the whole team. -Nowadays, I essentially develop in C++, C# (.Net / WPF), javascript (VueJS), and python (mainly to write acceptance tests). +Nowadays, I essentially develop in C++, C# (.Net / WPF), JavaScript (VueJS), and python (mainly to write acceptance tests). > The ease of installation and the set of features were the most decisive motivations to use [FusionAuth]. @@ -53,7 +53,7 @@ function populate(jwt, user, registration) { } ``` -In our software, JWTs are used on the admin frontend, where the craftsmen can define their inventory, shop managers can monitor sellings, etc. On the shop itself, we are not using JWTs yet, because we aren't supporting customer accounts yet, which would be the only use case where JWTs would be useful. Indeed, the whole shopping frontend is generated following the JAMStack philosophy. Therefore, the sensitive information is gathered from the hasura API with special rights on our CI/CD server and injected into the shop frontend whenever necessary. That leaves users of that frontend with (almost) no way to hack into our API. +In our software, JWTs are used on the admin frontend, where the craftsmen can define their inventory, shop managers can monitor sellings, etc. On the shop itself, we are not using JWTs yet, because we aren't supporting customer accounts yet, which would be the only use case where JWTs would be useful. Indeed, the whole shopping frontend is generated following the JAMstack philosophy. Therefore, the sensitive information is gathered from the hasura API with special rights on our CI/CD server and injected into the shop frontend whenever necessary. That leaves users of that frontend with (almost) no way to hack into our API. **Dan:** What problems did we solve for you? And how were you solving them before FusionAuth? @@ -71,7 +71,7 @@ In our software, JWTs are used on the admin frontend, where the craftsmen can de **Dan:** How do you run FusionAuth (k8s, standalone tomcat server, behind a proxy, etc)? -**Laurent:** We run FusionAuth on a Kubernetes (k8s) cluster. It is completely hidden behind our hasura api. We write hasura actions that interact with FusionAuth. +**Laurent:** We run FusionAuth on a Kubernetes (k8s) cluster. It is completely hidden behind our hasura API. We write hasura actions that interact with FusionAuth. > I'd say it saved us something like one man-year of time. diff --git a/astro/src/content/blog/spring-and-fusionauth.mdx b/astro/src/content/blog/spring-and-fusionauth.mdx index eced0330be..23876b908b 100644 --- a/astro/src/content/blog/spring-and-fusionauth.mdx +++ b/astro/src/content/blog/spring-and-fusionauth.mdx @@ -114,7 +114,7 @@ PKCE is enabled by default in FusionAuth for public clients. To enable PKCE for ## Setting up Spring -Navigate to [Spring Initialzr](https://start.spring.io), and create a new Spring Boot project with the following options set: +Navigate to [Spring Initializr](https://start.spring.io), and create a new Spring Boot project with the following options set: - You can choose either Gradle or Maven as your package manager—we've used Maven for this example - Spring Boot 2.7.x diff --git a/astro/src/content/blog/sunfinity-fusionauth-python.mdx b/astro/src/content/blog/sunfinity-fusionauth-python.mdx index 52782733a2..32fe6d0ec5 100644 --- a/astro/src/content/blog/sunfinity-fusionauth-python.mdx +++ b/astro/src/content/blog/sunfinity-fusionauth-python.mdx @@ -47,7 +47,7 @@ Also, it is SUPER FUN and unimaginably rewarding to build the infrastructure you * ERPNext * SuiteCRM * Nextcloud -* Gitlab +* GitLab And of course all of our own Angular/VueJS and Python apps. @@ -97,15 +97,15 @@ Before FusionAuth we were using our own custom authentication, but it wasn't OAu **Dan:** Why did you choose FusionAuth over the competition? -**Matthew:** When redesigning our entire auth and API stack we looked at Okta, Auth0, Keycloak and GLUU. Immediately Okta and Auth0 were out due to the cost per API hit and the cloud based approach. We did prototype them anyway, and they are indeed great services if you want to pay the premium. For Keycloak and GLUU we built a prototype infrastructure for each and tested CLI apps, SPAs and Kong interactions. To put it simply, those systems (specifically GLUU) are more complicated than they should be and the documentation was lackluster. +**Matthew:** When redesigning our entire auth and API stack we looked at Okta, Auth0, Keycloak and Gluu. Immediately Okta and Auth0 were out due to the cost per API hit and the cloud based approach. We did prototype them anyway, and they are indeed great services if you want to pay the premium. For Keycloak and Gluu we built a prototype infrastructure for each and tested CLI apps, SPAs and Kong interactions. To put it simply, those systems (specifically Gluu) are more complicated than they should be and the documentation was lackluster. -We spend months pulling our hair out with GLUU, never fully understanding the layout of the system with all their 404 linked documentation. When we found FusionAuth it was like a breath of fresh air on top of a 14er in Colorado. The entire layout just made sense. The FusionAuth design of tenants, users, groups, roles, apps, registrations modeled exactly how we think of auth. In a word, perfect. We were up and running with a self-hosted FusionAuth in a day and haven't looked back since! +We spend months pulling our hair out with Gluu, never fully understanding the layout of the system with all their 404 linked documentation. When we found FusionAuth it was like a breath of fresh air on top of a 14er in Colorado. The entire layout just made sense. The FusionAuth design of tenants, users, groups, roles, apps, registrations modeled exactly how we think of auth. In a word, perfect. We were up and running with a self-hosted FusionAuth in a day and haven't looked back since! **Dan:** How much time and money would you say FusionAuth has saved you? **Matthew:** From prototype to deploy of FusionAuth was literally a day. That said, we already had years of auth knowledge so the learning curve was low. But FusionAuth is such a great product with a simple design that anyone with basic auth knowledge can be up and running within the week. -Compare that to the months spent trying to set up and even understand GLUU. Money in the bank! Using FusionAuth and Kong ensures that all API hits are free. I would say Okta and Auth0 are similarly easy to get up and running but you pay the premium. If self-hosted / free'ish is your goal, FusionAuth will save you months of effort, time and money. And since our cost per API hit is now ZERO, I'm going to say savings cannot be quantified. But a word comes to mind: "priceless"! +Compare that to the months spent trying to set up and even understand Gluu. Money in the bank! Using FusionAuth and Kong ensures that all API hits are free. I would say Okta and Auth0 are similarly easy to get up and running but you pay the premium. If self-hosted / free'ish is your goal, FusionAuth will save you months of effort, time and money. And since our cost per API hit is now ZERO, I'm going to say savings cannot be quantified. But a word comes to mind: "priceless"! > From prototype to deploy of FusionAuth was literally a day. diff --git a/astro/src/content/blog/switchboard-reduced-migration-time.mdx b/astro/src/content/blog/switchboard-reduced-migration-time.mdx index ed68812572..a5ff51ae1d 100644 --- a/astro/src/content/blog/switchboard-reduced-migration-time.mdx +++ b/astro/src/content/blog/switchboard-reduced-migration-time.mdx @@ -71,7 +71,7 @@ However, our use-cases at Switchboard are quite different from my prior experien The FusionAuth developer documentation is top-notch with detailed usage examples, and the provided SDKs were intuitive to use and easy to implement using Typescript. Other competitors either lacked appropriate documentation or had an unintuitive SDK or development workflow. -I appreciated that FusionAuth provided a few avenues for support: the community forums, github issues, and paid support. I’ve had success getting answers to questions while I was prototyping a FusionAuth integration, and was surprised to see the level of FusionAuth engineering responses to issues that were reported. I really liked that I can interact directly with a FusionAuth engineer for any deep technical issues. +I appreciated that FusionAuth provided a few avenues for support: the community forums, GitHub issues, and paid support. I’ve had success getting answers to questions while I was prototyping a FusionAuth integration, and was surprised to see the level of FusionAuth engineering responses to issues that were reported. I really liked that I can interact directly with a FusionAuth engineer for any deep technical issues. Other competitors had a lot of complexity when working with their SDK or overall solutions. Some would require multiple products to fit together like pieces of a puzzle that required dedicated infrastructure or hide complex use-cases behind abstractions that were difficult to follow or customize. @@ -79,7 +79,7 @@ What I appreciated with FusionAuth is its flexibility. While it handles simple u In our case, we went for a customized approach as we wanted total control over our auth experience and workflows by utilizing the SDKs. The development experience was exceptional. We never felt like we were fighting against the FusionAuth platform to get what we wanted it to do. -Feature-wise, lambda / hooks that support modern Javascript (ES6+) is something I haven’t seen with other competitors (or rather, lambda support in general), and has been a boon for us when it came to adding custom logic around auth lifecycles. +Feature-wise, lambda / hooks that support modern JavaScript (ES6+) is something I haven’t seen with other competitors (or rather, lambda support in general), and has been a boon for us when it came to adding custom logic around auth lifecycles. Finally, we chose FusionAuth because of the options to self-host or have FusionAuth host for you. We did not want to maintain infrastructure for FusionAuth at the present, and the hosted option cost was very reasonable and removed a lot of the time to bootstrap. Having the option to self-host if we had significant growth in the future is really nice. diff --git a/astro/src/content/blog/talent-funnel-fusionauth.mdx b/astro/src/content/blog/talent-funnel-fusionauth.mdx index d043045236..c40c6f4166 100644 --- a/astro/src/content/blog/talent-funnel-fusionauth.mdx +++ b/astro/src/content/blog/talent-funnel-fusionauth.mdx @@ -33,7 +33,7 @@ We are currently rebuilding our entire platform from scratch and centralizing al **David:** We're using FusionAuth to power authentication for our entire platform. We have both power users for our ATS platform as well as a very large volume of 'low activity' users who may log in a couple of times a year. -We use FusionAuth to provide standard user accounts, two factor Authentication with Google Authenticator and social sign ons which is a very important feature to reduce friction for registrations on our system. Our legacy system used it's own custom built authentication system which we wanted to move away from, we're not in the authentication business so why waste time implementing your own security, leave it to the experts! We tried many competitors but either the technology didn't fit our use-case or the billing would have been astronomical for the types of users we have. +We use FusionAuth to provide standard user accounts, two factor Authentication with Google Authenticator and social sign-ons which is a very important feature to reduce friction for registrations on our system. Our legacy system used it's own custom built authentication system which we wanted to move away from, we're not in the authentication business so why waste time implementing your own security, leave it to the experts! We tried many competitors but either the technology didn't fit our use-case or the billing would have been astronomical for the types of users we have. > A lot of authentication providers seem to overcomplicate the process, something I found was not the case with FusionAuth. @@ -41,7 +41,7 @@ We use FusionAuth to provide standard user accounts, two factor Authentication w **David:** We've been able to grow on a smooth trajectory. The old system just ran on an AWS instance and has been upgraded a few times over the years but obviously you're limited to the amount of scalability you can achieve in this way. The new platform utilizes kubernetes and we're able to auto-scale pods when we detect a surge of traffic, if we have too many pods to schedule more hardware is automatically added. No more 2am phone calls to increase resources, it's handled automatically. -**Dan:** Which social signon have you found to be the most important or used? +**Dan:** Which social sign-on have you found to be the most important or used? **David:** A lot of our candidates like to use FaceBook to login. Obviously FaceBook isn't as popular with the younger generation so we're monitoring feedback and market forces to see what other social channels will become important soon. diff --git a/astro/src/content/blog/top-forum-posts-may-2021.mdx b/astro/src/content/blog/top-forum-posts-may-2021.mdx index 817a173d40..997bd3d1ca 100644 --- a/astro/src/content/blog/top-forum-posts-may-2021.mdx +++ b/astro/src/content/blog/top-forum-posts-may-2021.mdx @@ -19,7 +19,7 @@ If you want to participate, you need a free account. Or, check out [the forum](/ Post: [FusionAuth + NextAuth refresh tokens](/community/forum/topic/1011/fusionauth-nextauth-refresh-tokens) -In this post, naughtly.keller is sharing how they are building an application with Next.js, NextAuth, FusionAuth and Hasura. In particular they are wondering about refresh tokens and how they work in this context. They also learned about lambdas, mapping claims, the userinfo endpoint, and the introspect endpoint. FusionAuth team member Joshua also chimed in with some helpful feedback and links. +In this post, naughtly.keller is sharing how they are building an application with Next.js, NextAuth, FusionAuth and Hasura. In particular they are wondering about refresh tokens and how they work in this context. They also learned about lambdas, mapping claims, the UserInfo endpoint, and the introspect endpoint. FusionAuth team member Joshua also chimed in with some helpful feedback and links. [Refresh tokens](https://datatracker.ietf.org/doc/html/rfc6749#section-1.5) are a part of the OAuth2 standard and allow you to mint new access tokens without requiring a user to re-authenticate. diff --git a/astro/src/content/blog/understanding-the-authorization-code-grant.mdx b/astro/src/content/blog/understanding-the-authorization-code-grant.mdx new file mode 100644 index 0000000000..815699dfe0 --- /dev/null +++ b/astro/src/content/blog/understanding-the-authorization-code-grant.mdx @@ -0,0 +1,127 @@ +--- +publish_date: 2024-09-10 +title: Understanding The Authorization Code Grant +description: You'll dive into the benefits of Authorization Code Grant in simplifying your app's authentication flows. +authors: Alex Patterson +categories: Education +image: /img/blogs/video-auth-code-grant/authorization-code-grant-simple.png +tags: oauth, code grant +excerpt_separator: "{/* more */}" +--- +import Aside from '../../components/Aside.astro'; +import { YouTube } from '@astro-community/astro-embed-youtube'; + +In this video, you will be guided through the intricacies of the [Authorization Code Grant flow](/articles/login-authentication-workflows/webapp/oauth-authorization-code-grant-sessions-refresh-tokens-cookies) using FusionAuth's sandbox environment. This simple example aims to be accessible to everyone, so follow along and let's dive into the details. + +{/* more */} + + + +## What Is The Authorization Code Grant? + +The Authorization Code Grant is a widely used method in OAuth 2.0 for enabling users to securely authenticate with third-party applications. For the tech nerds in the house that is [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749). This method involves redirecting the user to an authorization server, obtaining an authorization code, and then exchanging that code for an access token. +Let's break this process down step-by-step. + +### Starting Point: The Initial URL + +Our journey begins by navigating to the admin application for FusionAuth. Initially, the URL [https://sandbox.fusionauth.io/admin](https://sandbox.fusionauth.io/admin) points to FusionAuth's admin UI, which then delegates authentication to FusionAuth itself. This delegation redirects us to the hosted login page that is both themed and customizable. + + + +### Customized Login Page + +In the below example, you'll use a customized login page from one of our clients as an example. You will notice familiar elements such as email and password fields, but there's a distinct branding as intended by Private Division. Once logged in, we proceed through the authentication flow and get redirected to the Admin UI. + + +![Private Division's custom login page with video game highlights on the left and a login form on the right.](/img/blogs/video-auth-code-grant/1-video-auth-code-grant.png) + +#### Why the Redirect is Crucial + +The redirect serves two main purposes: security and features. + +1. **Security**: + + + - By redirecting users to FusionAuth's hosted login pages, we make sure that applications delegating authentication to FusionAuth don't need to handle sensitive information like credentials. + - This minimizes the risk of sensitive data being spread across multiple applications. + + +2. **Features**: + + + - Delegating authentication to FusionAuth enables us to offer new features without burdening your application. + - Features like [profile](/docs/lifecycle/manage-users/account-management/updating-user-data) management, [Multi-Factor Authentication (MFA)](/docs/lifecycle/authenticate-users/multi-factor-authentication), [session management](/docs/lifecycle/authenticate-users/logout-session-management), etc., can be added through FusionAuth or its APIs with minimal complexity. + + + +## Implementing the Authorization Code Grant with FusionAuth + +To implement this, we'll follow easily configured steps, making sure the application is well-integrated with FusionAuth. + +### Step 1: Setting Up the Authorization Request + +Start by building the [authorization code grant request](/docs/lifecycle/authenticate-users/oauth/endpoints#authorization-code-grant-request). This URL will redirect the user to FusionAuth's login page. + +```http +GET /oauth2/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code&tenantId={tenantId}&scope={scope} +``` + +**Replace the placeholders**: + +- `client_id`: Your Application's Client Id. +- `redirect_uri`: The URI where the user will be redirected after logging in. +- `scope`: The permissions your application needs, like `openid` and `offline_access`. +- `response_type`: Always `code` in this case. +- `tenantId`: The unique Tenant Id used for applying the proper theme. + + + +### Step 2: Handling the Redirect + +When the user logs in successfully, FusionAuth will redirect them back to your `redirect_uri` with an [authorization code and state](/docs/lifecycle/authenticate-users/oauth/endpoints#response). Your application needs to handle the callback and extract these parameters. + +```http +GET /callback?code=AUTHORIZATION_CODE&state=YOUR_STATE +``` + +### Step 3: Exchanging the Authorization Code for an Access Token + +Next, your application sends a POST request to FusionAuth's token endpoint to exchange the authorization code for an access token. + +```http +POST /oauth2/token HTTP/1.1 +Host: sandbox.fusionauth.io +Content-Type: application/x-www-form-urlencoded +Accept: */* +Content-Length: 436 +client_id=3c219e58-ed0e-4b18-ad48-f4f92793ae32&code=+WYT3XemV4f81ghHi4V+RyNwvATDaD4FIj0BpfFC4Wzg&grant_type=authorization_code&redirect_uri=https%3A%2F%2F.sandbox.fusionauth.io +``` + +### Step 4: Using the Access Token + +Once you receive the access token, you can use it to authenticate API requests. + +```http +GET /your-api-endpoint +Authorization: Bearer ACCESS_TOKEN +``` + +One of the most common ways to verify the access token is by requesting the [JSON Web Key Set (JWKS)](/docs/lifecycle/authenticate-users/oauth/endpoints#json-web-key-set-jwks) public keys generated by FusionAuth. This will allow your system to cryptographically verify JWTs using the JWKS format. To find out more information you can read through our [JWT API docs](/docs/apis/jwt). + +## Enhancing User Experience with Passkeys + +Delegating authentication to FusionAuth has significant advantages. For instance, users might be prompted to set up a passkey for easier future authentication if they use a WebAuthn capable browser. This functionality is already built into FusionAuth and once again is a feature that doesn't require you to write any code. You can even add passkeys to the FusionAuth Community edition as of release [1.52.0](/docs/release-notes/#version-1-52-0), just by adding a community license to your platform. + +## Conclusion + +By integrating FusionAuth using the Authorization Code Grant flow, you significantly enhance the security and scalability of your application. The redirect ensures sensitive data is handled securely while also enabling you to leverage powerful features without additional complexity. + +For more details and advanced topics on OAuth 2.0, visit the [authenticate users](/docs/lifecycle/authenticate-users/) portion of our docs site. I hope this simple guide helps you understand the power of having a dedicated system for authentication that will add both security and features to all of your web and mobile applications. If you ever want to know what happens to the tokens after an OAuth Authorization Code Grant give this [post](/blog/what-happens-after-oauth-authentication-event) a read. \ No newline at end of file diff --git a/astro/src/content/blog/unio-saves-100k-with-fusionauth.mdx b/astro/src/content/blog/unio-saves-100k-with-fusionauth.mdx index 04fcdf5daa..99f43a933b 100644 --- a/astro/src/content/blog/unio-saves-100k-with-fusionauth.mdx +++ b/astro/src/content/blog/unio-saves-100k-with-fusionauth.mdx @@ -87,7 +87,7 @@ Installing 1.25 on `192.0.0.2` and then going to `192.0.0.2/swagger` would show **Jason:** Is there a Slack group that our developers can join if they have questions for the core FusionAuth team? If not, creating a feedback channel would be incredibly useful. -**Dan:** We do have a [community forum](/community/forum/) which is fairly active and we also have an [active github issues tracker](https://github.com/fusionauth/fusionauth-issues/issues) for bugs and feature requests. We love feedback from our community. +**Dan:** We do have a [community forum](/community/forum/) which is fairly active and we also have an [active GitHub issues tracker](https://github.com/fusionauth/fusionauth-issues/issues) for bugs and feature requests. We love feedback from our community. ------- diff --git a/astro/src/content/blog/updating-crufty-php-application.mdx b/astro/src/content/blog/updating-crufty-php-application.mdx index 48fdb5a852..b78189e79e 100644 --- a/astro/src/content/blog/updating-crufty-php-application.mdx +++ b/astro/src/content/blog/updating-crufty-php-application.mdx @@ -28,7 +28,7 @@ The code is all available in a [FusionAuth GitHub repository](https://github.com You'll need to have a few things set up before you get going. * A running instance of FusionAuth. If you don't have this, check out the [5 minute setup guide](/docs/quickstarts/5-minute-setup-guide). -* A modern version of PHP. This code was tested with php 7.3.11. +* A modern version of PHP. This code was tested with PHP 7.3.11. ## Introducing the legacy PHP app with a homegrown auth system diff --git a/astro/src/content/blog/user-registration-and-sign-in-with-laravel.mdx b/astro/src/content/blog/user-registration-and-sign-in-with-laravel.mdx index 7f36a6f273..cc545a925d 100644 --- a/astro/src/content/blog/user-registration-and-sign-in-with-laravel.mdx +++ b/astro/src/content/blog/user-registration-and-sign-in-with-laravel.mdx @@ -17,7 +17,7 @@ Laravel is one of the most popular PHP application frameworks in the marketplace -In this tutorial, we'll set up a new Laravel application that uses FusionAuth to register and login users. All the code used here is [available on Github](https://github.com/FusionAuth/fusionauth-example-laravel). This application will show just a tiny sample of what you can do with FusionAuth, so be sure to check out the [PHP Client Library](/docs/sdks/php) and [documentation](/docs/) for much more. +In this tutorial, we'll set up a new Laravel application that uses FusionAuth to register and login users. All the code used here is [available on GitHub](https://github.com/FusionAuth/fusionauth-example-laravel). This application will show just a tiny sample of what you can do with FusionAuth, so be sure to check out the [PHP Client Library](/docs/sdks/php) and [documentation](/docs/) for much more. ## What we'll cover 1. Installing and setting up a local FusionAuth instance @@ -37,7 +37,7 @@ In this tutorial, we'll set up a new Laravel application that uses FusionAuth to - Web browser Please note this example application was tested using: -- Php 7.2 +- PHP 7.2 - Laravel 7.30.4 ## Installing and setting up FusionAuth @@ -411,6 +411,6 @@ Now when a logged-in user viewing their profile clicks the `Logout` link, Larave ## Conclusion and next steps -I hope this minimal working example gives you a good starting point for integrating FusionAuth into your Laravel application. There are many other things you should consider if you're building authentication into a production application. For example, I've added [flash messages](https://laravel.com/docs/7.x/session#flash-data) for errors and successes to the [code repository on Github](https://github.com/FusionAuth/fusionauth-example-laravel). You will probably also want to create other workflows like deleting users, updating emails and passwords, setting user roles and permissions, and forgot password workflows. All of these things are possible using FusionAuth and Laravel. +I hope this minimal working example gives you a good starting point for integrating FusionAuth into your Laravel application. There are many other things you should consider if you're building authentication into a production application. For example, I've added [flash messages](https://laravel.com/docs/7.x/session#flash-data) for errors and successes to the [code repository on GitHub](https://github.com/FusionAuth/fusionauth-example-laravel). You will probably also want to create other workflows like deleting users, updating emails and passwords, setting user roles and permissions, and forgot password workflows. All of these things are possible using FusionAuth and Laravel. If you have questions or need help integrating your Laravel application with FusionAuth, feel free to leave a comment below. diff --git a/astro/src/content/blog/using-fusionauth-with-cockroachdb.mdx b/astro/src/content/blog/using-fusionauth-with-cockroachdb.mdx index 91ae1a7a3f..5173e94fe9 100644 --- a/astro/src/content/blog/using-fusionauth-with-cockroachdb.mdx +++ b/astro/src/content/blog/using-fusionauth-with-cockroachdb.mdx @@ -36,13 +36,13 @@ What we do is take note taking to the next level. We transcribe the meetings and **Dan:** How do you use FusionAuth? OAuth? User management? Social sign-on? Something else? -**Michael:** We use Fusionauth for user management, social login is not yet enabled as there is an incompatibility with cockroachdb right now. It should be fixed soon, [here's the bug](https://github.com/cockroachdb/cockroach/issues/40963). +**Michael:** We use FusionAuth for user management, social login is not yet enabled as there is an incompatibility with cockroachdb right now. It should be fixed soon, [here's the bug](https://github.com/cockroachdb/cockroach/issues/40963). **Dan:** What problems did we solve for you? **Michael:** The first prototype managed passwords and JWT keys in our own application. -Mid-last year the approaching go live required us to change a lot of things with authentication to facilitate the security level that we want to provide our users. Fusionauth does most of this for us; it is not user facing but handles password less logins and JWT creation/key management. +Mid-last year the approaching go live required us to change a lot of things with authentication to facilitate the security level that we want to provide our users. FusionAuth does most of this for us; it is not user facing but handles password less logins and JWT creation/key management. **Dan:** So you aren't using the hosted login pages (the FusionAuth provided login workflows) but instead using the APIs? And you built your own login pages and other flows? @@ -58,7 +58,7 @@ We would like to use Social Logins, like Facebook, Google and Apple, but right n **Michael:** It has the capabilities to handle our use cases but would also require more maintenance and more development time spent on having key management etc. -We still use it but only now to decode the received JWTs and to handle the verification/data passing in our api middleware. +We still use it but only now to decode the received JWTs and to handle the verification/data passing in our API middleware. **Dan:** Why did you choose FusionAuth over the alternatives? @@ -74,11 +74,11 @@ We still use it but only now to decode the received JWTs and to handle the verif The ongoing additional maintenance is something that would be hard to quantify but I would assume it to be several developer/testing/QA days per month. -One thought in regard to security is that the cost of breaches is usually higher than the implementation cost. Using a battle tested solution like Fusionauth is the only way to avoid such breaches in the future. +One thought in regard to security is that the cost of breaches is usually higher than the implementation cost. Using a battle tested solution like FusionAuth is the only way to avoid such breaches in the future. **Dan:** How do you run FusionAuth (kubernetes, standalone tomcat server, behind a proxy, etc)? -**Michael:** We run Fusionauth in Kubernetes behind a Traefik ingress. +**Michael:** We run FusionAuth in Kubernetes behind a Traefik ingress. **Dan:** Why are you using CockroachDB as the backend datastore for FusionAuth? @@ -90,11 +90,11 @@ After initial tests we concluded that only social logins would trigger a named q **Dan:** Any general feedback/areas to improve? -**Michael:** We'd like the ability to set custom HTTPS Headers for CDNs like AWS Cloudfront (cloudfront-forwarded-proto vs x-forwarded-proto). +**Michael:** We'd like the ability to set custom HTTPS Headers for CDNs like AWS CloudFront (`cloudfront-forwarded-proto` vs `x-forwarded-proto`). **Dan:** I don't understand. Where would you want to set these? Can you explain the use case a bit more? -**Michael:** This is to use the FusionAuth admin UI. When we try to log into those it would fail per default with a CSRF error because it thinks that the request is not made with https, but the request *was* performed with https. Cloudfront handles ssl termination for us and appends `cloudfront-forwarded-proto=https`. +**Michael:** This is to use the FusionAuth admin UI. When we try to log into those it would fail per default with a CSRF error because it thinks that the request is not made with HTTPS, but the request *was* performed with HTTPS. CloudFront handles SSL termination for us and appends `cloudfront-forwarded-proto=https`. For FusionAuth to work in this case we have a custom MiddleWare in Traefik just to set `x-forwarded-proto` to `https` all the time (because there cannot be unauthenticated requests anyway). diff --git a/astro/src/content/blog/using-oauth-and-pkce-to-add-authentication-to-your-gatsby-site.mdx b/astro/src/content/blog/using-oauth-and-pkce-to-add-authentication-to-your-gatsby-site.mdx index 7594323e4b..d294c8a02e 100644 --- a/astro/src/content/blog/using-oauth-and-pkce-to-add-authentication-to-your-gatsby-site.mdx +++ b/astro/src/content/blog/using-oauth-and-pkce-to-add-authentication-to-your-gatsby-site.mdx @@ -20,7 +20,7 @@ At a high level, the authorization process looks like this: -In this tutorial, you'll walk through the process step-by-step, but if you want to download the code, it is [available on Github](https://github.com/fusionauth/fusionauth-example-gatsby). +In this tutorial, you'll walk through the process step-by-step, but if you want to download the code, it is [available on GitHub](https://github.com/fusionauth/fusionauth-example-gatsby). ## What we'll cover 1. Setting up FusionAuth @@ -101,7 +101,7 @@ module.exports = { }; ``` -Within the `./server` directory, create a new [Express](https://expressjs.com/) app and install the [cors](https://www.npmjs.com/package/cors), [session](https://www.npmjs.com/package/express-session) and [request](https://www.npmjs.com/package/request) packages. +Within the `./server` directory, create a new [Express](https://expressjs.com/) app and install the [`cors`](https://www.npmjs.com/package/cors), [`session`](https://www.npmjs.com/package/express-session) and [`request`](https://www.npmjs.com/package/request) packages. ```bash npm init diff --git a/astro/src/content/blog/what-happens-after-oauth-authentication-event.mdx b/astro/src/content/blog/what-happens-after-oauth-authentication-event.mdx index 80e5c06f9f..a59e80fa04 100644 --- a/astro/src/content/blog/what-happens-after-oauth-authentication-event.mdx +++ b/astro/src/content/blog/what-happens-after-oauth-authentication-event.mdx @@ -56,13 +56,13 @@ If you've decided to use the Authorization Code grant, you need to store the res The first option is to send the access token and refresh token down to the client. While both are stored on the client, only the access token must be presented to any APIs or protected resources. The refresh token should be presented to FusionAuth, but that workflow will be covered in more detail below. If the refresh token cookie is sent to a resource server, it can be safely ignored. -When using a browser, store these as `HTTPOnly`, secure cookies with a `SameSite` value of `Lax` or `Strict`. +When using a browser, store these as `HttpOnly`, secure cookies with a `SameSite` value of `Lax` or `Strict`. If you choose this option, the browser, whether a simple HTML page with some JavaScript or a complicated single page application (SPA), makes requests against APIs, and the access token is along for the ride. As long as the APIs live on a common domain, or a parent domain, the access token cookie will be sent with requests. For example, the server which gets the tokens can live at `auth.example.com` and if you set the cookie domain to `.example.com`, APIs living at `api.example.com`, `todo.example.com`, or any other host under `.example.com`, will receive the token. - + When using a native app, store these tokens in a secure location, such as the [iOS Keychain](https://developer.apple.com/documentation/security/keychain_services) or [Android internal data](https://developer.android.com/topic/security/best-practices#safe-data). Retrieve them and append them to the proper header before making API requests. @@ -95,7 +95,7 @@ The signature and standard claims checks can and should be done with a language If you don't have a token that has internal structure and a signature, another option is to introspect the token by presenting it to FusionAuth. Here the validity of the token is confirmed by FusionAuth. - + A successful introspection will return JSON. The claims in the JSON still need to be checked: @@ -125,7 +125,7 @@ If you choose to use client stored tokens, you gain a lot of horizontal scalabil As mentioned above, this approach is a great fit for a single page JavaScript application using data from multiple APIs on the same domain. -Using secure `HTTPOnly` cookies protects you from cross-site scripting (XSS) attacks. XSS is a common mechanism for attackers to gain access to tokens and therefore to make requests masquerading as another user. Secure `HTTPOnly` cookies are not available to JavaScript running on the page, and therefore can't be accessed by malicious scripts. +Using secure `HttpOnly` cookies protects you from cross-site scripting (XSS) attacks. XSS is a common mechanism for attackers to gain access to tokens and therefore to make requests masquerading as another user. Secure `HttpOnly` cookies are not available to JavaScript running on the page, and therefore can't be accessed by malicious scripts. If APIs are on different domains, you have two options. You can use a proxy which can ingest the token, validate it and pass on requests to other domains, or choose the session based approach, discussed later. diff --git a/astro/src/content/blog/whats-new-in-oauth-2-1.mdx b/astro/src/content/blog/whats-new-in-oauth-2-1.mdx index d430e60d3e..780e6013d3 100644 --- a/astro/src/content/blog/whats-new-in-oauth-2-1.mdx +++ b/astro/src/content/blog/whats-new-in-oauth-2-1.mdx @@ -9,7 +9,7 @@ tags: standards, oauth, oauth2 excerpt_separator: "{/* more */}" --- -Hey look! OAuth is getting spiffed up a bit. The original OAuth 2.0 specification was released in October 2012 as [RFC 6749](https://tools.ietf.org/html/rfc6749). It replaced OAuth 1.0, released in April 2010. There have been some extensions over the years. A new OAuth specification has been proposed and is currently under discussion. As of this blog post's writing, the specification was most recently updated on March 8, 2020. If approved, [OAuth 2.1](https://tools.ietf.org/html/draft-parecki-oauth-v2-1-01) will obsolete certain parts of Oauth 2.0 and mandate additional security best practices. The rest of the OAuth 2.0 specification will be retained. +Hey look! OAuth is getting spiffed up a bit. The original OAuth 2.0 specification was released in October 2012 as [RFC 6749](https://tools.ietf.org/html/rfc6749). It replaced OAuth 1.0, released in April 2010. There have been some extensions over the years. A new OAuth specification has been proposed and is currently under discussion. As of this blog post's writing, the specification was most recently updated on March 8, 2020. If approved, [OAuth 2.1](https://tools.ietf.org/html/draft-parecki-oauth-v2-1-01) will obsolete certain parts of OAuth 2.0 and mandate additional security best practices. The rest of the OAuth 2.0 specification will be retained. {/* more */} @@ -23,7 +23,7 @@ It's been a long time since OAuth 2.0 was released. A consolidation point releas So, this is not a scrape and rebuild of OAuth 2.0. Instead, OAuth 2.1 consolidates the changes and tweaks to OAuth 2.0 that have been made over the past eight years, with a focus on better default security. It establishes the best practices and will serve as a reference document. Here's a suggested description pulled from the [ongoing mailing list discussion](https://mailarchive.ietf.org/arch/msg/oauth/Ne4Q9erPP7SpC5051sSy6XnLDv0/): "By design, [OAuth 2.1] does not introduce any new features to what already exists in the OAuth 2.0 specifications being replaced." Many of the new draft specification details are drawn from the [OAuth 2.0 Security Best Current Practices](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-14) document. However, in the name of security best practices, some of the more problematic grants will be removed. -At the end of the day, the goal is to have a single document detailing how to best implement and use OAuth, as both a client and an implementor. No longer will developers have to hunt across multiple RFCs and standards documents to understand how a specified behavior should be implemented or used. +At the end of the day, the goal is to have a single document detailing how to best implement and use OAuth, as both a client and an implementer. No longer will developers have to hunt across multiple RFCs and standards documents to understand how a specified behavior should be implemented or used. ## I use OAuth in my application, what does OAuth 2.1 mean to me? diff --git a/astro/src/content/blog/why-consider-standards-based-auth-options-excerpt.mdx b/astro/src/content/blog/why-consider-standards-based-auth-options-excerpt.mdx index 75a2b1426a..998612f13f 100644 --- a/astro/src/content/blog/why-consider-standards-based-auth-options-excerpt.mdx +++ b/astro/src/content/blog/why-consider-standards-based-auth-options-excerpt.mdx @@ -31,7 +31,7 @@ When you use a standardized protocol, you have the peace of mind that comes with What would happen if every time you built a new system's authentication system, you had to create it from scratch? You would have to learn the nitty-gritty details of authentication over and over again. -This would lead to a scenario where you couldn't leverage your hardwon knowledge between projects and employers. If you instead use a ubiquitous protocol like OAuth, there may be subtle differences, but you'll understand the general authentication architecture. If you know how standardized protocols work and what use cases they solve, you can bring that knowledge to other projects and companies. +This would lead to a scenario where you couldn't leverage your hard won knowledge between projects and employers. If you instead use a ubiquitous protocol like OAuth, there may be subtle differences, but you'll understand the general authentication architecture. If you know how standardized protocols work and what use cases they solve, you can bring that knowledge to other projects and companies. The same applies when teaching and onboarding new engineers to your team. If you are using a standardized auth protocol, then your new team members are likely to already know about OAuth, SAML, or other standardized protocols. It will be much easier to get these new team members up and running and contributing to these relevant areas of your system. diff --git a/astro/src/content/docs/_shared/_access-token-claims.mdx b/astro/src/content/docs/_shared/_access-token-claims.mdx index 833ee1b798..9397ca1b91 100644 --- a/astro/src/content/docs/_shared/_access-token-claims.mdx +++ b/astro/src/content/docs/_shared/_access-token-claims.mdx @@ -28,14 +28,16 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; The email address of the User whose claims are represented by this JWT. - + In version `1.50.0` and later this claim is not returned when the oauthConfiguration.scopeHandlingPolicy value of the Application is `Strict`. - + + The OpenId Connect claim indicating if the User's email has been verified. - + In version `1.50.0` and later this claim is not returned when the oauthConfiguration.scopeHandlingPolicy value of the Application is `Strict`. + The expiration instant of the JWT, expressed as UNIX time which is the number of seconds since Epoch. This registered claim is defined by @@ -56,8 +58,9 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; The username of the User whose claims are represented by this JWT. - + In version `1.50.0` and later this claim is not returned when the oauthConfiguration.scopeHandlingPolicy value of the Application is `Strict`. + The roles assigned to the User in the authenticated Application. This claim is only present if the User has a registration to the Application. diff --git a/astro/src/content/docs/_shared/_hosted-backend-response-cookies.mdx b/astro/src/content/docs/_shared/_hosted-backend-response-cookies.mdx index 1331e0e515..070c098955 100644 --- a/astro/src/content/docs/_shared/_hosted-backend-response-cookies.mdx +++ b/astro/src/content/docs/_shared/_hosted-backend-response-cookies.mdx @@ -3,10 +3,10 @@ import APIField from 'src/components/api/APIField.astro'; - The encoded access token. This cookie is written in the response as a `Secure` `HTTPOnly` session cookie. + The encoded access token. This cookie is written in the response as a `Secure` `HttpOnly` session cookie. - The refresh token. This cookie is written in the response as a `Secure` `HTTPOnly` persistent cookie. The cookie expiration is configured in the JWT + The refresh token. This cookie is written in the response as a `Secure` `HttpOnly` persistent cookie. The cookie expiration is configured in the JWT configuration for the application or the global JWT configuration. diff --git a/astro/src/content/docs/_shared/_scim-server-permissions.md b/astro/src/content/docs/_shared/_scim-server-permissions.md new file mode 100644 index 0000000000..353d3c0d2d --- /dev/null +++ b/astro/src/content/docs/_shared/_scim-server-permissions.md @@ -0,0 +1,21 @@ +Below is a list of available permissions that can be included in your SCIM server entity type. Each controls access to a single API endpoint. You can choose to create as few or as many of these as you require. The names must match exactly. + + +| Name | Access to API | +|-------------------------------------|--------------------------------------------------------------------------------------------------------------------------| +| `scim:enterprise:user:create` | [Create an Enterprise User](/docs/apis/scim/scim-enterprise-user#create-an-enterpriseuser) | +| `scim:enterprise:user:read` | [Retrieve an Enterprise User](/docs/apis/scim/scim-enterprise-user#retrieve-an-enterpriseuser) | +| `scim:enterprise:user:update` | [Update an Enterprise User](/docs/apis/scim/scim-enterprise-user#update-an-enterpriseuser) | +| `scim:enterprise:user:delete` | [Delete an Enterprise User](/docs/apis/scim/scim-enterprise-user#delete-an-enterpriseuser) | +| `scim:group:create` | [Create a Group](/docs/apis/scim/scim-group#create-a-group) | +| `scim:group:read` | [Retrieve a Group](/docs/apis/scim/scim-group#retrieve-a-group) | +| `scim:group:update` | [Update a Group](/docs/apis/scim/scim-group#update-a-group) | +| `scim:group:delete` | [Delete a Group](/docs/apis/scim/scim-group#delete-a-group) | +| `scim:resource-types:read` | [Retrieve Resource Types](/docs/apis/scim/scim-service-provider#retrieve-resource-types) | +| `scim:schemas:read` | [Retrieve Schemas](/docs/apis/scim/scim-service-provider#retrieve-schemas) | +| `scim:service-provider-config:read` | [Retrieve Service Provider Configuration](/docs/apis/scim/scim-service-provider#retrieve-service-provider-configuration) | +| `scim:user:create` | [Create a User](/docs/apis/scim/scim-user#create-a-user) | +| `scim:user:read` | [Retrieve a User](/docs/apis/scim/scim-user#retrieve-a-user) | +| `scim:user:update` | [Update a User](/docs/apis/scim/scim-user#update-a-user) | +| `scim:user:delete` | [Delete a User](/docs/apis/scim/scim-user#delete-a-user) | + diff --git a/astro/src/content/docs/_shared/_theme_template_variables.astro b/astro/src/content/docs/_shared/_theme_template_variables.astro index c1f04fd926..72949d857b 100644 --- a/astro/src/content/docs/_shared/_theme_template_variables.astro +++ b/astro/src/content/docs/_shared/_theme_template_variables.astro @@ -21,7 +21,7 @@ const makeId = (name) => { return name.toLowerCase().replaceAll(' ', '-') }; {t.variables && t.variables.sort((a,b) => a.name.toUpperCase().localeCompare(b.name.toUpperCase())).map((tvar) => - {tvar.removed && <>
    } + {tvar.removed && <>
    }
    )}
    diff --git a/astro/src/content/docs/apis/_application-oauth-configuration-response-body.mdx b/astro/src/content/docs/apis/_application-oauth-configuration-response-body.mdx index 1694e30fa2..e63d166203 100644 --- a/astro/src/content/docs/apis/_application-oauth-configuration-response-body.mdx +++ b/astro/src/content/docs/apis/_application-oauth-configuration-response-body.mdx @@ -126,8 +126,9 @@ import JSON from 'src/components/JSON.astro'; Determines if the OAuth 2.0 Token endpoint requires client authentication. If this is enabled, the client must provide client credentials when using the Token endpoint. The `client_id` and `client_secret` may be provided using a Basic Authorization HTTP header, or by sending these parameters in the request body using POST data. - - In version 1.28.0 and beyond, client authentication can be managed via oauthConfiguration.clientAuthenticationPolicy. + + In version 1.28.0 and beyond, client authentication can be managed via oauthConfiguration.clientAuthenticationPolicy. + Determines if the user will be required to be registered, or complete registration before redirecting to the configured callback in the authorization code grant or the implicit grant. This configuration does not affect any other grant, and does not affect the API usage. diff --git a/astro/src/content/docs/apis/_application-request-body.mdx b/astro/src/content/docs/apis/_application-request-body.mdx index 4556e9fff7..ba5cd8df15 100644 --- a/astro/src/content/docs/apis/_application-request-body.mdx +++ b/astro/src/content/docs/apis/_application-request-body.mdx @@ -73,7 +73,9 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature When an HMAC algorithm is used such as `HS256`, `HS384` or `HS512`, the OAuth `client_secret` will be used as the signing secret. - In version 1.6.0 and beyond, JWT configuration can be managed in the `[Keys API](/docs/apis/keys)` and Keymaster. + + In version 1.6.0 and beyond, JWT configuration can be managed in the [Keys API](/docs/apis/keys) and Keymaster. + Indicates if this application is using the JWT configuration defined here or the global JWT configuration defined by the Tenant. If this is `false` the signing algorithm configured in the Tenant will be used. If `true` the signing algorithm defined in this application will be used. @@ -86,14 +88,18 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature Required when `enabled` is set to `true` and `algorithm` is set to an `RSA` or `ECDSA` based value. - In version 1.6.0 and beyond, JWT configuration can be managed in the `[Keys API](/docs/apis/keys)` and Keymaster. + + In version 1.6.0 and beyond, JWT configuration can be managed in the [Keys API](/docs/apis/keys) and Keymaster. + The public key used when an `RSA` or `ECDSA` signing algorithms has been selected. The public key will be used to verify JWTs signed with the private key. This key is expected to be presented in a PEM encoded format. Required when `enabled` is set to `true` and `algorithm` is set to an `RSA` or `ECDSA` based value. - In version 1.6.0 and beyond, JWT configuration can be managed in the `[Keys API](/docs/apis/keys)` and Keymaster. + + In version 1.6.0 and beyond, JWT configuration can be managed in the [Keys API](/docs/apis/keys) and Keymaster. + The Refresh Token expiration policy. @@ -120,14 +126,16 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature * `Reusable` - the token does not change after it was issued. * `OneTimeUse` - the token value will be changed each time the token is used to refresh a JWT. The client must store the new value after each usage. - +
    The secret used when an `HMAC` based signing algorithm has been selected. This secret is used to sign and verify JWTs. Required when `enabled` is set to `true` and `algorithm` is set to an `HMAC` based value. - In version 1.5.0 and beyond, when selecting an `HMAC` algorithm, the `client_secret` from the OAuth configuration will be used to sign and verify the JWTs. + + In version 1.5.0 and beyond, when selecting an `HMAC` algorithm, the `client_secret` from the OAuth configuration will be used to sign and verify the JWTs. + The length of time in seconds the JWT will live before it is expired and no longer valid. @@ -135,21 +143,21 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature Required when `enabled` is set to `true`. - The Id of the Lambda that will be invoked when an access token is generated for this application. This will be utilized during OAuth2 and OpenID Connect authentication requests as well as when an access token is generated for the Login API. + The Id of the lambda that will be invoked when an access token is generated for this application. This will be utilized during OAuth2 and OpenID Connect authentication requests as well as when an access token is generated for the Login API. - The Id of the Lambda that will be invoked when an Id token is generated for this application during an OpenID Connect authentication request. + The Id of the lambda that will be invoked when an Id token is generated for this application during an OpenID Connect authentication request. - The Id of the Lambda that will be invoked when a SAML response is generated during a SAML authentication request. + The Id of the lambda that will be invoked when a SAML response is generated during a SAML authentication request. - The unique Id of the lambda that will be used to perform additional validation on registration form steps. + The Id of the lambda that will be used to perform additional validation on registration form steps. - The Id of the Lambda that will be invoked when a UserInfo response is generated for this application. + The Id of the lambda that will be invoked when a UserInfo response is generated for this application. Indicates if a JWT may be refreshed using a Refresh Token for this application. This configuration is separate from issuing new Refresh Tokens which is controlled by the `generateRefreshTokens` parameter. This configuration indicates specifically if an existing Refresh Token may be used to request a new JWT using the [Refresh API](/docs/apis/jwt#refresh-a-jwt). @@ -339,8 +347,9 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature Determines if the OAuth 2.0 Token endpoint requires client authentication. If this is enabled, the client must provide client credentials when using the Token endpoint. The `client_id` and `client_secret` may be provided using a Basic Authorization HTTP header, or by sending these parameters in the request body using POST data. - - In version 1.28.0 and beyond, client authentication can be managed via application.oauthConfiguration.clientAuthenticationPolicy. + + In version 1.28.0 and beyond, client authentication can be managed via application.oauthConfiguration.clientAuthenticationPolicy. + When enabled the user will be required to be registered, or complete registration before redirecting to the configured callback in the authorization code grant or the implicit grant. This configuration does not affect any other grant, and does not affect the API usage. @@ -531,8 +540,9 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature The URL of the callback (sometimes called the Assertion Consumer Service or ACS). This is where FusionAuth sends the browser after the user logs in via SAML. - - In version 1.20.0 and beyond, Callback URLs can be managed via application.samlv2Configuration.authorizedRedirectURLs. + + In version 1.20.0 and beyond, Callback URLs can be managed via application.samlv2Configuration.authorizedRedirectURLs. + Whether or not FusionAuth will log SAML debug messages to the event log. This is useful for debugging purposes. @@ -681,7 +691,9 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature An array of Webhook Ids. For Webhooks that are not already configured for All Applications, specifying an Id on this request will indicate the associated Webhook should handle events for this application. - In version 1.37.0 and beyond, Webhooks configuration can be managed in the `[Tenant API](/docs/apis/tenants)`. + + In version 1.37.0 and beyond, Webhooks configuration can be managed in the [Tenant API](/docs/apis/tenants). + diff --git a/astro/src/content/docs/apis/_application-response-body-base.mdx b/astro/src/content/docs/apis/_application-response-body-base.mdx index 003e7c3841..90fb7918bf 100644 --- a/astro/src/content/docs/apis/_application-response-body-base.mdx +++ b/astro/src/content/docs/apis/_application-response-body-base.mdx @@ -20,8 +20,9 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature Whether or not the Application is active. - - In version 1.22.0 and beyond, prefer the use of state. + + In version 1.22.0 and beyond, prefer the use of state. + Whether or not Users can have Authentication Tokens associated with this Application. @@ -69,7 +70,9 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature - In version 1.6.0 and beyond, JWT configuration can be managed in the `[Keys API](/docs/apis/keys)` and Keymaster. + + In version 1.6.0 and beyond, JWT configuration can be managed in the [Keys API](/docs/apis/keys) and Keymaster. + Indicates if this application is using the JWT configuration defined here or the global JWT configuration defined by the Tenant. If this is `false` the signing algorithm configured in the Tenant will be used. If `true` the signing algorithm defined in this application will be used. @@ -80,12 +83,16 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature The private key used when an `RSA` signing algorithm has been selected. The private key will be used to sign the JWT. This key will be returned in a PEM encoded format. - In version 1.6.0 and beyond, JWT configuration can be managed in the `[Keys API](/docs/apis/keys)` and Keymaster. + + In version 1.6.0 and beyond, JWT configuration can be managed in the [Keys API](/docs/apis/keys) and Keymaster. + The public key used when an `RSA` signing algorithms has been selected. The public key will be used to verify JWTs signed with the private key. This key will be returned in a PEM encoded format. - In version 1.6.0 and beyond, JWT configuration can be managed in the `[Keys API](/docs/apis/keys)` and Keymaster. + + In version 1.6.0 and beyond, JWT configuration can be managed in the [Keys API](/docs/apis/keys) and Keymaster. + The Refresh Token expiration policy. @@ -96,7 +103,7 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature * `SlidingWindow` - the expiration is calculated from the last time the token was used. * `SlidingWindowWithMaximumLifetime` - the expiration is calculated from the last time the token was used, or until the maximumTimeToLiveInMinutes is reached. Available since 1.46.0 - + The maximum lifetime of a refresh token when using a refreshTokenExpirationPolicy of `SlidingWindowWithMaximumLifetime`. @@ -104,18 +111,20 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature The length of time in minutes the JWT refresh token will live before it is expired and is not able to be exchanged for a JWT. - + The refresh token usage policy. The following are valid values: * `Reusable` - the token does not change after it was issued. * `OneTimeUse` - the token value will be changed each time the token is used to refresh a JWT. The client must store the new value after each usage. - + The secret used when an `HMAC` based signing algorithm has been selected. This secret is used to sign and verify JWTs. - In version 1.5.0 and beyond, when selecting an `HMAC` algorithm, the `client_secret` from the OAuth configuration will be used to sign and verify the JWTs. + + In version 1.5.0 and beyond, when selecting an `HMAC` algorithm, the `client_secret` from the OAuth configuration will be used to sign and verify the JWTs. + diff --git a/astro/src/content/docs/apis/_event-types.mdx b/astro/src/content/docs/apis/_event-types.mdx index 9aff887ed6..9790942873 100644 --- a/astro/src/content/docs/apis/_event-types.mdx +++ b/astro/src/content/docs/apis/_event-types.mdx @@ -1,45 +1,44 @@ import EnterpriseEditionBlurbApi from 'src/content/docs/_shared/_enterprise-edition-blurb-api.astro'; import PremiumEditionBlurbApi from 'src/content/docs/_shared/_premium-edition-blurb-api.astro'; -import APIField from 'src/components/api/APIField.astro'; import AvailableSince from 'src/components/api/AvailableSince.astro'; -* audit-log.create - When an audit log is created -* event-log.create - When an event log is created +* audit-log.create - When an audit log is created +* event-log.create - When an event log is created * jwt.public-key.update - When a JWT RSA Public / Private keypair may have been changed -* jwt.refresh - When an access token is refreshed using a refresh token +* jwt.refresh - When an access token is refreshed using a refresh token * jwt.refresh-token.revoke - When a JWT Refresh Token is revoked -* kickstart.success - When kickstart has successfully completed +* kickstart.success - When kickstart has successfully completed * user.action - When a user action is triggered * user.bulk.create - When multiple users are created in bulk (i.e. during an import) * user.create - When a user is created -* user.create.complete - When a user create transaction has completed +* user.create.complete - When a user create transaction has completed * user.deactivate - When a user is deactivated * user.delete - When a user is deleted -* user.delete.complete - When a user delete transaction has completed -* user.email.update - When a user updates their email address -* user.email.verified - When a user verifies their email address -* user.identity-provider.link - When a link is created from a user to an Identity Provider +* user.delete.complete - When a user delete transaction has completed +* user.email.update - When a user updates their email address +* user.email.verified - When a user verifies their email address +* user.identity-provider.link - When a link is created from a user to an Identity Provider * user.identity-provider.unlink - When an existing Identity Provider link is removed from a User -* user.loginId.duplicate.create - When a request to create a user with a login Id (email or username) which is already in use has been received the `user.loginId.duplicate.create` event -* user.loginId.duplicate.update - When a request to update a user and change their login Id (email or username) to one that is already in use has been received
    the ``user.loginId.duplicate.update`` event +* user.loginId.duplicate.create - When a request to create a user with a login Id (email or username) which is already in use has been received the `user.loginId.duplicate.create` event +* user.loginId.duplicate.update - When a request to update a user and change their login Id (email or username) to one that is already in use has been received
    the ``user.loginId.duplicate.update`` event * user.login.failed - When a user fails a login request -* user.login.new-device - When a user begins a login request with a new device
    the ``user.login.new-device`` event -* user.login.success - When a user completes a login request -* user.login.suspicious - When a user logs in and is considered to be a potential threat (requires an activated Enterprise license)
    the ``user.login.suspicious`` event -* user.password.breach - When Reactor detects a user is using a potentially breached password (requires an activated license)
    the ``user.password.breach`` event -* user.password.reset.send - When a forgot password email has been sent to a user
    the ``user.password.reset.send`` event -* user.password.reset.start - When the process to reset a user password has started
    the ``user.password.reset.start`` event -* user.password.reset.success - When a user has successfully reset their password
    the ``user.password.reset.success`` event -* user.password.update - When a user has updated their password
    the ``user.password.update`` event +* user.login.new-device - When a user begins a login request with a new device
    the ``user.login.new-device`` event +* user.login.success - When a user completes a login request +* user.login.suspicious - When a user logs in and is considered to be a potential threat (requires an activated Enterprise license)
    the ``user.login.suspicious`` event +* user.password.breach - When Reactor detects a user is using a potentially breached password (requires an activated license)
    the ``user.password.breach`` event +* user.password.reset.send - When a forgot password email has been sent to a user
    the ``user.password.reset.send`` event +* user.password.reset.start - When the process to reset a user password has started
    the ``user.password.reset.start`` event +* user.password.reset.success - When a user has successfully reset their password
    the ``user.password.reset.success`` event +* user.password.update - When a user has updated their password
    the ``user.password.update`` event * user.reactivate - When a user is reactivated -* user.registration.create - When a user registration is created -* user.registration.create.complete - When a user registration create transaction has completed -* user.registration.delete - When a user registration is deleted -* user.registration.delete.complete - When a user registration delete transaction has completed -* user.registration.update - When a user registration is updated -* user.registration.update.complete - When a user registration update transaction has completed -* user.registration.verified - When a user completes registration verification -* user.two-factor.method.add - When a user has added a two-factor method
    the ``user.two-factor.method.add`` event +* user.registration.create - When a user registration is created +* user.registration.create.complete - When a user registration create transaction has completed +* user.registration.delete - When a user registration is deleted +* user.registration.delete.complete - When a user registration delete transaction has completed +* user.registration.update - When a user registration is updated +* user.registration.update.complete - When a user registration update transaction has completed +* user.registration.verified - When a user completes registration verification +* user.two-factor.method.add - When a user has added a two-factor method
    the ``user.two-factor.method.add`` event * user.two-factor.method.remove - When a user has removed a two-factor method
    the ``user.two-factor.method.remove`` event * user.update - When a user is updated -* user.update.complete - When a user update transaction has completed +* user.update.complete - When a user update transaction has completed diff --git a/astro/src/content/docs/apis/_integration-request-body.mdx b/astro/src/content/docs/apis/_integration-request-body.mdx index 4248b94392..0d240cd7d9 100644 --- a/astro/src/content/docs/apis/_integration-request-body.mdx +++ b/astro/src/content/docs/apis/_integration-request-body.mdx @@ -33,39 +33,39 @@ import JSON from 'src/components/JSON.astro'; The Twilio Account ID to use when connecting to the Twilio API. This can be found in your Twilio dashboard. Required when the Twilio integration is enabled. - - + In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). - + +
    The Twilio Auth Token to use when connecting to the Twilio API. This can be found in your Twilio dashboard. Required when the Twilio integration is enabled. - - - In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + + In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + True if the Twilio integration is enabled. - - - In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + + In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + The configured Twilio phone number that will be used to send messages. This can be found in your Twilio dashboard. - - - In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + + In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + The Twilio message service Id, this is used when using Twilio Copilot to load balance between numbers. This can be found in your Twilio dashboard. When using the Twilio Messaging Services Id, you may omit the fromPhoneNumber field. - - - In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + + In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + diff --git a/astro/src/content/docs/apis/_integration-response-body.mdx b/astro/src/content/docs/apis/_integration-response-body.mdx index 8b51faf7a3..5e93e532c6 100644 --- a/astro/src/content/docs/apis/_integration-response-body.mdx +++ b/astro/src/content/docs/apis/_integration-response-body.mdx @@ -33,39 +33,39 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; The Twilio Account ID to use when connecting to the Twilio API. This can be found in your Twilio dashboard. - - - In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + + In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + The Twilio Auth Token to use when connecting to the Twilio API. This can be found in your Twilio dashboard. - - - In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + + In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + True if the Twilio integration is enabled. - - - In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + + In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + The configured Twilio phone number that will be used to send messages. This can be found in your Twilio dashboard. - - - In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + + In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + The Twilio message service Id, this is used when using Twilio Copilot to load balance between numbers. This can be found in your Twilio dashboard. When using the Twilio Messaging Services Id, you may omit the fromPhoneNumber field. - - - In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + + In version 1.26.0 and beyond, Twilio configuration can be managed in the [Messengers API](/docs/apis/messengers/). + diff --git a/astro/src/content/docs/apis/_lambda-request-body.mdx b/astro/src/content/docs/apis/_lambda-request-body.mdx index 9b5a139fda..f443be509d 100644 --- a/astro/src/content/docs/apis/_lambda-request-body.mdx +++ b/astro/src/content/docs/apis/_lambda-request-body.mdx @@ -1,6 +1,7 @@ import APIBlock from 'src/components/api/APIBlock.astro'; import APIField from 'src/components/api/APIField.astro'; import LambdaOptions from './_lambda-engine-options.mdx'; +import LambdaType from './_lambda-type.astro'; #### Request Body @@ -20,5 +21,6 @@ import LambdaOptions from './_lambda-engine-options.mdx'; The name of the lambda. + diff --git a/astro/src/content/docs/apis/_lambda-response-body.mdx b/astro/src/content/docs/apis/_lambda-response-body.mdx index 12d6ea84b4..b8b893612d 100644 --- a/astro/src/content/docs/apis/_lambda-response-body.mdx +++ b/astro/src/content/docs/apis/_lambda-response-body.mdx @@ -1,6 +1,7 @@ import APIBlock from 'src/components/api/APIBlock.astro'; import APIField from 'src/components/api/APIField.astro'; import LambdaOptions from './_lambda-engine-options.mdx'; +import LambdaType from './_lambda-type.astro'; #### Response Body @@ -29,5 +30,6 @@ import LambdaOptions from './_lambda-engine-options.mdx'; The name of the lambda. + diff --git a/astro/src/content/docs/apis/_lambda-responses-body.mdx b/astro/src/content/docs/apis/_lambda-responses-body.mdx index e713498b72..fa3705ff67 100644 --- a/astro/src/content/docs/apis/_lambda-responses-body.mdx +++ b/astro/src/content/docs/apis/_lambda-responses-body.mdx @@ -1,6 +1,7 @@ import APIBlock from 'src/components/api/APIBlock.astro'; import APIField from 'src/components/api/APIField.astro'; import LambdaOptions from './_lambda-engine-options.mdx'; +import LambdaType from './_lambda-type.astro'; #### Response Body @@ -32,5 +33,6 @@ import LambdaOptions from './_lambda-engine-options.mdx'; The name of the lambda. + diff --git a/astro/src/content/docs/apis/_lambda-search-request-parameters.mdx b/astro/src/content/docs/apis/_lambda-search-request-parameters.mdx index 667d67187d..892db0ac7b 100644 --- a/astro/src/content/docs/apis/_lambda-search-request-parameters.mdx +++ b/astro/src/content/docs/apis/_lambda-search-request-parameters.mdx @@ -3,6 +3,7 @@ import APIField from 'src/components/api/APIField.astro'; import InlineField from 'src/components/InlineField.astro'; import DeprecatedSince from 'src/components/api/DeprecatedSince.astro'; import RemovedSince from 'src/components/api/RemovedSince.astro'; +import LambdaType from './_lambda-type.astro'; {/* parameter_prefix is either blank for parameters or "search." for body */} @@ -37,4 +38,5 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; For example, if the total search results are greater than the page size designated by numberOfResults, set this value to `25` to retrieve results `26-50`, assuming the default page size.
    + diff --git a/astro/src/content/docs/apis/_lambda-type-api.astro b/astro/src/content/docs/apis/_lambda-type.astro similarity index 75% rename from astro/src/content/docs/apis/_lambda-type-api.astro rename to astro/src/content/docs/apis/_lambda-type.astro index 556c401166..816f4d7a9c 100644 --- a/astro/src/content/docs/apis/_lambda-type-api.astro +++ b/astro/src/content/docs/apis/_lambda-type.astro @@ -4,12 +4,27 @@ import { LambdaDoc } from 'src/tools/docs'; import APIField from 'src/components/api/APIField.astro'; import AvailableSince from "../../../components/api/AvailableSince.astro"; +interface Props { + prefix?: String, + showRequired?: boolean, + showSince?: boolean +} + const lambdasEntry = await getEntry('json', 'lambdas'); const lambdas: LambdaDoc[] = (lambdasEntry.data as LambdaDoc[]) .sort((a, b) => a.typeText.localeCompare(b.typeText)); const { prefix, showRequired, showSince } = Astro.props; + +if (typeof prefix !== 'undefined' && prefix !== '') { + if (!prefix.endsWith(".")) { + throw new Error(`Prefix, if provided, must end with a ".". Prefix: '${prefix}'`); + } +} + const name = `${prefix || ''}type`; + + ---

    The lambda type. The possible values are:

    diff --git a/astro/src/content/docs/apis/_standard-delete-response-codes.astro b/astro/src/content/docs/apis/_standard-delete-response-codes.astro index 5da44d17f7..d2b84b8df2 100644 --- a/astro/src/content/docs/apis/_standard-delete-response-codes.astro +++ b/astro/src/content/docs/apis/_standard-delete-response-codes.astro @@ -26,7 +26,7 @@ const {success_code, success_message, async_enabled, never_search_error, no_erro 200 { success_code ? { success_message } - : The request was successful. The response will contain a JSON body. + : The request was successful. } {async_enabled && diff --git a/astro/src/content/docs/apis/_system-configuration-request-body.mdx b/astro/src/content/docs/apis/_system-configuration-request-body.mdx index 415b2b9ddd..8098013c1b 100644 --- a/astro/src/content/docs/apis/_system-configuration-request-body.mdx +++ b/astro/src/content/docs/apis/_system-configuration-request-body.mdx @@ -94,6 +94,12 @@ import JSON from 'src/components/JSON.astro'; > Example: `FFFFFF` would set the menu font color to white.
    + + Whether or not FusionAuth should delete Webhook Event Logs based upon this configuration. When `true` the webhookEventLogConfiguration.delete.numberOfDaysToRetain will be used to identify webhook event logs that are eligible for deletion. When this value is set to `false` webhook event logs will be preserved forever. + + + The number of days to retain Webhook Event Logs. Required when webhookEventLogConfiguration.delete.enabled is set to `true`. + diff --git a/astro/src/content/docs/apis/_system-configuration-response-body.mdx b/astro/src/content/docs/apis/_system-configuration-response-body.mdx index 30e8421092..58ef76070a 100644 --- a/astro/src/content/docs/apis/_system-configuration-response-body.mdx +++ b/astro/src/content/docs/apis/_system-configuration-response-body.mdx @@ -76,6 +76,12 @@ import JSON from 'src/components/JSON.astro'; A hexadecimal color to override the default menu font color in the user interface. + + Whether or not FusionAuth should delete Webhook Event Logs based upon this configuration. When `true` the webhookEventLogConfiguration.delete.numberOfDaysToRetain will be used to identify webhook event logs that are eligible for deletion. When this value is set to `false` webhook event logs will be preserved forever. + + + The number of days to retain Webhook Event Logs. + diff --git a/astro/src/content/docs/apis/_tenant-request-body.mdx b/astro/src/content/docs/apis/_tenant-request-body.mdx index 5570fb3be4..32faa0cf61 100644 --- a/astro/src/content/docs/apis/_tenant-request-body.mdx +++ b/astro/src/content/docs/apis/_tenant-request-body.mdx @@ -25,7 +25,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx';
    - The type of captcha method to use. This field is required when tenant.captchaConfiguration.enabled is set to `true`. The possible values are: + The type of CAPTCHA method to use. This field is required when tenant.captchaConfiguration.enabled is set to `true`. The possible values are: @@ -34,20 +34,20 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; - Whether captcha configuration is enabled. + Whether CAPTCHA configuration is enabled. - The secret key for this captcha method. This field is required when tenant.captchaConfiguration.enabled is set to `true`. + The secret key for this CAPTCHA method. This field is required when tenant.captchaConfiguration.enabled is set to `true`. - The site key for this captcha method. This field is required when tenant.captchaConfiguration.enabled is set to `true`. + The site key for this CAPTCHA method. This field is required when tenant.captchaConfiguration.enabled is set to `true`. @@ -170,11 +170,17 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; + The time in seconds until an external authentication Id is no longer valid and cannot be used by the Token API. Value must be greater than 0. Prior to version `1.28.0` this value was required. + + + The time in seconds until a Login Timeout identifier is no longer valid to complete post-authentication steps in the OAuth workflow. Must be greater than 0. + + The time in seconds until a One Time Password is no longer valid and cannot be used by the Login API. Value must be greater than 0. @@ -424,7 +430,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; * `Fixed` - the expiration is calculated from the time the token is issued. * `SlidingWindow` - the expiration is calculated from the last time the token was used. - * `SlidingWindowWithMaximumLifetime` - the expiration is calculated from the last time the token was used, or until the maximumTimeToLiveInMinutes is reached.   + * `SlidingWindowWithMaximumLifetime` - the expiration is calculated from the last time the token was used, or until the maximumTimeToLiveInMinutes is reached.   @@ -466,8 +472,12 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; Prior to version `1.28.0` this value was required. + + The Id of the lambda that will be invoked at the end of a successful login request in order to extend custom validation of a login request. + + - The Id of a SCIM User Request Lambda that will be used to convert the SCIM Enterprise User request to a FusionAuth User. + The Id of a SCIM User Request lambda that will be used to convert the SCIM Enterprise User request to a FusionAuth User. @@ -475,7 +485,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; - The Id of a SCIM User Response Lambda that will be used to convert a FusionAuth Enterprise User to a SCIM Server response. + The Id of a SCIM User Response lambda that will be used to convert a FusionAuth Enterprise User to a SCIM Server response. @@ -483,7 +493,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; - The Id of a SCIM Group Request Lambda that will be used to convert the SCIM Group request to a FusionAuth Group. + The Id of a SCIM Group Request lambda that will be used to convert the SCIM Group request to a FusionAuth Group. @@ -491,7 +501,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; - The Id of a SCIM Group Response Lambda that will be used to convert a FusionAuth Group to a SCIM Server response. + The Id of a SCIM Group Response lambda that will be used to convert a FusionAuth Group to a SCIM Server response. @@ -499,7 +509,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; - The Id of a SCIM User Request Lambda that will be used to convert the SCIM User request to a FusionAuth User. + The Id of a SCIM User Request lambda that will be used to convert the SCIM User request to a FusionAuth User. @@ -507,7 +517,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; - The Id of a SCIM User Response Lambda that will be used to convert a FusionAuth User to a SCIM Server response. + The Id of a SCIM User Response lambda that will be used to convert a FusionAuth User to a SCIM Server response. @@ -565,7 +575,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; * `Enabled` - Require a two-factor challenge during login when an eligible method is available. * `Disabled` - Do not require a two-factor challenge during login. - * `Required` - Require a two-factor challenge during login. A user will be required to configure 2FA if no eligible methods are available. + * `Required` - Require a two-factor challenge during login. A user will be required to configure 2FA if no eligible methods are available. diff --git a/astro/src/content/docs/apis/_tenant-response-body-base.mdx b/astro/src/content/docs/apis/_tenant-response-body-base.mdx index 5c61ebc261..28c6aec0e4 100644 --- a/astro/src/content/docs/apis/_tenant-response-body-base.mdx +++ b/astro/src/content/docs/apis/_tenant-response-body-base.mdx @@ -139,6 +139,10 @@ import JSON from 'src/components/JSON.astro'; The time in seconds until an external authentication Id is no longer valid and cannot be used by the Token API. Value must be greater than 0. + + The time in seconds until a Login Timeout identifier is no longer valid to complete post-authentication steps in the OAuth workflow. Must be greater than 0. + + The time in seconds until a One Time Password is no longer valid and cannot be used by the Login API. Value must be greater than 0. @@ -338,7 +342,7 @@ import JSON from 'src/components/JSON.astro'; * `Fixed` - the expiration is calculated from the time the token is issued. * `SlidingWindow` - the expiration is calculated from the last time the token was used. - * `SlidingWindowWithMaximumLifetime` - the expiration is calculated from the last time the token was used, or until the maximumTimeToLiveInMinutes is reached.   + * `SlidingWindowWithMaximumLifetime` - the expiration is calculated from the last time the token was used, or until the maximumTimeToLiveInMinutes is reached.  
    @@ -372,6 +376,10 @@ import JSON from 'src/components/JSON.astro'; The length of time in seconds this JWT is valid from the time it was issued. Value must be greater than 0. + + The Id of the lambda that will be invoked at the end of a successful login request in order to extend custom validation of a login request. + + The Id of a SCIM User Request Lambda that will be used to convert the SCIM Enterprise User request to a FusionAuth User. diff --git a/astro/src/content/docs/apis/_user-registration-combined-response-body.mdx b/astro/src/content/docs/apis/_user-registration-combined-response-body.mdx index c65ba33543..863fe7cea6 100644 --- a/astro/src/content/docs/apis/_user-registration-combined-response-body.mdx +++ b/astro/src/content/docs/apis/_user-registration-combined-response-body.mdx @@ -50,9 +50,9 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; For example, if this user has authenticated using the Facebook Identity Provider, the Facebook access token will be available in this map, keyed by name `Facebook`. For an OpenID Connect Identity provider, or other generic providers, if a token is stored it will be keyed by the Identity Provider unique Id. - - - The token returned and stored from the Identity Provider is now stored in the IdP link and is retrievable using the Identity Provider [Link API](/docs/apis/identity-providers/links). + + The token returned and stored from the Identity Provider is now stored in the IdP link and is retrievable using the Identity Provider [Link API](/docs/apis/identity-providers/links). +
    The username of the User for this Application. It is for display purposes only. diff --git a/astro/src/content/docs/apis/_user-registration-response-body.mdx b/astro/src/content/docs/apis/_user-registration-response-body.mdx index e463a1376e..0d008c48f4 100644 --- a/astro/src/content/docs/apis/_user-registration-response-body.mdx +++ b/astro/src/content/docs/apis/_user-registration-response-body.mdx @@ -49,9 +49,9 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; For example, if this user has authenticated using the Facebook Identity Provider, the Facebook access token will be available in this map, keyed by name `Facebook`. For an OpenID Connect Identity provider, or other generic providers, if a token is stored it will be keyed by the Identity Provider unique Id. - - - The token returned and stored from the Identity Provider is now stored in the IdP link and is retrievable using the Identity Provider [Link API](/docs/apis/identity-providers/links). + + The token returned and stored from the Identity Provider is now stored in the IdP link and is retrievable using the Identity Provider [Link API](/docs/apis/identity-providers/links). + The username of the User for this Application only. diff --git a/astro/src/content/docs/apis/_user-response-body.mdx b/astro/src/content/docs/apis/_user-response-body.mdx index c15a413e3c..8b32ba67f0 100644 --- a/astro/src/content/docs/apis/_user-response-body.mdx +++ b/astro/src/content/docs/apis/_user-response-body.mdx @@ -153,9 +153,9 @@ import UserLoginFieldsResponse from 'src/content/docs/apis/_user-login-response. For example, if this user has authenticated using the Facebook Identity Provider, the Facebook access token will be available in this map, keyed by name `Facebook`. For an OpenID Connect Identity provider, or other generic providers, if a token is stored it will be keyed by the Identity Provider unique Id. - - - The token returned and stored from the Identity Provider is now stored in the IdP link and is retrievable using the Identity Provider [Link API](/docs/apis/identity-providers/links). + + The token returned and stored from the Identity Provider is now stored in the IdP link and is retrievable using the Identity Provider [Link API](/docs/apis/identity-providers/links). + The username of the User for this registration only. This is for display purposes and cannot be used to login. diff --git a/astro/src/content/docs/apis/_users-response-body.mdx b/astro/src/content/docs/apis/_users-response-body.mdx index 4efdfc392a..7306059a71 100644 --- a/astro/src/content/docs/apis/_users-response-body.mdx +++ b/astro/src/content/docs/apis/_users-response-body.mdx @@ -151,9 +151,9 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; For example, if this user has authenticated using the Facebook Identity Provider, the Facebook access token will be available in this map, keyed by name Facebook. For an OpenID Connect Identity provider, or other generic providers, if a token is stored it will be keyed by the Identity Provider unique Id. - - - The token returned and stored from the Identity Provider is now stored in the IdP link and is retrievable using the Identity Provider [Link API](/docs/apis/identity-providers/links). + + The token returned and stored from the Identity Provider is now stored in the IdP link and is retrievable using the Identity Provider [Link API](/docs/apis/identity-providers/links). + The username of the User for this registration only. This is for display purposes and cannot be used to login. diff --git a/astro/src/content/docs/apis/_webhook-attempt-log-response-body-base.mdx b/astro/src/content/docs/apis/_webhook-attempt-log-response-body-base.mdx new file mode 100644 index 0000000000..ec7376ad76 --- /dev/null +++ b/astro/src/content/docs/apis/_webhook-attempt-log-response-body-base.mdx @@ -0,0 +1,36 @@ +import APIBlock from 'src/components/api/APIBlock.astro'; +import APIField from 'src/components/api/APIField.astro'; + + + + An object that can hold additional details of a webhook attempt log. + + + The [instant](/docs/reference/data-types#instants) the attempt received a response or timed out. + + + The unique Id of this webhook attempt. + + + The [instant](/docs/reference/data-types#instants) the attempt request was sent. + + + The `exception` field from the event receiver if it was present on the response. + + + The HTTP status code from the event response. + + + The fully qualified URL that was used to send the event to the webhook receiver. + + This field will be omitted from the response if this attempt was sent to a Kafka topic. + + + The unique Id for the associated webhook event log. + + + The unique Id of the configured webhook. + + This field will be omitted from the response if this attempt was sent to a Kafka topic. + + diff --git a/astro/src/content/docs/apis/_webhook-attempt-log-response-body.mdx b/astro/src/content/docs/apis/_webhook-attempt-log-response-body.mdx new file mode 100644 index 0000000000..6d1fbd6b71 --- /dev/null +++ b/astro/src/content/docs/apis/_webhook-attempt-log-response-body.mdx @@ -0,0 +1,8 @@ +import JSON from 'src/components/JSON.astro'; +import WebhookAttemptLogResponseBodyBase from 'src/content/docs/apis/_webhook-attempt-log-response-body-base.mdx'; + +#### Response Body + + + + diff --git a/astro/src/content/docs/apis/_webhook-event-log-response-body-base.mdx b/astro/src/content/docs/apis/_webhook-event-log-response-body-base.mdx new file mode 100644 index 0000000000..707dd17885 --- /dev/null +++ b/astro/src/content/docs/apis/_webhook-event-log-response-body-base.mdx @@ -0,0 +1,56 @@ +import APIBlock from 'src/components/api/APIBlock.astro'; +import APIField from 'src/components/api/APIField.astro'; +import EventTypes from 'src/content/docs/apis/_event-types.mdx'; +import InlineField from 'src/components/InlineField.astro'; +import WebhookAttemptLogResponseBodyBase from 'src/content/docs/apis/_webhook-attempt-log-response-body-base.mdx'; + + + + An array of attempts for this event. + + + + An object that can hold additional details of a webhook event log. + + + Contains the full event request payload. The contents vary by [event](/docs/extend/events-and-webhooks/events) type. + + + The overall result of a [transactional](/docs/extend/events-and-webhooks/events#transaction-compatibility) event. Possible values are: + * `Running` - The default state after an event is fired. + * `Succeeded` - The transactional event was successful, and pending database changes were committed. Non-transactional events are transitioned to this state immediately after the event payload is sent to all recipients regardless of the response. + * `Failed` - The transactional event was unsuccessful, and pending database changes were rolled back. + + + The event type. Possible values are: + + + + + The number of failed event send attempts. Aggregate based on failed attempts. + + + The webhook event log unique Id. + + + The [instant](/docs/reference/data-types#instants) when the Webhook Event Log was created. + + + The [instant](/docs/reference/data-types#instants) the last attempt was made to send the event. + + + The [instant](/docs/reference/data-types#instants) when the Webhook Event Log was lasted updated. + + + If present, contains the unique Id of the associated object. The object type the Id references varies based on { props.base_field_name + ".eventType" } + + + An auto-incremented database field to maintain order of events. + + + The number of successful event send attempts. Aggregate based on successful attempts. + + + The total number of Webhook Event Logs matching the search criteria. Use this value along with the numberOfResults and startRow in the Search request to perform pagination. + + diff --git a/astro/src/content/docs/apis/_webhook-event-log-response-body.mdx b/astro/src/content/docs/apis/_webhook-event-log-response-body.mdx new file mode 100644 index 0000000000..1bfb6b2d3b --- /dev/null +++ b/astro/src/content/docs/apis/_webhook-event-log-response-body.mdx @@ -0,0 +1,8 @@ +import JSON from 'src/components/JSON.astro'; +import WebhookEventLogResponseBodyBase from 'src/content/docs/apis/_webhook-event-log-response-body-base.mdx'; + +#### Response Body + + + + diff --git a/astro/src/content/docs/apis/_webhook-event-log-search-response-body.mdx b/astro/src/content/docs/apis/_webhook-event-log-search-response-body.mdx new file mode 100644 index 0000000000..9f56227e3b --- /dev/null +++ b/astro/src/content/docs/apis/_webhook-event-log-search-response-body.mdx @@ -0,0 +1,5 @@ +import WebhookEventLogResponseBodyBase from 'src/content/docs/apis/_webhook-event-log-response-body-base.mdx'; + +#### Response Body + + diff --git a/astro/src/content/docs/apis/_webhook-request-body.mdx b/astro/src/content/docs/apis/_webhook-request-body.mdx index b95c8ecfe1..2e8f3171d1 100644 --- a/astro/src/content/docs/apis/_webhook-request-body.mdx +++ b/astro/src/content/docs/apis/_webhook-request-body.mdx @@ -1,5 +1,6 @@ import APIBlock from 'src/components/api/APIBlock.astro'; import APIField from 'src/components/api/APIField.astro'; +import BeforeVersion from 'src/components/api/BeforeVersion.astro'; import DeprecatedSince from 'src/components/api/DeprecatedSince.astro'; import EventTypes from 'src/content/docs/apis/_event-types.mdx'; import InlineField from 'src/components/InlineField.astro'; @@ -12,8 +13,9 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; The Ids of the Applications that this Webhook should be associated with. If no Ids are specified and the global field is `false`, this Webhook will not be used. Typically global should be set to `true`. - - In version 1.37.0 and beyond, Webhooks are optionally associated with Tenants instead of Applications. See new field tenantIds. + + In version 1.37.0 and beyond, Webhooks are optionally associated with Tenants instead of Applications. See new field tenantIds. + @@ -42,10 +44,9 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; Whether or not this Webhook is used for all Tenants or just for specific Tenants. -

    - Before 1.37.0 -

    + Whether or not this Webhook is used for all events or just for specific Applications. In almost all cases you want to set this field to `true` and filter on the application Id when processing the webhook. +
    An object that contains headers that are sent as part of the HTTP request for the events. @@ -67,10 +68,10 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; An SSL certificate in PEM format that is used to establish the SSL (TLS specifically) connection to the Webhook. - - - In version 1.48.0 and beyond, the webhook SSL certificate can be managed via webhook.sslCertificateKeyId. This field is not allowed on a request when webhook.sslCertificateKeyId is provided. + + In version 1.48.0 and beyond, the webhook SSL certificate can be managed via webhook.sslCertificateKeyId. This field is not allowed on a request when webhook.sslCertificateKeyId is provided. + The Id of an existing [Key](/docs/apis/keys). The X.509 certificate is used for client certificate authentication in requests to the Webhook. diff --git a/astro/src/content/docs/apis/_webhook-response-body-base.mdx b/astro/src/content/docs/apis/_webhook-response-body-base.mdx index fd3d01081f..ec11e6ca25 100644 --- a/astro/src/content/docs/apis/_webhook-response-body-base.mdx +++ b/astro/src/content/docs/apis/_webhook-response-body-base.mdx @@ -20,12 +20,9 @@ import RemovedSince from 'src/components/api/RemovedSince.astro'; The Ids of the Applications that this Webhook is associated with. If no Ids are returned and the global field is `false`, this Webhook is not used. Typically global should be set to `true`.

    -

    - -

    -

    - In version 1.37.0 and beyond, Webhooks are optionally associated with Tenants instead of Applications. See new field tenantIds. -

    + + In version 1.37.0 and beyond, Webhooks are optionally associated with Tenants instead of Applications. See new field tenantIds. +
    @@ -101,10 +98,10 @@ import RemovedSince from 'src/components/api/RemovedSince.astro';
    An SSL certificate in PEM format that is used to establish the SSL (TLS specifically) connection to the Webhook. - - - In version 1.48.0 and beyond, the webhook SSL certificate can be managed via webhook.sslCertificateKeyId. + + In version 1.48.0 and beyond, the webhook SSL certificate can be managed via webhook.sslCertificateKeyId. + The Id of an existing [Key](/docs/apis/keys). The X.509 certificate is used for client certificate authentication in requests to the Webhook. diff --git a/astro/src/content/docs/apis/authentication.mdx b/astro/src/content/docs/apis/authentication.mdx index 737d4a17bc..37f280041d 100644 --- a/astro/src/content/docs/apis/authentication.mdx +++ b/astro/src/content/docs/apis/authentication.mdx @@ -175,7 +175,6 @@ Prior to version `1.26.0`, the FusionAuth administrative user interface was the ### Create an API Key Create an API Key -{/* /img/docs/apis/create-api-key.png */} #### Form Fields diff --git a/astro/src/content/docs/apis/entities/grants.mdx b/astro/src/content/docs/apis/entities/grants.mdx index 13432cbd97..015e8d2e1b 100644 --- a/astro/src/content/docs/apis/entities/grants.mdx +++ b/astro/src/content/docs/apis/entities/grants.mdx @@ -75,7 +75,7 @@ This is an upsert operation. If the grant to this Entity for the specified User This API does not return a JSON response body. - + ## Retrieve Grants diff --git a/astro/src/content/docs/apis/families.mdx b/astro/src/content/docs/apis/families.mdx index 8f4da8179e..f235bc444e 100644 --- a/astro/src/content/docs/apis/families.mdx +++ b/astro/src/content/docs/apis/families.mdx @@ -200,4 +200,4 @@ This API is used to send an email requesting parental approval for a child regis This API does not return a JSON response body. - + diff --git a/astro/src/content/docs/apis/hosted-backend.mdx b/astro/src/content/docs/apis/hosted-backend.mdx index 4799e94b7b..c46f9dac77 100644 --- a/astro/src/content/docs/apis/hosted-backend.mdx +++ b/astro/src/content/docs/apis/hosted-backend.mdx @@ -37,7 +37,7 @@ _Cookies Set By the Hosted Backend_ | app.at | true | The access token for the configured application. This is a JWT and can be presented to your APIs to access data and functionality. | | app.rt | true | The refresh token for the configured application. Only present if the `offline_access` scope is requested. This can be presented to FusionAuth to retrieve a new access token. | | app.idt | false | The Id token for the user for the configured application. Only present if the `openid` scope is requested. This is a JWT and can be accessed by JavaScript to display user account information. | -| app.at_exp | false | The unix epoch timestamp indicating when the access token will expire. This can be checked by JavaScript to determine when a refresh token should be used to get a new access token. | +| app.at_exp | false | The UNIX epoch timestamp indicating when the access token will expire. This can be checked by JavaScript to determine when a refresh token should be used to get a new access token. | FusionAuth will set the domain on these cookies to `.example.com` where `example` is the domain name that FusionAuth is serving from either from the domain or any subdomain, `com` is the top-level domain, and the `.` allows the cookie to match the domain and all subdomains. If the host is a simple host name or IP address FusionAuth will set the domain to that (i.e. `localhost` or `127.0.0.1`). If FusionAuth is on a nested domain, then it will set cookies on the broadest domain that is not a top-level domain. @@ -66,7 +66,7 @@ To use this API, redirect the browser to this route. This is not meant to be cal The client Id for your Application. - The URL encoded URL that the browser will be redirected to at the end of the login flow. If provided, this URL must be included in the Authorized Redirect URLs array for your application. If not provided, the default will be the first value in the Authorized Redirect URLs array configured for your application. This parameter is validated the same as if it were being passed to `/oauth/authorize`, however when using this endpoint FusionAuth will pass as the redirect_uri to `/oauth2/authorize` as that route will handle the token exchange. + The URL encoded URL that the browser will be redirected to at the end of the login flow. If provided, this URL must be included in the Authorized Redirect URLs array for your application. If not provided, the default will be the first value in the Authorized Redirect URLs array configured for your application. This parameter is validated the same as if it were being passed to `/oauth2/authorize`, however when using this endpoint FusionAuth will pass as the redirect_uri to `/oauth2/authorize` as that route will handle the token exchange. The value of this parameter will be echoed back in the state parameter of the redirect URL at the end of the login flow. @@ -94,7 +94,7 @@ _Response Codes_ | Code | Description | |------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 200 | There was an error. The route will serve up an error page with html and details on what went wrong. | +| 200 | There was an error. The route will serve up an error page with HTML and details on what went wrong. | | 302 | A successful request will redirect the user to `/oauth2/authorize` to log in. | | 403 | A forbidden response typically means that the Origin of this request did not pass the FusionAuth CORS filter. Add your app origin to your [CORS Configuration](/docs/operate/secure-and-monitor/cors) as an Allowed Origin. | | 500 | There was a FusionAuth internal error. A stack trace is provided and logged in the FusionAuth log files. | @@ -118,7 +118,7 @@ To use this API, redirect the browser to this route. This is not meant to be cal The client Id for your Application. - The URL encoded URL that the browser will be redirected to at the end of the registration. If provided, this URL must be included in the Authorized Redirect URLs array for your application. If not provided, the default will be the first value in the Authorized Redirect URLs array configured for your application. This parameter is validated the same as if it were being passed to `/oauth/register`, however when using this endpoint FusionAuth will pass as the redirect_uri to `/oauth2/register` as that route will handle the token exchange. + The URL encoded URL that the browser will be redirected to at the end of the registration. If provided, this URL must be included in the Authorized Redirect URLs array for your application. If not provided, the default will be the first value in the Authorized Redirect URLs array configured for your application. This parameter is validated the same as if it were being passed to `/oauth2/register`, however when using this endpoint FusionAuth will pass as the redirect_uri to `/oauth2/register` as that route will handle the token exchange. The value of this parameter will be echoed back in the state parameter of the redirect URL at the end of the registration flow. @@ -146,7 +146,7 @@ _Response Codes_ | Code | Description | |------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 200 | There was an error. The route will serve up an error page with html and details on what went wrong. | +| 200 | There was an error. The route will serve up an error page with HTML and details on what went wrong. | | 302 | A successful request will redirect the user to `/oauth2/register` to register. | | 403 | A forbidden response typically means that the Origin of this request did not pass the FusionAuth CORS filter. Add your app origin to your [CORS Configuration](/docs/operate/secure-and-monitor/cors) as an Allowed Origin. | | 500 | There was a FusionAuth internal error. A stack trace is provided and logged in the FusionAuth log files. | @@ -189,7 +189,7 @@ _Response Codes_ | Code | Description | |------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 200 | There was an error. The route will serve up an error page with html and details on what went wrong. | +| 200 | There was an error. The route will serve up an error page with HTML and details on what went wrong. | | 302 | A successful request will redirect the user to `redirect_uri` specified in the request or the default Authorized Redirect URL configured for the Application. | | 500 | There was a FusionAuth internal error. A stack trace is provided and logged in the FusionAuth log files. | @@ -228,7 +228,7 @@ _Response Codes_ | Code | Description | |------|----------------------------------------------------------------------------------------------------------------| -| 200 | There was an error. The route will serve up an error page with html and details on what went wrong. | +| 200 | There was an error. The route will serve up an error page with HTML and details on what went wrong. | | 400 | The request was not successful. The client needs to reauthorize. Redirect the browser to the `Login` endpoint. | | 500 | There was a FusionAuth internal error. A stack trace is provided and logged in the FusionAuth log files. | @@ -238,7 +238,7 @@ _Response Codes_ ## Me -This api is used to retrieve information about the currently logged in user. This call will take the `app.at` cookie value and use that to call the `/oauth2/userinfo` API. +This API is used to retrieve information about the currently logged in user. This call will take the `app.at` cookie value and use that to call the `/oauth2/userinfo` API. This is an API request made from the client application and the browser must *NOT* be redirected to this endpoint. @@ -283,8 +283,8 @@ To use this API, redirect the browser to this route and the router will respond The client Id for your Application. - - The URL encoded URL that the browser will be redirected to at the end of the logout flow. If not provided, this will be the Logout URL configured for the Application. If another value is used, it must be defined in the Authorized Redirect URLs for the Application. + + The URL encoded URL that the browser will be redirected to at the end of the logout flow. This value must be in the Application's Authorized Redirect URLs list. If no `post_logout_redirect_uri` is provided, the user will be redirected to the Logout URL configured for the Application. @@ -301,6 +301,6 @@ _Response Codes_ | Code | Description | |------|----------------------------------------------------------------------------------------------------------| -| 200 | There was an error. The route will serve up an error page with html and details on what went wrong. | +| 200 | There was an error. The route will serve up an error page with HTML and details on what went wrong. | | 302 | A successful request will redirect the user to `/oauth2/logout` to complete the logout. | | 500 | There was a FusionAuth internal error. A stack trace is provided and logged in the FusionAuth log files. | diff --git a/astro/src/content/docs/apis/identity-providers/_identity-provider-login-request-body.astro b/astro/src/content/docs/apis/identity-providers/_identity-provider-login-request-body.astro index 7eb3845be6..e122dea37d 100644 --- a/astro/src/content/docs/apis/identity-providers/_identity-provider-login-request-body.astro +++ b/astro/src/content/docs/apis/identity-providers/_identity-provider-login-request-body.astro @@ -101,7 +101,7 @@ const show_code_and_token_examples = ['Facebook', 'Google'].includes(idp_display { idp_token_or_code === 'token or code' && } - The Steam Oauth access token returned from their login API. This token will be sent to the Steam Token Details API as the access_token parameter. + The Steam OAuth access token returned from their login API. This token will be sent to the Steam Token Details API as the access_token parameter. { idp_display_name === 'Facebook' && } @@ -132,17 +132,17 @@ const show_code_and_token_examples = ['Facebook', 'Google'].includes(idp_display { idp_display_name === 'Twitter' && -

    The Twitter oauth token returned from their login API. This token will be sent to the Twitter OAuth Access Token API as the oauth_token parameter.

    +

    The Twitter OAuth token returned from their login API. This token will be sent to the Twitter OAuth Access Token API as the oauth_token parameter.

    Since 1.25.0

    Beginning in version 1.25.0, if this value is an access token then it will not be sent to the Twitter OAuth Access Token API, and instead be directly used to call the Twitter Verify Credentials API to obtain user details. See notes in oauth_verifier.

    -

    The Twitter oauth token secret returned from their login API. This token will be used to sign the request to the OAuth Access Token API.

    +

    The Twitter OAuth token secret returned from their login API. This token will be used to sign the request to the OAuth Access Token API.

    Since 1.25.0

    Beginning in version 1.25.0, if this value is an access token then it will not be sent to the Twitter OAuth Access Token API, and instead be directly used to call the Twitter Verify Credentials API to obtain user details. See notes in oauth_verifier..

    -

    The Twitter oauth verifier returned from their login API. This token will be sent to the Twitter OAuth Access Token API in the request body as the oauth_verifier parameter.

    +

    The Twitter OAuth verifier returned from their login API. This token will be sent to the Twitter OAuth Access Token API in the request body as the oauth_verifier parameter.

    Since 1.25.0

    Beginning in version 1.25.0, you may optionally omit the oauth_verifier field if the values for oauth_token and oauth_token_secret are an access token. This allows for a use case where you are not using the FusionAuth themed login pages and you have integrated the Twitter login using this API and prior to calling FusionAuth you have already exchanged these values for a Twitter access token. In this scenario, you may take these two parameters representing the access token and FusionAuth will still complete the login for you by skipping the request to exchange the request token for an access token.

    diff --git a/astro/src/content/docs/apis/identity-providers/steam.mdx b/astro/src/content/docs/apis/identity-providers/steam.mdx index ef8f40dc27..5f4b669263 100644 --- a/astro/src/content/docs/apis/identity-providers/steam.mdx +++ b/astro/src/content/docs/apis/identity-providers/steam.mdx @@ -18,7 +18,7 @@ import OauthIdpOperations from 'src/content/docs/apis/identity-providers/_oauth- This API has been available since 1.28.0 -The Steam identity provider type will use the Steam OAuth login API. It will also provide a `Login with Steam` button on FusionAuth’s login page that will direct a user to the Steam login page. The Steam login uses the implicit OAuth grant and will return to the callback URL with `token` and `state` in the URL Fragment. This is handled by the FusionAuth `/oauth2/implicit` javascript function to pass those values to the `/oauth2/callback` endpoint. +The Steam identity provider type will use the Steam OAuth login API. It will also provide a `Login with Steam` button on FusionAuth’s login page that will direct a user to the Steam login page. The Steam login uses the implicit OAuth grant and will return to the callback URL with `token` and `state` in the URL Fragment. This is handled by the FusionAuth `/oauth2/implicit` JavaScript function to pass those values to the `/oauth2/callback` endpoint. This identity provider will call Steam's API to load the Steam user's `personaname` and use that as `username` to lookup or create a user in FusionAuth depending on the linking strategy configured for this identity provider. However, Steam does not allow access to user emails, so neither email linking strategy can be used and user’s will not be able to login or be created. diff --git a/astro/src/content/docs/apis/index.mdx b/astro/src/content/docs/apis/index.mdx index 46122866aa..8b692e241e 100644 --- a/astro/src/content/docs/apis/index.mdx +++ b/astro/src/content/docs/apis/index.mdx @@ -108,13 +108,13 @@ _PATCH options_ ### PATCH Example -Here's an example of how the different options work when used to modify the roles of a [Group](/docs/apis/groups) which has roles of "ceo" and "dev" to remove the "dev" role. +Here's an example of how the different options work when used to modify the roles of a [Group](/docs/apis/groups) which has roles of `ceo` and `dev` to remove the `dev` role. If you are only modifying specific object fields, all three `PATCH` methods are equivalent. #### Original -With the original, pre 1.39.0 `PATCH` method, the correct way to remove the "dev" role is to request the group JSON, find the "ceo" role from the `roleIds` array, and use `PUT` to update the group object. +With the original, pre 1.39.0 `PATCH` method, the correct way to remove the `dev` role is to request the group JSON, find the `ceo` role from the `roleIds` array, and use `PUT` to update the group object. diff --git a/astro/src/content/docs/apis/jwt.mdx b/astro/src/content/docs/apis/jwt.mdx index c46ede8cf8..a58688d754 100644 --- a/astro/src/content/docs/apis/jwt.mdx +++ b/astro/src/content/docs/apis/jwt.mdx @@ -31,7 +31,7 @@ Here's a presentation discussing how to use JWTs in a microservices architecture ## Issue a JWT This API is used to issue a new access token (JWT) using an existing access token (JWT). -This API provides the single signon mechanism for access tokens. For example you have an access token for application A and you need an access +This API provides the single sign-on mechanism for access tokens. For example you have an access token for application A and you need an access token for application B. You may use this API to request an access token to application B with the authorized token to application A. The returned access token will have the same expiration of the one provided. This API will use a JWT as authentication. See [JWT Authentication](/docs/apis/authentication#jwt-authentication) for examples of how you can send the JWT to FusionAuth. @@ -132,10 +132,10 @@ _Response Codes_ - The encoded access token. This cookie is written in the response as an `HTTPOnly` session cookie. + The encoded access token. This cookie is written in the response as an `HttpOnly` session cookie. - The refresh token. This cookie is written in the response as an `HTTPOnly` persistent cookie. The cookie expiration is configured in the JWT + The refresh token. This cookie is written in the response as an `HttpOnly` persistent cookie. The cookie expiration is configured in the JWT configuration for the application or the global JWT configuration. @@ -276,12 +276,12 @@ Cookie: refresh_token=xRxGGEpVawiUak6He367W3oeOfh+3irw+1G1h1jc; access_token=eyJ - The encoded access token. This cookie is written in the response as an `HTTPOnly` session cookie. + The encoded access token. This cookie is written in the response as an `HttpOnly` session cookie. The encoded refresh token. - This cookie is written in the response as an `HTTPOnly` cookie. When jwtConfiguration.refreshTokenUsagePolicy is equal to `Reusable` this will be equal to the refresh token provided in the request. When jwtConfiguration.refreshTokenUsagePolicy is equal to `OneTimeUse` a new value will be returned and the previous refresh token value will no longer be valid. + This cookie is written in the response as an `HttpOnly` cookie. When jwtConfiguration.refreshTokenUsagePolicy is equal to `Reusable` this will be equal to the refresh token provided in the request. When jwtConfiguration.refreshTokenUsagePolicy is equal to `OneTimeUse` a new value will be returned and the previous refresh token value will no longer be valid. The jwtConfiguration.refreshTokenUsagePolicy is configured at the tenant, and optionally per application. diff --git a/astro/src/content/docs/apis/lambdas.mdx b/astro/src/content/docs/apis/lambdas.mdx index 7b9f1e4f8f..62494aa386 100644 --- a/astro/src/content/docs/apis/lambdas.mdx +++ b/astro/src/content/docs/apis/lambdas.mdx @@ -21,7 +21,7 @@ import GenericUpdateExplanationFragment from 'src/content/docs/apis/_generic-upd import LambdaPutRequestBody from 'src/content/docs/apis/_lambda-put-request-body.mdx'; import StandardPutResponseCodes from 'src/content/docs/apis/_standard-put-response-codes.astro'; import StandardDeleteResponseCodes from 'src/content/docs/apis/_standard-delete-response-codes.astro'; -import LambdaTypeApi from './_lambda-type-api.astro'; +import LambdaType from './_lambda-type.astro'; export const singlePrefix = 'lambda.'; export const multiPrefix = 'lambda[x].'; @@ -51,8 +51,6 @@ This API is used to create a Lambda. - - ### Response @@ -62,7 +60,6 @@ The response for this API contains the Lambda that was created. - ## Retrieve a Lambda @@ -78,7 +75,7 @@ This API is used to retrieve a single Lambda by unique Id or all of the Lambdas. #### Request Parameters - + @@ -98,11 +95,9 @@ The response for this API contains either a single Lambda or all of the Lambdas. - - ## Search for Lambdas @@ -119,7 +114,6 @@ This API is used to search for Lambdas and may be called using the `GET` or `POS #### Request Parameters - @@ -128,7 +122,6 @@ When calling the API using a `POST` request you will send the search criteria in #### Request Body - @@ -139,7 +132,6 @@ The response for this API contains the Lambdas matching the search criteria in p - ## Update a Lambda @@ -148,7 +140,7 @@ The response for this API contains the Lambdas matching the search criteria in p The lambda type may not be changed. -/> + ### Request Parameters @@ -159,7 +151,6 @@ The lambda type may not be changed. -{/* no type include here because you can't change the type of a lambda after you create it. */} ### Response @@ -168,7 +159,6 @@ The response for this API contains the Lambda that was updated. - ## Delete a Lambda diff --git a/astro/src/content/docs/apis/reactor.mdx b/astro/src/content/docs/apis/reactor.mdx index 36b4bce873..53219f146a 100644 --- a/astro/src/content/docs/apis/reactor.mdx +++ b/astro/src/content/docs/apis/reactor.mdx @@ -46,7 +46,7 @@ This API is used to activate a Reactor license. This API does not return a JSON response body. - + ## Retrieve Reactor metrics diff --git a/astro/src/content/docs/apis/registrations.mdx b/astro/src/content/docs/apis/registrations.mdx index 7c29284c42..3ded577860 100644 --- a/astro/src/content/docs/apis/registrations.mdx +++ b/astro/src/content/docs/apis/registrations.mdx @@ -189,9 +189,9 @@ This API is used to mark a User Registration as verified. This is usually called The verification Id generated by FusionAuth used to verify the User's registration is valid by ensuring they have access to the provided email address. - - + This value can still be provided on the URL segment as shown in the above example, but it is recommended you send this value in the request body instead using the verificationId field. If the value is provided in the URL segment and in the request body, the value provided in the request body will be preferred. + diff --git a/astro/src/content/docs/apis/system.mdx b/astro/src/content/docs/apis/system.mdx index 83d517d1e3..76b9bea719 100644 --- a/astro/src/content/docs/apis/system.mdx +++ b/astro/src/content/docs/apis/system.mdx @@ -37,10 +37,6 @@ import PrometheusJvmGauges from 'src/content/docs/_shared/_prometheus-jvm-gauges This page contains the APIs that are used for retrieving and updating the system configuration. - - ## Retrieve the System Configuration This API is used to retrieve the System Configuration. diff --git a/astro/src/content/docs/apis/themes/advanced-themes.mdx b/astro/src/content/docs/apis/themes/advanced-themes.mdx index aead623806..0b6303fe39 100644 --- a/astro/src/content/docs/apis/themes/advanced-themes.mdx +++ b/astro/src/content/docs/apis/themes/advanced-themes.mdx @@ -120,7 +120,7 @@ The response for this API contains either a single Theme or all of the Themes. W @@ -158,7 +158,7 @@ The response for this API contains the Themes matching the search criteria in pa diff --git a/astro/src/content/docs/apis/themes/simple-themes.mdx b/astro/src/content/docs/apis/themes/simple-themes.mdx index 38338c8c8b..349aeb9809 100644 --- a/astro/src/content/docs/apis/themes/simple-themes.mdx +++ b/astro/src/content/docs/apis/themes/simple-themes.mdx @@ -119,7 +119,7 @@ The response for this API contains either a single Theme or all of the Themes. W @@ -154,7 +154,7 @@ The response for this API contains the Themes matching the search criteria in pa diff --git a/astro/src/content/docs/apis/users.mdx b/astro/src/content/docs/apis/users.mdx index 99970d77f0..dae42f96fd 100644 --- a/astro/src/content/docs/apis/users.mdx +++ b/astro/src/content/docs/apis/users.mdx @@ -632,9 +632,9 @@ This API is used to mark a User's email as verified. This is usually called afte The verification Id generated by FusionAuth used to verify the User's registration is valid by ensuring they have access to the provided email address. - - + This value can still be provided on the URL segment as shown in the above example, but it is recommended you send this value in the request body instead using the verificationId field. If the value is provided in the URL segment and in the request body, the value provided in the request body will be preferred. + @@ -817,7 +817,7 @@ If FusionAuth sends an email to the user, it will either use the `email` top lev ### Response {/* -this 'response codes' header has extra spacing, but to fix we'd have to convert the below table into a html table inside an astro component, like we did with astro/src/content/docs/apis/_change-pass-response-codes.astro +this 'response codes' header has extra spacing, but to fix we'd have to convert the below table into a HTML table inside an astro component, like we did with astro/src/content/docs/apis/_change-pass-response-codes.astro */} Response Codes |Code |Description | @@ -874,9 +874,9 @@ This usage is generally intended to be part of an email workflow and does not re If this `changePasswordId` was sent via an email to the User by FusionAuth during User create in order to set up a new password, or as part of a Forgot Password request, then successful use of this identifier to change the User's password will implicitly complete Email Verification if not already verified and the Tenant configuration has enabled implicit email verification. - - + This value can still be provided on the URL segment as shown in the above example, but it is recommended you send this value in the request body instead using the changePasswordId field. If the value is provided in the URL segment and in the request body, the value provided in the request body will be preferred. +
    diff --git a/astro/src/content/docs/apis/webhook-event-logs.mdx b/astro/src/content/docs/apis/webhook-event-logs.mdx new file mode 100644 index 0000000000..2c12bd55cd --- /dev/null +++ b/astro/src/content/docs/apis/webhook-event-logs.mdx @@ -0,0 +1,179 @@ +--- +title: Webhook Event Logs +description: Learn about the APIs for searching and retrieving webhook event and attempt logs. +section: apis +--- +import API from 'src/components/api/API.astro'; +import APIBlock from 'src/components/api/APIBlock.astro'; +import APIField from 'src/components/api/APIField.astro'; +import Aside from 'src/components/Aside.astro'; +import InlineField from 'src/components/InlineField.astro'; +import JSON from 'src/components/JSON.astro'; +import StandardGetResponseCodes from 'src/content/docs/apis/_standard-get-response-codes.astro'; +import WebhookAttemptLogResponseBody from 'src/content/docs/apis/_webhook-attempt-log-response-body.mdx'; +import WebhookEventLogResponseBody from 'src/content/docs/apis/_webhook-event-log-response-body.mdx'; +import WebhookEventLogSearchResponseBody from 'src/content/docs/apis/_webhook-event-log-search-response-body.mdx'; + +## Overview + + + +The Webhook Event Log contains a record of [Events](/docs/extend/events-and-webhooks/events) sent by FusionAuth, including request payloads. It also records attempts to send the event payload to [Webhook](/docs/extend/events-and-webhooks) and [Kafka](/docs/extend/events-and-webhooks/kafka) endpoints. + +Test events sent through the FusionAuth admin UI are not recorded in the Webhook Event Log. + +This page contains the APIs that are used to retrieve Webhook Event Logs and associated attempt details. Here are the APIs: + +## Retrieve a Webhook Event Log + +### Request + + + +#### Request Parameters + + + + The unique Id of the Webhook Event Log to retrieve. + + + +### Response + + + + + +## Retrieve a Webhook Attempt Log + +### Request + + + +#### Request Parameters + + + + The unique Id of the Webhook Attempt Log to retrieve. + + + +### Response + + + + + +## Search Webhook Event Logs + +### Request + + + +When calling the API using a `GET` request you will send the search criteria on the URL using request parameters. In order to simplify the example URL above, not every possible parameter is shown, however using the provided pattern you may add any of the documented request parameters to the URL. + +#### Request Parameters + + + + The end [instant](/docs/reference/data-types#instants) of the date/time range to search within. + + + The string to search in the Webhook Event Log request body for. This can contain wildcards using the asterisk character (`*`). If no wildcards are present, this parameter value will be interpreted as `*value*`. + + + The overall result of a [transactional](/docs/extend/events-and-webhooks/events#transaction-compatibility) event. Possible values are: + * `Running` - The default state after an event is fired. + * `Succeeded` - The transactional event was successful, and pending database changes were committed. Non-transactional events are transitioned to this state immediately after the event payload is sent to all recipients regardless of the response. + * `Failed` - The transactional event was unsuccessful, and pending database changes were rolled back. + + + The event type. + + + The number of results to return from the search. + + + The database column to order the search results on plus the order direction. + + The possible values are: + + * `eventResult` - the overall result of the event + * `eventType` - the event type + * `id` - the unique Id of the Webhook Event Log + * `insertInstant` - the [instant](/docs/reference/data-types#instants) when the Webhook Event Log was created + * `lastAttemptInstant` - the [instant](/docs/reference/data-types#instants) when the last attempt was made to deliver the event + * `linkedObjectId` - the unique Id of the object associated with this event + * `sequence` - the system-assigned event sequence + + For example, to order the results by the insert instant in a descending order, the value would be provided as `insertInstant DESC`. The final string is optional can be set to `ASC` or `DESC`. + + + The start [instant](/docs/reference/data-types#instants) of the date/time range to search within. + + + The offset row to return results from. If the search has 200 records in it and this is 50, it starts with row 50. + + + + + +When calling the API using a `POST` request you will send the search criteria in a JSON request body. + +#### Request Body + + + + The end [instant](/docs/reference/data-types#instants) of the date/time range to search within. + + + The string to search in the Webhook Event Log request body for. This can contain wildcards using the asterisk character (`*`). If no wildcards are present, this parameter value will be interpreted as `*value*`. + + + The overall result of a [transactional](/docs/extend/events-and-webhooks/events#transaction-compatibility) event. Possible values are: + * `Running` - The default state after an event is fired. + * `Succeeded` - The transactional event was successful, and pending database changes were committed. Non-transactional events are transitioned to this state immediately after the event payload is sent to all recipients regardless of the response. + * `Failed` - The transactional event was unsuccessful, and pending database changes were rolled back. + + + The event type. + + + The number of results to return from the search. + + + The database column to order the search results on plus the order direction. + + The possible values are: + + * `eventResult` - the overall result of the event + * `eventType` - the event type + * `id` - the unique Id of the Webhook Event Log + * `insertInstant` - the [instant](/docs/reference/data-types#instants) when the Webhook Event Log was created + * `lastAttemptInstant` - the [instant](/docs/reference/data-types#instants) when the last attempt was made to deliver the event + * `linkedObjectId` - the unique Id of the object associated with this event + * `sequence` - the system-assigned event sequence + + For example, to order the results by the insert instant in a descending order, the value would be provided as `insertInstant DESC`. The final string is optional can be set to `ASC` or `DESC`. + + + The start [instant](/docs/reference/data-types#instants) of the date/time range to search within. + + + The offset row to return results from. If the search has 200 records in it and this is 50, it starts with row 50. + + + + + +### Response + +The response for this API contains the Webhook Event Logs matching the search criteria in paginated format. + + + + + + diff --git a/astro/src/content/docs/archive/apis/_event-types.mdx b/astro/src/content/docs/archive/apis/_event-types.mdx deleted file mode 100644 index 9d6c80a6d8..0000000000 --- a/astro/src/content/docs/archive/apis/_event-types.mdx +++ /dev/null @@ -1,20 +0,0 @@ -import AvailableSince from 'src/components/api/AvailableSince.astro'; - -* ``user.action`` - When a user action is triggered -* ``user.bulk.create`` - When multiple users are created in bulk (i.e. during an import) -* ``user.create`` - When a user is created -* ``user.email.verified`` - When a user verifies their email address -* ``user.update`` - When a user is updated -* ``user.deactivate`` - When a user is deactivated -* ``user.reactivate`` - When a user is reactivated -* ``user.login.success`` - When a user completes a login request -* ``user.login.failed`` - When a user fails a login request -* ``user.password.breach`` - When Reactor detects a user is using a potentially breached password (requires an activated license) -* ``user.registration.create`` - When a user registration is created -* ``user.registration.update`` - When a user registration is updated -* ``user.registration.delete`` - When a user registration is deleted -* ``user.registration.verified`` - When a user completes registration verification -* ``user.delete`` - When a user is deleted -* ``jwt.public-key.update`` - When a JWT RSA Public / Private keypair may have been changed -* ``jwt.refresh`` - When an access token is refreshed using a refresh token -* ``jwt.refresh-token.revoke`` - When a JWT Refresh Token is revoked diff --git a/astro/src/content/docs/archive/apis/_expiry_unit.mdx b/astro/src/content/docs/archive/apis/_expiry_unit.mdx deleted file mode 100644 index 53a4ee3928..0000000000 --- a/astro/src/content/docs/archive/apis/_expiry_unit.mdx +++ /dev/null @@ -1,8 +0,0 @@ -The unit of time associated with a duration. The possible values are: - -* `MINUTES` -* `HOURS` -* `DAYS` -* `WEEKS` -* `MONTHS` -* `YEARS` \ No newline at end of file diff --git a/astro/src/content/docs/archive/apis/_jwt_algorithm.mdx b/astro/src/content/docs/archive/apis/_jwt_algorithm.mdx deleted file mode 100644 index fe6d0cae05..0000000000 --- a/astro/src/content/docs/archive/apis/_jwt_algorithm.mdx +++ /dev/null @@ -1,13 +0,0 @@ -import AvailableSince from 'src/components/api/AvailableSince.astro'; - -The algorithm used to sign the JSON Web Token (JWT). The following available JSON Web Algorithms (JWA) as described in [RFC 7518](https://tools.ietf.org/html/rfc7518) are available. - -* `ES256` - ECDSA using P-256 curve and SHA-256 -* `ES384` - ECDSA using P-384 curve and SHA-384 -* `ES512` - ECDSA using P-521 curve and SHA-512 -* `HS256` - HMAC using SHA-256 -* `HS384` - HMAC using SHA-384 -* `HS512` - HMAC using SHA-512 -* `RS256` - RSASSA-PKCS1-v1_5 using SHA-256 -* `RS384` - RSASSA-PKCS1-v1_5 using SHA-384 -* `RS512` - RSASSA-PKCS1-v1_5 using SHA-512 diff --git a/astro/src/content/docs/archive/apis/_system-configuration-request-body.mdx b/astro/src/content/docs/archive/apis/_system-configuration-request-body.mdx deleted file mode 100644 index aebcb7af59..0000000000 --- a/astro/src/content/docs/archive/apis/_system-configuration-request-body.mdx +++ /dev/null @@ -1,573 +0,0 @@ -import APIBlock from 'src/components/api/APIBlock.astro'; -import APIField from 'src/components/api/APIField.astro'; -import AvailableSince from 'src/components/api/AvailableSince.astro'; -import InlineField from 'src/components/InlineField.astro'; -import EventTypes from 'src/content/docs/archive/apis/_event-types.mdx'; -import TransactionTypes from 'src/content/docs/archive/apis/_transaction-types.mdx'; -import ExpiryUnit from 'src/content/docs/archive/apis/_expiry_unit.mdx'; -import JwtAlgorithm from 'src/content/docs/archive/apis/_jwt_algorithm.mdx'; -import JSON from 'src/components/JSON.astro'; -import RemovedSince from 'src/components/api/RemovedSince.astro'; - -#### Request Body - - - - Whether or not FusionAuth should delete the Audit Log based upon this configuration. When `true` the auditLogConfiguration.delete.numberOfDaysToRetain will be used to identify audit logs that are eligible for deletion. When this value is set to `false` audit logs will be preserved forever. - - - The number of days to retain the Audit Log. Required when auditLogConfiguration.delete.enabled is set to `true`. - - - The `Access-Control-Allow-Credentials` response header values as described by [MDN Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials). - - - The `Access-Control-Allow-Headers` response header values as described by [MDN Access-Control-Allow-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers). - - - The `Access-Control-Allow-Methods` response header values as described by [MDN Access-Control-Allow-Methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods). - - - The `Access-Control-Allow-Origin` response header values as described by [MDN Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin). If the wildcard `*` is specified, no additional domains may be specified. - - - Whether or not FusionAuth will log debug messages to the event log. This is primarily useful for identifying why the FusionAuth CORS filter is rejecting a request and returning an HTTP response status code of `403`. - - - Whether the FusionAuth CORS filter will process requests made to FusionAuth. - - - The `Access-Control-Expose-Headers` response header values as described by [MDN Access-Control-Expose-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers). - - - The `Access-Control-Max-Age` response header values as described by [MDN Access-Control-Max-Age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age). - - - Indicates that the SMTP email configuration is available for use by FusionAuth. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The Id of the Email Template that is used when a user is sent a forgot password email. - -   - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The host name of the SMTP server that FusionAuth will use. Required when `systemConfiguration.emailConfiguration.enabled` is set to `true`. - -   - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - An optional password FusionAuth will use to authenticate with the SMTP server. - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The port of the SMTP server that FusionAuth will use. Required when `systemConfiguration.emailConfiguration.enabled` is set to `true`. - -   - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The Id of the Email Template that is used when a user had their account created for them and they must set their password manually and they are sent an email to set their password. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The type of security protocol FusionAuth will use when connecting to the SMTP server. The possible values are: - - * `NONE` - no security will be used. All communications will be sent plaintext. - * `SSL` - SSL will be used to connect to the SMTP server. This protocol is not recommended unless it is the only one your SMTP server supports. - * `TLS` - TLS will be used to connect to the SMTP server. This is the preferred protocol for all SMTP servers. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - An optional username FusionAuth will to authenticate with the SMTP server. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The If of the Email Template that is used to send the verification emails to users. These emails are used to verify that a user's email address is valid. If the `verifyEmail` field is `true` this field is required. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - Whether or not user's email addresses are verified when the register with your application. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - Whether or not user's email addresses are verified when the user changes them. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - A mapping of the configuration for each event type that FusionAuth sends. The event types that are the keys into this Object are: - - - - - - In version 1.8.0 and beyond, event configuration is managed per [Tenant](/docs/apis/tenants). - - - Whether or not FusionAuth should send these types of events to any configured Webhooks. - - - - In version 1.8.0 and beyond, event configuration is managed per [Tenant](/docs/apis/tenants). - - - The transaction type that FusionAuth uses when sending these types of events to any configured Webhooks. The transaction types are: - - - - - - In version 1.8.0 and beyond, event configuration is managed per [Tenant](/docs/apis/tenants). - - - The number of events to retain. Once the number of event logs exceeds this configured value they will be deleted starting with the oldest event logs. - - - The time in seconds until a OAuth authorization code in no longer valid to be exchanged for an access token. This is essentially the time allowed between the start - of an Authorization request during the Authorization code grant and when you request an access token using this authorization code on the Token endpoint. - - Value must be greater than 0 and less than or equal to 600. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until a change password Id is no longer valid and cannot be used by the Change Password API. Value must be greater than 0. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until a email verification Id is no longer valid and cannot be used by the Verify Email API. Value must be greater than 0. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until a registration verification Id is no longer valid and cannot be used by the Verify Registration API. Value must be greater than 0. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until a setup password Id is no longer valid and cannot be used by the Change Password API. Value must be greater than 0. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until a two factor Id is no longer valid and cannot be used by the Two Factor Login API. Value must be greater than 0. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until an issued Two Factor trust Id is no longer valid and the User will be required to complete Two Factor authentication - during the next authentication attempt. Value must be greater than 0. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The duration of the User Action. This value along with the `actionDurationUnit` will be used to set the duration of the User Action. - - - - In version 1.8.0 and beyond, failed authentication configuration is managed per [Tenant](/docs/apis/tenants). - - - - - - - In version 1.8.0 and beyond, failed authentication configuration is managed per [Tenant](/docs/apis/tenants). - - - The length of time in seconds before the failed authentication count will be reset. - - For example, if `tooManyAttempts` is set to `5` and you fail to authenticate `4` times in a row, waiting for the duration specified here will cause your fifth attempt to start back at `1`. - - - - In version 1.8.0 and beyond, failed authentication configuration is managed per [Tenant](/docs/apis/tenants). - - - The number of failed attempts considered to be too many. Once this threshold is reached the specified User Action will be applied to the user for the duration specified. - - - - In version 1.8.0 and beyond, failed authentication configuration is managed per [Tenant](/docs/apis/tenants). - - - The Id of the User Action that is applied when the threshold is reached for too many failed authentication attempts. - - - - In version 1.8.0 and beyond, failed authentication configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until an inactive session will be invalidated. Used when creating a new session in the FusionAuth Front End. - - In version 1.8.0 and beyond, http session max inactive interval is managed per [Tenant](/docs/apis/tenants). - - - The name or issuer of the JWT, this is generally something unique such as a fully qualified domain name. This is also used as the default issuer value when generating `[Keys](/docs/apis/keys)`. - - For example, `fusionauth.io`. - - - - In version 1.8.0 and beyond, issuer is managed per [Tenant](/docs/apis/tenants). - - - The Id of the signing key used to sign the access token. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants). - - - - - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants) and Keymaster. - - - The Id of the signing key used to sign the Id token. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants). - - - The name or issuer of the JWT, this is generally something unique such as a fully qualified domain name. - - For example, `fusionauth.io`. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants) and Keymaster. - - - The private key used when an `RSA` signing algorithm has been selected. The private key will be used to sign the JWT. This key is expected to be in a PEM encoded format. Required when `algorithm` is set to an RSA based value. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants) and Keymaster. - - - The public key used when an `RSA` signing algorithms has been selected. The public key will be used to verify JWTs signed with the private key. This key is expected to be in a PEM encoded format. Required when `algorithm` is set to an RSA based value. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants) and Keymaster. - - - The length of time in minutes the JWT refresh token will live before it is expired and is not able to be exchanged for a JWT. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants). - - - The secret used when an `HMAC` based signing algorithm has been selected. This secret is used to sign and verify JWTs. Required when `algorithm` is set to an HMAC based value. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants) and Keymaster. - - - The length of time in seconds the JWT will live before it is expired. This value is used to calculate the `exp` (expiration) identity claim. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants). - - - Whether or not FusionAuth should delete the login records based upon this configuration. When `true` the loginRecordConfiguration.delete.numberOfDaysToRetain will be used to identify login records that are eligible for deletion. When this value is set to `false` login records will be preserved forever. - - - The number of days to retain login records. Required when loginRecordConfiguration.delete.enabled is set to `true`. - - - The logout redirect URL when sending the user's browser to the `/oauth2/logout` URI of the FusionAuth Front End. This value is only used when a logout URL is not defined in your Application. - - - - In version 1.8.0 and beyond, logoutURL is managed per [Tenant](/docs/apis/tenants). - - - The password maximum age in days. The number of days after which FusionAuth will require a user to change their password. Required when `systemConfiguration.maximumPasswordAge.enabled` is set to `true`. - - - - In version 1.8.0 and beyond, password age settings are managed per [Tenant](/docs/apis/tenants). - - - Indicates that the maximum password age is enabled and being enforced. - - - - In version 1.8.0 and beyond, password age settings are managed per [Tenant](/docs/apis/tenants). - - - The password minimum age in seconds. When enabled FusionAuth will not allow a password to be changed until it reaches this minimum age. Required when `systemConfiguration.minimumPasswordAge.enabled` is set to `true`. - - - - In version 1.8.0 and beyond, password age settings are managed per [Tenant](/docs/apis/tenants). - - - Indicates that the minimum password age is enabled and being enforced. - - - - In version 1.8.0 and beyond, password age settings are managed per [Tenant](/docs/apis/tenants). - - - The default method for encrypting the User's password. The following encryptors are provided with FusionAuth: - - * [salted-md5](/docs/reference/password-hashes#salted-md5) - * [salted-sha256](/docs/reference/password-hashes#salted-sha-256) - * [salted-hmac-sha256](/docs/reference/password-hashes#salted-hmac-sha-256) - * [salted-pbkdf2-hmac-sha256](/docs/reference/password-hashes#salted-pbkdf2-hmac-sha-256) - * [bcrypt](/docs/reference/password-hashes#salted-bcrypt) - - - - In version 1.8.0 and beyond, password encryption configuration is managed per [Tenant](/docs/apis/tenants). - - - The factor used by the password encryption scheme. If not provided, the `PasswordEncryptor` provides a default value. Generally this will be used as an iteration count to generate the hash. The actual use of this value is up to the `PasswordEncryptor` implementation. - - - - In version 1.8.0 and beyond, password encryption configuration is managed per [Tenant](/docs/apis/tenants). - - - When enabled a user's hash configuration will be modified to match these configured settings. This can be useful to increase a password hash strength over time or upgrade imported users to a more secure encryption scheme after an initial import. - - - - In version 1.8.0 and beyond, password encryption configuration is managed per [Tenant](/docs/apis/tenants). - - - The maximum number of characters that are allowed for user passwords. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - The minimum number of characters that are required for user passwords. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - The number of previous passwords that should be remembered so they are not re-used by the User. Required when `systemConfiguration.passwordValidationRules.rememberPreviousPasswords.count` is set to `true`. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - Indicates that the remember previous password validation is enabled and being enforced. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - Indicates that passwords require an uppercase and lowercase character to be valid. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - Indicates that passwords require a non-alphanumeric character to be valid. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - Indicates that passwords require at least one number to be valid. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - The [time zone](/docs/reference/data-types#time-zone) used to adjust the stored UTC time when generating reports. Since reports are usually rolled up hourly, this timezone will be used for demarcating the hours. - - For example: - - > `America/Denver` or `US/Mountain` - - - A hexadecimal color to override the default menu color in the user interface. - - > Example: `000000` would set the menu color to black. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /email/complete page. This page is used after a user has verified their email address by clicking the URL in the email. After FusionAuth has updated their user object to indicate that their email was verified, the browser is redirected to this page. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /email/send page. This page is used after a user has asked for the verification email to be resent. This can happen if the URL in the email expired and the user clicked it. In this case, the user can provide their email address again and FusionAuth will resend the email. After the user submits their email and FusionAuth re-sends a verification email to them, the browser is redirected to this page. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /email/verify page by clicking the URL from the verification email and the `verificationId` has expired. FusionAuth expires `verificationId` after a period of time (which is configurable). If the user has a URL from the verification email that has expired, this page will be rendered and the error will be displayed to the user. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - Indicates that the login theme is enabled and will be used to style the login pages. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that contains all of the macros and templates used by the rest of the `loginTheme` FreeMarker templates (i.e. `oauth2Authorize`). This allows you to configure the general layout of your UI configuration and login theme without having to copy and paste HTML into each of the templates. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /oauth2/authorize page. This is the main login page for FusionAuth and is used for all interactive OAuth and OpenId Connect workflows. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /oauth2/error page. This page is used if the user starts or is in the middle of the OAuth workflow and any type of error occurs. This could be caused by the user messing with the URL or internally some type of information wasn't passed between the OAuth endpoints correctly. For example, if you are federating login to an external IdP and that IdP does not properly echo the `state` parameter, FusionAuth's OAuth workflow will break and this page will be displayed. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /oauth2/two-factor page. This page is used if the user has two-factor authentication enabled and they need to type in their code again. FusionAuth will properly handle the SMS or authenticator app processing on the back end. This page contains the form that the user will put their code into. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /password/change page. This page is used if the user is required to change their password or if they have requested a password reset. This page contains the form that allows the user to provide a new password. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /password/complete page. This page is used after the user has successfully updated their password (or reset it). This page should instruct the user that their password was updated and that they need to login again. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /password/forgot page. This page is used when a user starts the forgot password workflow. This page renders the form where the user types in their email address. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /password/sent page. This page is used when a user has submitted the forgot password form with their email. FusionAuth does not indicate back to the user if their email address was valid in order to prevent malicious activity that could reveal valid email addresses. Therefore, this page should indicate to the user that if their email was valid, they will receive an email shortly with a link to reset their password. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /registration/complete page. This page is used after a user has verified their email address for a specific application (i.e. a user registration) by clicking the URL in the email. After FusionAuth has updated their registration object to indicate that their email was verified, the browser is redirected to this page. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /registration/send page. This page is used after a user has asked for the application specific verification email to be resent. This can happen if the URL in the email expired and the user clicked it. In this case, the user can provide their email address again and FusionAuth will resend the email. After the user submits their email and FusionAuth re-sends a verification email to them, the browser is redirected to this page. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /registration/verify page by clicking the URL from the application specific verification email and the `verificationId` has expired. FusionAuth expires `verificationId` after a period of time (which is configurable). If the user has a URL from the verification email that has expired, this page will be rendered and the error will be displayed to the user. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A CSS stylesheet used to style the login page and other templates such as forgot password, and verify email. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A URL of a logo to override the default FusionAuth logo in the user interface. - - - A hexadecimal color to override the default menu font color in the user interface. - - > Example: `FFFFFF` would set the menu font color to white. - - - - diff --git a/astro/src/content/docs/archive/apis/_system-configuration-response-body.mdx b/astro/src/content/docs/archive/apis/_system-configuration-response-body.mdx deleted file mode 100644 index 26e9736aa0..0000000000 --- a/astro/src/content/docs/archive/apis/_system-configuration-response-body.mdx +++ /dev/null @@ -1,581 +0,0 @@ -import APIBlock from 'src/components/api/APIBlock.astro'; -import APIField from 'src/components/api/APIField.astro'; -import InlineField from 'src/components/InlineField.astro'; -import EventTypes from 'src/content/docs/archive/apis/_event-types.mdx'; -import TransactionTypes from 'src/content/docs/archive/apis/_transaction-types.mdx'; -import ExpiryUnit from 'src/content/docs/archive/apis/_expiry_unit.mdx'; -import JwtAlgorithm from 'src/content/docs/archive/apis/_jwt_algorithm.mdx'; -import JSON from 'src/components/JSON.astro'; -import RemovedSince from 'src/components/api/RemovedSince.astro'; - -#### Response Body - - - - Whether or not FusionAuth should delete the Audit Log based upon this configuration. When `true` the auditLogConfiguration.delete.numberOfDaysToRetain will be used to identify audit logs that are eligible for deletion. When this value is set to `false` audit logs will be preserved forever. - - - The number of days to retain the Audit Log. - - - The `Access-Control-Allow-Credentials` response header values as described by [MDN Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials). - - - The `Access-Control-Allow-Headers` response header values as described by [MDN Access-Control-Allow-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers). - - - The `Access-Control-Allow-Methods` response header values as described by [MDN Access-Control-Allow-Methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods). The possible values are: - * `GET` - * `POST` - * `PUT` - * `DELETE` - * `HEAD` - * `OPTIONS` - - - The `Access-Control-Allow-Origin` response header values as described by [MDN Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin). If the wildcard `*` is specified, no additional domains may be specified. - - - Whether the FusionAuth CORS filter will process requests made to FusionAuth. - - - The `Access-Control-Expose-Headers` response header values as described by [MDN Access-Control-Expose-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers). - - - The `Access-Control-Max-Age` response header values as described by [MDN Access-Control-Max-Age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age). - - - An object that can hold any information about the System that should be persisted. - - - Whether or not FusionAuth will log debug messages to the event log. This is primarily useful for identifying why the FusionAuth CORS filter is rejecting a request and returning an HTTP response status code of `403`. - - - Indicates that the SMTP email configuration is available for use by FusionAuth. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The host name of the SMTP server that FusionAuth will use. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The Id of the Email Template that is used when a user is sent a forgot password email. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - An optional password FusionAuth will use to authenticate with the SMTP server. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The port of the SMTP server that FusionAuth will use. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The type of security protocol FusionAuth will use when connecting to the SMTP server. The possible values are: - - * `NONE` - no security will be used. All communications will be sent plaintext. - * `SSL` - SSL will be used to connect to the SMTP server. This protocol is not recommended unless it is the only one your SMTP server supports. - * `TLS` - TLS will be used to connect to the SMTP server. This is the preferred protocol for all SMTP servers. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The Id of the Email Template that is used when a user had their account created for them and they must set their password manually and they are sent an email to set their password. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - An optional username FusionAuth will to authenticate with the SMTP server. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - The Id of the Email Template that is used to send the verification emails to users. These emails are used to verify that a user's email address is valid. If the `verifyEmail` field is `true` this field is required. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - Whether or not user's email addresses are verified when the register with your application. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - Whether or not user's email addresses are verified when the user changes them. - - - - In version 1.8.0 and beyond, email configuration is managed per [Tenant](/docs/apis/tenants). - - - A mapping of the configuration for each event type that FusionAuth sends. The event types that are the keys into this Object are: - - - - - - In version 1.8.0 and beyond, event configuration is managed per [Tenant](/docs/apis/tenants). - - - Whether or not FusionAuth should send these types of events to any configured Webhooks. - - - - In version 1.8.0 and beyond, event configuration is managed per [Tenant](/docs/apis/tenants). - - - The transaction type that FusionAuth uses when sending these types of events to any configured Webhooks. The transaction types are: - - - - - - In version 1.8.0 and beyond, event configuration is managed per [Tenant](/docs/apis/tenants). - - - The number of events to retain. Once the number of event logs exceeds this configured value they will be deleted starting with the oldest event logs. - - - The time in seconds until a OAuth authorization code in no longer valid to be exchanged for an access token. This is essentially the time allowed between the start - of an Authorization request during the Authorization code grant and when you request an access token using this authorization code on the Token endpoint. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until a change password Id is no longer valid and cannot be used by the Change Password API. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until a email verification Id is no longer valid and cannot be used by the Verify Email API. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until a registration verification Id is no longer valid and cannot be used by the Verify Registration API. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until a setup password Id is no longer valid and cannot be used by the Change Password API. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until a two factor Id is no longer valid and cannot be used by the Two Factor Login API. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until an issued Two Factor trust Id is no longer valid and the User will be required to complete Two Factor authentication - during the next authentication attempt. - - - - In version 1.8.0 and beyond, external identifier configuration is managed per [Tenant](/docs/apis/tenants). - - - The duration of the User Action. This value along with the `actionDurationUnit` will be used to set the duration of the User Action. - - - - In version 1.8.0 and beyond, failed authentication configuration is managed per [Tenant](/docs/apis/tenants). - - - - - - - - In version 1.8.0 and beyond, failed authentication configuration is managed per [Tenant](/docs/apis/tenants). - - - The length of time in seconds before the failed authentication count will be reset. - - For example, if `tooManyAttempts` is set to `5` and you fail to authenticate `4` times in a row, waiting for the duration specified here will cause your fifth attempt to start back at `1`. - - - - In version 1.8.0 and beyond, failed authentication configuration is managed per [Tenant](/docs/apis/tenants). - - - The number of failed attempts considered to be too many. Once this threshold is reached the specified User Action will be applied to the user for the duration specified. - - - - In version 1.8.0 and beyond, failed authentication configuration is managed per [Tenant](/docs/apis/tenants). - - - The Id of the User Action that is applied when the threshold is reached for too many failed authentication attempts. - - - - In version 1.8.0 and beyond, failed authentication configuration is managed per [Tenant](/docs/apis/tenants). - - - The time in seconds until an inactive session will be invalidated. Used when creating a new session in the FusionAuth OAuth front-end. - - - - In version 1.8.0 and beyond, http session max inactive interval is managed per [Tenant](/docs/apis/tenants). - - - The name or issuer of the JWT, this is generally something unique such as a fully qualified domain name. This is also used as the default issuer value when generating `[Keys](/docs/apis/keys)`. - - For example, `fusionauth.io`. - - - - In version 1.8.0 and beyond, issuer is managed per [Tenant](/docs/apis/tenants). - - - The Id of the signing key used to sign the access token. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants). - - - - - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants) and Keymaster. - - - This value will always be true. The JWT configuration may not be disabled for the System Configuration. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants). - - - The Id of the signing key used to sign the Id token. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants). - - - The name or issuer of the JWT, this is generally something unique such as a fully qualified domain name. - - For example, `fusionauth.io`. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants) and Keymaster. - - - The private key used when an `RSA` signing algorithm has been selected. The private key will be used to sign the JWT. This key will be returned in a PEM encoded format. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants) and Keymaster. - - - The public key used when an `RSA` signing algorithms has been selected. The public key will be used to verify JWTs signed with the private key. This key will be returned in a PEM encoded format. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants) and Keymaster. - - - The length of time in minutes the JWT refresh token will live before it is expired and is not able to be exchanged for a JWT. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants). - - - The secret used when an `HMAC` based signing algorithm has been selected. This secret is used to sign and verify JWTs. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants) and Keymaster. - - - The length of time in seconds the JWT will live before it is expired. This value is used to calculate the `exp` (expiration) identity claim. - - - - In version 1.8.0 and beyond, JWT configuration is managed per [Tenant](/docs/apis/tenants). - - - Whether or not FusionAuth should delete the login records based upon this configuration. When `true` the loginRecordConfiguration.delete.numberOfDaysToRetain will be used to identify login records that are eligible for deletion. When this value is set to `false` login records will be preserved forever. - - - The number of days to retain login records. - - - The logout redirect URL when sending the user's browser to the `/oauth2/logout` URI of the FusionAuth Front End. This value is only used when a logout URL is not defined in your Application. - - - - In version 1.8.0 and beyond, logoutURL is managed per [Tenant](/docs/apis/tenants). - - - The password maximum age in days. The number of days after which FusionAuth will require a user to change their password. - - - - In version 1.8.0 and beyond, password age settings are managed per [Tenant](/docs/apis/tenants). - - - Indicates that the maximum password age is enabled and being enforced. - - - - In version 1.8.0 and beyond, password age settings are managed per [Tenant](/docs/apis/tenants). - - - The password minimum age in seconds. When enabled FusionAuth will not allow a password to be changed until it reaches this minimum age. - - - - In version 1.8.0 and beyond, password age settings are managed per [Tenant](/docs/apis/tenants). - - - Indicates that the minimum password age is enabled and being enforced. - - - - In version 1.8.0 and beyond, password age settings are managed per [Tenant](/docs/apis/tenants). - - - The selected default encryption scheme. - - - - In version 1.8.0 and beyond, password encryption configuration is managed per [Tenant](/docs/apis/tenants). - - - The factor used by the password encryption scheme. Generally this will be used as an iteration count to generate the hash. The actual use of this value is up to the `PasswordEncryptor` implementation. - - - - In version 1.8.0 and beyond, password encryption configuration is managed per [Tenant](/docs/apis/tenants). - - - When enabled a user's hash configuration will be modified to match these configured settings. - - - - In version 1.8.0 and beyond, password encryption configuration is managed per [Tenant](/docs/apis/tenants). - - - The maximum number of characters that are allowed for user passwords. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - The minimum number of characters that are required for user passwords. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - The number of previous passwords that should be remembered so they are not re-used by the User. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - Indicates that the remember previous password validation is enabled and being enforced. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - Indicates that passwords require an uppercase and lowercase character to be valid. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - Indicates that passwords require a non-alphanumeric character to be valid. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - Indicates that passwords require at least one number to be valid. - - - - In version 1.8.0 and beyond, password validation rules are configured per [Tenant](/docs/apis/tenants). - - - The [time zone](/docs/reference/data-types#time-zone) used to adjust the stored UTC time when generating reports. Since reports are usually rolled up hourly, this timezone will be used for demarcating the hours. - - For example: - - > `America/Denver` or `US/Mountain` - - - A hexadecimal color to override the default menu color in the user interface. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /email/complete page. This page is used after a user has verified their email address by clicking the URL in the email. After FusionAuth has updated their user object to indicate that their email was verified, the browser is redirected to this page. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /email/send page. This page is used after a user has asked for the verification email to be resent. This can happen if the URL in the email expired and the user clicked it. In this case, the user can provide their email address again and FusionAuth will resend the email. After the user submits their email and FusionAuth re-sends a verification email to them, the browser is redirected to this page. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /email/verify page by clicking the URL from the verification email and the `verificationId` has expired. FusionAuth expires `verificationId` after a period of time (which is configurable). If the user has a URL from the verification email that has expired, this page will be rendered and the error will be displayed to the user. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - Indicates that the login theme is enabled and will be used to style the login pages. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that contains all of the macros and templates used by the rest of the `loginTheme` FreeMarker templates (i.e. `oauth2Authorize`). This allows you to configure the general layout of your UI configuration and login theme without having to copy and paste HTML into each of the templates. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /oauth2/authorize page. This is the main login page for FusionAuth and is used for all interactive OAuth and OpenId Connect workflows. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /oauth2/error page. This page is used if the user starts or is in the middle of the OAuth workflow and any type of error occurs. This could be caused by the user messing with the URL or internally some type of information wasn't passed between the OAuth endpoints correctly. For example, if you are federating login to an external IdP and that IdP does not properly echo the `state` parameter, FusionAuth's OAuth workflow will break and this page will be displayed. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /oauth2/two-factor page. This page is used if the user has two-factor authentication enabled and they need to type in their code again. FusionAuth will properly handle the SMS or authenticator app processing on the back end. This page contains the form that the user will put their code into. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /password/change page. This page is used if the user is required to change their password or if they have requested a password reset. This page contains the form that allows the user to provide a new password. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /password/complete page. This page is used after the user has successfully updated their password (or reset it). This page should instruct the user that their password was updated and that they need to login again. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /password/forgot page. This page is used when a user starts the forgot password workflow. This page renders the form where the user types in their email address. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /password/sent page. This page is used when a user has submitted the forgot password form with their email. FusionAuth does not indicate back to the user if their email address was valid in order to prevent malicious activity that could reveal valid email addresses. Therefore, this page should indicate to the user that if their email was valid, they will receive an email shortly with a link to reset their password. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /registration/complete page. This page is used after a user has verified their email address for a specific application (i.e. a user registration) by clicking the URL in the email. After FusionAuth has updated their registration object to indicate that their email was verified, the browser is redirected to this page. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /registration/send page. This page is used after a user has asked for the application specific verification email to be resent. This can happen if the URL in the email expired and the user clicked it. In this case, the user can provide their email address again and FusionAuth will resend the email. After the user submits their email and FusionAuth re-sends a verification email to them, the browser is redirected to this page. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A [FreeMarker](https://freemarker.apache.org) template that is rendered when the user requests the /registration/verify page by clicking the URL from the application specific verification email and the `verificationId` has expired. FusionAuth expires `verificationId` after a period of time (which is configurable). If the user has a URL from the verification email that has expired, this page will be rendered and the error will be displayed to the user. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A CSS stylesheet used to style the login page and other templates such as forgot password, and verify email. - - - - In version 1.8.0 and beyond, theme configuration is managed per [Tenant](/docs/apis/tenants) and themes are configured using the [Theme](/docs/apis/themes) API or via the UI. - - - A URL of a logo to override the default FusionAuth logo in the user interface. - - - A hexadecimal color to override the default menu font color in the user interface. - - - - diff --git a/astro/src/content/docs/archive/apis/_system-logs-request-body.mdx b/astro/src/content/docs/archive/apis/_system-logs-request-body.mdx deleted file mode 100644 index f0ada95d53..0000000000 --- a/astro/src/content/docs/archive/apis/_system-logs-request-body.mdx +++ /dev/null @@ -1,30 +0,0 @@ -import APIBlock from 'src/components/api/APIBlock.astro'; -import APIField from 'src/components/api/APIField.astro'; -import InlineField from 'src/components/InlineField.astro'; -import JSON from 'src/components/JSON.astro'; - -#### Request Body - - - - The format string used to format the date and time columns in the export result. - - When this parameter is omitted a default format of `M/d/yyyy hh:mm:ss a z` will be used. See the [DateTimeFormatter patterns](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) for additional examples. - - - The number of bytes to retrieve from the end of each of the system logs. When this value is `-1`, the entire log will be downloaded. - - - The [time zone](/docs/reference/data-types#time-zone) used to adjust the stored UTC time in the export result. - - For example: - - > `America/Denver` or `US/Mountain` - -   - - When this parameter is omitted the configured default report time zone will be used. See reportTimezone in the [System Configuration API](/docs/apis/system). - - - - diff --git a/astro/src/content/docs/archive/apis/_transaction-types.mdx b/astro/src/content/docs/archive/apis/_transaction-types.mdx deleted file mode 100644 index c498d8b415..0000000000 --- a/astro/src/content/docs/archive/apis/_transaction-types.mdx +++ /dev/null @@ -1,5 +0,0 @@ -* ``None`` - No Webhooks are required to succeed for the FusionAuth transaction to be committed. -* ``Any`` - Only a single Webhook is required to succeed for the FusionAuth transaction to be committed. -* ``SimpleMajority`` - A simple majority (50% or more) of Webhooks are required to succeed for the FusionAuth transaction to be committed. -* ``SuperMajority`` - A super majority (2/3 or more) of Webhooks are required to succeed for the FusionAuth transaction to be committed. -* ``AbsoluteMajority`` - Every Webhook must succeed for the FusionAuth transaction to be committed. diff --git a/astro/src/content/docs/archive/apis/system-1-29.mdx b/astro/src/content/docs/archive/apis/system-1-29.mdx deleted file mode 100644 index 7dfb78adf5..0000000000 --- a/astro/src/content/docs/archive/apis/system-1-29.mdx +++ /dev/null @@ -1,354 +0,0 @@ ---- -title: Pre 1.30 System APIs -description: Learn about the APIs for retrieving and updating the system configuration. -section: archive -subcategory: apis ---- -import API from 'src/components/api/API.astro'; -import StandardGetResponseCodes from 'src/content/docs/apis/_standard-get-response-codes.astro'; -import SystemConfigurationResponseBody from 'src/content/docs/archive/apis/_system-configuration-response-body.mdx'; -import GenericUpdateExplanationFragment from 'src/content/docs/apis/_generic-update-explanation-fragment.mdx'; -import SystemConfigurationRequestBody from 'src/content/docs/archive/apis/_system-configuration-request-body.mdx'; -import StandardPostResponseCodes from 'src/content/docs/apis/_standard-post-response-codes.astro'; -import Aside from 'src/components/Aside.astro'; -import APIBlock from 'src/components/api/APIBlock.astro'; -import APIField from 'src/components/api/APIField.astro'; -import InlineField from 'src/components/InlineField.astro'; -import SystemLogsRequestBody from 'src/content/docs/archive/apis/_system-logs-request-body.mdx'; -import JSON from 'src/components/JSON.astro'; -import ReindexRequestBody from 'src/content/docs/apis/_reindex-request-body.mdx'; -import PrometheusJvmGauges from 'src/content/docs/_shared/_prometheus-jvm-gauges.mdx'; - -## Overview - -This page contains the APIs that are used for retrieving and updating the system configuration. - -## Retrieve the System Configuration - -This API is used to retrieve the System Configuration. - -### Request - - - -### Response - -The response for this API contains the System Configuration. - - - - - -## Update the System Configuration - - - -### Request - - - - - -### Response - -The response for this API contains the System Configuration. - - - - - -## Export System Logs - - - -This API is used to export the System Logs, the response will be a compressed zip archive containing the logs from the configured log directory. When running FusionAuth on Docker or other container service where logs are written to `stdout` and not written to the file system, this API will return an empty archive. - -### Request - - - -When calling the API using a `GET` request you will send the export criteria on the URL using request parameters. - -#### Request Parameters - - - - The format string used to format the date and time columns in the export result. - - When this parameter is omitted a default format of `M/d/yyyy hh:mm:ss a z` will be used. See the [DateTimeFormatter patterns](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) for additional examples. - - - The number of bytes to retrieve from the end of each of the system logs. When this value is `-1`, the entire log will be downloaded. - - - The [time zone](/docs/reference/data-types#time-zone) used to calculate the current time and build the filename. - - For example: - - > `America/Denver` or `US/Mountain` - - When this parameter is omitted the configured default report time zone will be used. See reportTimezone in the [System Configuration API](/docs/apis/system). - - - - - -When calling the API using a `POST` request you will send the export criteria in a JSON request body. - - - -### Response - -The response for this API will contain a compressed zip of the system logs. - - - -## Retrieve the Logging Level - -The Logger API is used to retrieve the current log level for a particular logger by name. - - - -### Request - - - -#### Request Parameters - - - - The logger name for which you are requesting to retrieve the current logging level. - - - -### Response - - - -#### Response Body - - - - The name of the logger. - - - The current logging level. Possible values are: - - * `error` - * `warn` - * `info` - * `debug` - * `trace` - * `off` - - - - - -## Update the Logging Level - -This API is used to update the log level for a particular FusionAuth package. - - - -### Request - - - -#### Request Headers - - - - The request body is expected to be sent using form encoded data. Ensure your HTTP client sends the `Content-Type` request header set to `application/x-www-form-urlencoded`. - - - -#### Request Parameters - - - - The logger name for which you are requesting to update the current logging level. - - - The requested logging level. Possible values are: - - * `error` - * `warn` - * `info` - * `debug` - * `trace` - * `off` - - - -### Response - - - -#### Response Body - - - - The logging level. If the request was successful, this value should be equal to the request value. Possible values are: - - * `error` - * `warn` - * `info` - * `debug` - * `trace` - * `off` - - - - - -## Rebuild the Elasticsearch index - - - -This API is used to rebuild the Elasticsearch index. In general you do not need to rebuild the search index at runtime, and doing will cause additional CPU and I/O overhead to FusionAuth until the request has completed. Please be careful with this API. - -This API may be useful if you are building a new FusionAuth environment from an existing database w/out moving over an existing search index. In this scenario you will need to rebuild the search index from the database in order see the Users show up in the UI or use any of the Search APIs. - -### Request - - - - - -### Response - - - -## Retrieve the status of an index rebuild - - - -This API is used to retrieve the status of a reindex request. This may be useful to identify if an existing re-index operation has been completed. - -### Request - - - -### Response - - - -## Retrieve System Status - -The Status API is used to retrieve the current status and metrics for FusionAuth. This is useful for health checks and monitoring. - - - -### Request - - - -
    - - -### Response -The JSON response from the Status API is complex and subject to change. The only exception is the `version` key. - -`version` will not change and will be returned as below. As a reminder, an API key is required to obtain this value. -```javascript -{ -{/* .. */} - "version": "1.26.1" -{/* .. */} -} -``` - -The specific contents of the JSON body are not documented here. If you choose to use this API for monitoring purposes you should primarily use the response code to indicate server health. If you receive a `200` you may consider FusionAuth in a healthy state. The response body is intended for use by FusionAuth support. - -_Response Codes_ - -| Code | Description | -|------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 200 | The FusionAuth is functioning properly | -| 452 | The FusionAuth is failing to make a JDBC connection to the configured database.Available since 1.19.0 | -| 453 | The FusionAuth database connection pool connectivity is below the healthy threshold. Additional information may be available in the JSON response which is retrieved when using an API key.Available since 1.19.0 | -| 454 | The FusionAuth database connectivity pool connectivity is below the healthy threshold. Additional information may be available in the JSON response which is retrieved when using an API key.Available since 1.19.0 | -| 460 | FusionAuth is using Elasticsearch and the search service is reporting an unhealthy cluster status. In a cluster with 2+ nodes, this means the cluster status is being reported as `yellow` or `red`. In a single-node Elasticsearch configuration this means the cluster status is `red.`Available since 1.19.0 | -| 500 | The FusionAuth server is not functioning properly. This could indicate that the database connectivity failed or one or more services within FusionAuth failed. Consult the FusionAuth [Troubleshooting](/docs/operate/troubleshooting/troubleshooting) to learn more about the failure or contact FusionAuth support for assistance. | - -## Retrieve System Version - - - -The Version API is used to retrieve the current version of FusionAuth. - -### Request - - - -### Response - - - -#### Response Body - - - - The version of the running FusionAuth instance. - - - -```json title="Example JSON Response" -{ - "version": "1.27.0" -} -``` - -## Retrieve System Metrics Using Prometheus - - - -This page contains the API that is used for retrieving FusionAuth application metrics to be used with Prometheus. Please refer to the [Prometheus setup](/docs/operate/secure-and-monitor/prometheus#) guide to understand how to set up Prometheus with the FusionAuth metrics endpoint. - - - -### Request Parameters -There are no request parameters required with this API. - -### Response -The response to this API call contains currently available metrics. The metrics in this response are subject to change. - - - -```plaintext title="Example Prometheus Response" - # HELP jvm_memory_heap_committed Generated from Dropwizard metric import (metric=jvm.memory.heap.committed, type=com.codahale.metrics.jvm.MemoryUsageGaugeSet$8) -# TYPE jvm_memory_heap_committed gauge -jvm_memory_heap_committed 5.36870912E8 -# HELP jvm_memory_non_heap_used Generated from Dropwizard metric import (metric=jvm.memory.non-heap.used, type=com.codahale.metrics.jvm.MemoryUsageGaugeSet$11) -# TYPE jvm_memory_non_heap_used gauge -jvm_memory_non_heap_used 1.66423384E8 -# HELP jvm_memory_pools_CodeHeap__non_profiled_nmethods__used Generated from Dropwizard metric import (metric=jvm.memory.pools.CodeHeap-'non-profiled-nmethods'.used, type=com.codahale.metrics.jvm.MemoryUsageGaugeSet$17) -# TYPE jvm_memory_pools_CodeHeap__non_profiled_nmethods__used gauge -jvm_memory_pools_CodeHeap__non_profiled_nmethods__used 3.0334336E7 -# HELP prime_mvc___admin_group_index__requests Generated from Dropwizard metric import (metric=prime-mvc.[/admin/group/index].requests, type=com.codahale.metrics.Timer) -# TYPE prime_mvc___admin_group_index__requests summary -prime_mvc___admin_group_index__requests{quantile="0.5",} 0.0 -prime_mvc___admin_group_index__requests{quantile="0.75",} 0.0 -prime_mvc___admin_group_index__requests{quantile="0.95",} 0.0 -prime_mvc___admin_group_index__requests{quantile="0.98",} 0.0 -prime_mvc___admin_group_index__requests{quantile="0.99",} 0.0 -prime_mvc___admin_group_index__requests{quantile="0.999",} 0.0 -prime_mvc___admin_group_index__requests_count 1.0 -``` diff --git a/astro/src/content/docs/archive/passport-to-fusionauth.mdx b/astro/src/content/docs/archive/passport-to-fusionauth.mdx index 37ce9b25e3..71807d6395 100644 --- a/astro/src/content/docs/archive/passport-to-fusionauth.mdx +++ b/astro/src/content/docs/archive/passport-to-fusionauth.mdx @@ -24,7 +24,7 @@ _Name changes_ | passport.properties | fusionauth.properties | The Passport configuration file is now named `fusionauth.properties`. | | Passport Backend | FusionAuth App | The Passport Backend which refers to the webservice that services APIs and provides the UI is now referred as FusionAuth or FusionAuth App. | | passport-backend | fusionauth-app | The passport-backend which was the name of the package or bundle which contained the Passport Backend service will now be called fusionauth-app. | -| Passport Search Search | FusionAuth Search | The Passport Search Search which refers to the webservice that provides search capability to FusionAuth is now referred to FusionAuth Search. | +| Passport Search | FusionAuth Search | The Passport Search which refers to the webservice that provides search capability to FusionAuth is now referred to FusionAuth Search. | | passport-search-engine | fusionauth-search | The `passport-search-engine` which was the name of the package or bundle which contained the Passport Search Engine service will now be called `fusionauth-search`. | | X-Passport-TenantId | X-FusionAuth-TenantId | The `X-Passport-TenantId` which was used if you had configured more than one tenant to scope an API request to a particular tenant should be changed to `X-FusionAuth-TenantId`. | diff --git a/astro/src/content/docs/customize/look-and-feel/_messages-example.mdx b/astro/src/content/docs/customize/look-and-feel/_messages-example.mdx index 43ccd274b2..ef63bebd73 100644 --- a/astro/src/content/docs/customize/look-and-feel/_messages-example.mdx +++ b/astro/src/content/docs/customize/look-and-feel/_messages-example.mdx @@ -1,4 +1,4 @@ -import InlineField from 'src/components/InlineField.astro'; +import Aside from 'src/components/Aside.astro'; Consider the following message bundle and theme usage example with English and German messages defined. @@ -15,11 +15,20 @@ optional-greeting=Mitmensch

    ${theme.message('greeting')} ${theme.optionalMessage('optional-greeting')}

    ``` -If I have selected German as my locale, I will be greeted with `Guten Tag Mitmensch` rendered on the page. +If I have selected German as my locale, I will be greeted with `Guten Tag Mitmensch` rendered on the page. If I have English selected I will instead find the greeting `Good day optional-greeting`. -The behavior differs between `theme.message` and `theme.optionalMessage` only when the key doesn't exist in any of the messages files, including the default one. + + + +The following example that demonstrates the difference in behavior between `theme.message` and `theme.optionalMessage` only pertains to versions of FusionAuth prior to `1.53.0.` + +The behavior differs between `theme.message` and `theme.optionalMessage` only when the key doesn't exist in any of the messages files, including the default one. When there is no suitable key found and `theme.message` is used, an exception is thrown and the template fails to completely render. When there is no suitable key found and `theme.optionalMessage` is used, the key value is returned: `optional-message` in the example above. diff --git a/astro/src/content/docs/customize/look-and-feel/_theme-upgrade.mdx b/astro/src/content/docs/customize/look-and-feel/_theme-upgrade.mdx index c6911bb3f9..26d1989332 100644 --- a/astro/src/content/docs/customize/look-and-feel/_theme-upgrade.mdx +++ b/astro/src/content/docs/customize/look-and-feel/_theme-upgrade.mdx @@ -57,6 +57,12 @@ Once you have both sets of theme files downloaded, you can run the `diff-themes. ``` The script will output a list of files with differences between the two themes along with the detailed diff for each file. You can use this output to update your customized theme files or use the file list as a guide along with an external diff tool. +#### Using The Theme History Repository + +There's a FusionAuth maintained repository which tracks the history of hosted theme pages across releases. Each release is tagged with the version. This repository has theme files back to version 1.23.0. + +You can view [the repository](https://github.com/FusionAuth/fusionauth-theme-history) and use GitHub tooling to compare different the themes from different versions. You can also clone the repository and use your preferred git diffing tools. + ### Messages When new functionality is introduced to [the hosted login pages](/docs/get-started/core-concepts/integration-points#hosted-login-pages), new theme message keys are sometimes required. They are added to the default theme `messages` file by the upgrade process. diff --git a/astro/src/content/docs/extend/code/lambdas/index.mdx b/astro/src/content/docs/extend/code/lambdas/index.mdx index 878d907899..c9a0a0a780 100644 --- a/astro/src/content/docs/extend/code/lambdas/index.mdx +++ b/astro/src/content/docs/extend/code/lambdas/index.mdx @@ -10,9 +10,7 @@ import AdvancedEditionBlurb from 'src/content/docs/_shared/_advanced-edition-blu import APIBlock from 'src/components/api/APIBlock.astro'; import APIField from 'src/components/api/APIField.astro'; import Aside from 'src/components/Aside.astro'; -import DeprecatedSince from 'src/components/api/DeprecatedSince.astro'; import InlineField from 'src/components/InlineField.astro'; -import InlineUIElement from 'src/components/InlineUIElement.astro'; import LambdaTypes from 'src/content/docs/_shared/_lambda-types.astro'; import MembershipLambda from 'src/content/docs/extend/code/_membership-lambda.md'; import { YouTube } from '@astro-community/astro-embed-youtube'; diff --git a/astro/src/content/docs/extend/code/lambdas/login-validation.mdx b/astro/src/content/docs/extend/code/lambdas/login-validation.mdx new file mode 100644 index 0000000000..4fef4de723 --- /dev/null +++ b/astro/src/content/docs/extend/code/lambdas/login-validation.mdx @@ -0,0 +1,91 @@ +--- +title: Login Validation Lambda +description: An overview of the login validation lambda. +navcategory: customization +section: extend +subcategory: code +tertcategory: lambdas +--- +import Breadcrumb from 'src/components/Breadcrumb.astro'; +import InlineField from 'src/components/InlineField.astro'; + +During a login request FusionAuth performs various validations such as verifying credentials or verifying a one time code during a multi-factor login. Using this lambda function, you may extend this functionality to include your own validation as part of a login request. + +The login validation lambda has access to the user record, the user's registration for the application they're trying to authenticate to if applicable and meta-data about the request. While Lambda HTTP Connect may be used in this function in order to utilize external resources to perform validation, please be aware that adding latency to the login request will likely be observable to your end user. + +When you create a new lambda using the FusionAuth UI we will provide you an empty function for you to implement. + +## Lambda Structure + +If you are using the API to create the lambda you will need to ensure your function has the following signature: + +```javascript +function validate(result, user, registration, context) { + // Lambda code goes here +} +``` + +This lambda must contain a function named `validate` that takes four parameters. The parameters that the lambda is passed are: + +* `result` - An [Errors](/docs/apis/errors) object used for communicating validation errors +* `user` - the FusionAuth User object. This is read-only. +* `registration` - the FusionAuth UserRegistration object. This is read-only. +* `context` - an object containing context for the current request. This is read-only. + +The `user` and `registration` objects are well documented in the [User API](/docs/apis/users) and [Registration API](/docs/apis/registrations) documentation. The `context` object has the following structure: + +```json +{ + "authenticationType": "...", + "identityProvider": { + "id": "...", + "name": "...", + "identityProviderType": "..." + } +} +``` + +The `identityProvider` object in the `context` will only be present when the login request is from a 3rd party Identity Provider. + +To deny a login attempt, simply add one or more field or general errors to the result. The error schema can be found in the [API Errors](/docs/apis/errors) documentation. + +## Assigning The Lambda + +Once a lambda is created, you must assign it to a Tenant. Using the FusionAuth admin UI, find the Login validation lambda field found on the Security tab in the Tenant configuration. + +Or if you using the Tenant API, assign the lambda Id to the `tenant.lambdaConfiguration.loginValidationId` field. + +## Example Lambda + +Here is an example of a simple Lambda that prevents login attempts by users whose accounts are past due. Note that this is just an example that is assuming you have set the `accountStatus` in the user's data using the User API. + +```javascript +function validate(result, user, registration, context) { + if (user.data.accountStatus === 'pastDue') { + result.errors.generalErrors = [{ + code: "[LoginRestricted]", + message: "Account is past due, please contact accounts payable." + }]; + } +} +``` + +## Localization + +When using any of the Login APIs directly, if the lambda function adds errors to the `result`, the API will respond with a `400` status code and the JSON response will contain the same errors object returned by the lambda function. + +When using the FusionAuth hosted login pages, the messaging may be localized. The order of precedence is as follows. + +* If the message key returned in the `code` field is defined in your theme, that localized message will be displayed. +* If the message key returned in the `code` field is not defined in your theme, the message as provided by the lambda function will be displayed. +* If the message key returned in the `code` field is not defined in your theme, and the lambda function did not define a value for the `message`, the message key returned in the `code` field will be displayed to the user. + +Using the above example, by default the user will be shown the message `Account is past due, please contact accounts payable.`. + +To localize this message, or simply modify it to be more user friendly, add the following message to your theme: + +``` +[LoginRestricted]=Looks like you forgot to pay your bill. Please call 1-800-555-5555 for assitance. +``` + +With this change, the user will be shown `Looks like you forgot to pay your bill. Please call 1-800-555-5555 for assitance.`. diff --git a/astro/src/content/docs/extend/code/lambdas/sony-playstation-network-reconcile.mdx b/astro/src/content/docs/extend/code/lambdas/sony-playstation-network-reconcile.mdx index 2ae29c75c1..0099018dd1 100644 --- a/astro/src/content/docs/extend/code/lambdas/sony-playstation-network-reconcile.mdx +++ b/astro/src/content/docs/extend/code/lambdas/sony-playstation-network-reconcile.mdx @@ -1,6 +1,6 @@ --- -title: Sony Playstation Network Reconcile Lambda -description: An overview of the Sony Playstation Network Reconcile lambda. +title: Sony PlayStation Network Reconcile Lambda +description: An overview of the Sony PlayStation Network Reconcile lambda. navcategory: customization section: extend subcategory: code @@ -9,7 +9,7 @@ tertcategory: lambdas import ReconcileLambdaUserRegistrationParameters from 'src/content/docs/extend/code/lambdas/_reconcile-lambda-user-registration-parameters.mdx'; import ReconcileLambdaIntro from 'src/content/docs/extend/code/lambdas/_reconcile-lambda-intro.mdx'; - + ## Lambda Structure @@ -24,12 +24,12 @@ function reconcile(user, registration, userInfo) { This lambda must contain a function named `reconcile` that takes three parameters. The parameters that the lambda is passed are: -* `userInfo` - the JSON payload returned by the Sony Playstation Network UserInfo API. This is read-only. +* `userInfo` - the JSON payload returned by the Sony PlayStation Network UserInfo API. This is read-only. -The two FusionAuth objects are well documented here in the [User API](/docs/apis/users) and [Registration API](/docs/apis/registrations) documentation. The `userInfo` may contain various user claims depending upon the user's Sony Playstation Network configuration. +The two FusionAuth objects are well documented here in the [User API](/docs/apis/users) and [Registration API](/docs/apis/registrations) documentation. The `userInfo` may contain various user claims depending upon the user's Sony PlayStation Network configuration. ## Assigning The Lambda -Once a lambda is created, you may assign it to the Sony Playstation Network identity provider in the IdP configuration. +Once a lambda is created, you may assign it to the Sony PlayStation Network identity provider in the IdP configuration. -Navigate to Settings -> Identity Providers and select your existing Sony Playstation Network configuration or click Add provider and select Sony Playstation Network if it has not yet been configured. +Navigate to Settings -> Identity Providers and select your existing Sony PlayStation Network configuration or click Add provider and select Sony PlayStation Network if it has not yet been configured. diff --git a/astro/src/content/docs/extend/code/password-hashes/writing-a-plugin.mdx b/astro/src/content/docs/extend/code/password-hashes/writing-a-plugin.mdx index 8aec869c2e..42409dad37 100644 --- a/astro/src/content/docs/extend/code/password-hashes/writing-a-plugin.mdx +++ b/astro/src/content/docs/extend/code/password-hashes/writing-a-plugin.mdx @@ -28,7 +28,7 @@ cd fusionauth-example-password-encryptor mvn compile package ``` -If the above commands were successful you have now downloaded the example code and performed and initial build of the jar. If last command was not found, you do not yet have Maven build tool installed. You may utilize whatever Java build system you prefer, such as Maven, Ant, Gradle or Savant. This example wil use the Maven build system. +If the above commands were successful you have now downloaded the example code and performed and initial build of the jar. If last command was not found, you do not yet have Maven build tool installed. You may utilize whatever Java build system you prefer, such as Maven, Ant, Gradle or Savant. This example will use the Maven build system. The following is a representation of the plugin project layout. diff --git a/astro/src/content/docs/extend/events-and-webhooks/events/index.mdx b/astro/src/content/docs/extend/events-and-webhooks/events/index.mdx index 330ecffccb..553f088c09 100644 --- a/astro/src/content/docs/extend/events-and-webhooks/events/index.mdx +++ b/astro/src/content/docs/extend/events-and-webhooks/events/index.mdx @@ -94,4 +94,4 @@ Events can be either transactional or non-transactional. The final state of the To learn more about writing webhooks, see [Writing a Webhook](../writing-a-webhook#calling-fusionauth-apis-in-webhooks). -For more information on event transaction configurations, see transaction setting under [Tenant Settings](../#tenant-settings). +For more information on event transaction configurations, see transaction setting under [Tenant Settings](/docs/extend/events-and-webhooks#tenant-settings). diff --git a/astro/src/content/docs/extend/events-and-webhooks/events/user-login-failed.mdx b/astro/src/content/docs/extend/events-and-webhooks/events/user-login-failed.mdx index b9ac037a0b..383e724f24 100644 --- a/astro/src/content/docs/extend/events-and-webhooks/events/user-login-failed.mdx +++ b/astro/src/content/docs/extend/events-and-webhooks/events/user-login-failed.mdx @@ -47,6 +47,29 @@ export const eventType = 'user.login.failed'; Moved to event.info in 1.30.0
    + + An object containing data on the reason the login failed. + + + + The cause of the event. The possible values are: + + * `credentials` + * `lambdaValidation` + + + + This is the unique Id of the lambda that caused the login to fail. + + This field is only present if reason.code is `lambdaValidation`. + + + + The [Errors](/docs/apis/errors) object returned by the lambda function which caused the login to fail. + + This field is only present if reason.code is `lambdaValidation`. + + The unique tenant identifier. This value may not be returned if not applicable. diff --git a/astro/src/content/docs/extend/events-and-webhooks/webhook-event-log.mdx b/astro/src/content/docs/extend/events-and-webhooks/webhook-event-log.mdx new file mode 100644 index 0000000000..66f1cfe20e --- /dev/null +++ b/astro/src/content/docs/extend/events-and-webhooks/webhook-event-log.mdx @@ -0,0 +1,68 @@ +--- +title: Webhook Event Log +description: Learn about FusionAuth's Webhook Event Log and how to use it to search and view details of past events. +navcategory: developer +section: extend +subcategory: events and webhooks +--- +import ApplicationWebhooksWarning from 'src/content/docs/extend/events-and-webhooks/_application-webhooks-warning.mdx'; +import Aside from 'src/components/Aside.astro'; +import Breadcrumb from 'src/components/Breadcrumb.astro'; +import Icon from 'src/components/icon/Icon.astro'; +import InlineField from 'src/components/InlineField.astro'; +import InlineUIElement from 'src/components/InlineUIElement.astro'; +import {RemoteCode} from '@fusionauth/astro-components'; +import DiagramTxNone from 'src/diagrams/docs/extend/events-and-webhooks/_transaction-none.astro'; +import DiagramTxAny from 'src/diagrams/docs/extend/events-and-webhooks/_transaction-any-succeed.astro'; +import DiagramTxThree from 'src/diagrams/docs/extend/events-and-webhooks/_transaction-any-succeed-three-failures.astro'; +import { YouTube } from '@astro-community/astro-embed-youtube'; + + + +## Overview + +A Webhook Event Log is provided to review events sent by FusionAuth along with timing and result information for each attempt to send the event to configured endpoints. The `webhook_event_log_viewer` role grants users access to these pages. You can find the Webhook Event Log by navigating to System > Webhook Log. The same information is available via the [Webhook Event Log APIs](/docs/apis/webhook-event-logs). + +## Webhook Event Log UI + +### List of Webhook Event Logs + +The main Webhook Event Log page provides a list of summary information and search functionality for events. Test events sent via the admin UI are not recorded in the Webhook Event Log. + +List of Webhook Event Logs + +Using the icons on this screen, you can: + +* Manage the webhook event log + +### Manage Webhook Event + +Click the Manage button on the list to manage a webhook event. + +The page displays summary information about the event such as timing, event type, and result. The Webhook attempts tab contains information on attempts to send the event to each configured receiver. + +Manage of Webhook Event + +Using the icons on this screen, you can: + +* View attempt details + +The Source tab shows a read-only view of the event request body. The same event body is sent to all receivers. + +Webhook Event Source + +### View attempt details + +Click the View button on the manage screen to view details for an attempt to send the event. + +Webhook Attempt Log + +### Configuration + +By default Webhook Event Logs are never deleted. The retention period can be configured under Settings > System on the Advanced tab. + +Webhook Event Log Settings + +When the Delete retention is enabled, Webhook Event Logs older than the configured number of days will be deleted automatically. The retention period can be set to a minimum of one day. diff --git a/astro/src/content/docs/extend/events-and-webhooks/writing-a-webhook.mdx b/astro/src/content/docs/extend/events-and-webhooks/writing-a-webhook.mdx index b4922012bb..53149bf829 100644 --- a/astro/src/content/docs/extend/events-and-webhooks/writing-a-webhook.mdx +++ b/astro/src/content/docs/extend/events-and-webhooks/writing-a-webhook.mdx @@ -35,7 +35,7 @@ Here's a video displaying how to configure a webhook. If you have multiple Webhooks configured for a single Tenant, the transaction setting for the event will dictate if FusionAuth will commit the transaction or not. -As of version 1.37.0 if you have multiple webhooks assigned to different tenants but configured for the same event, such as `user.create`, only the events matching both tenant and type will be delivered. For example, imagine you have Pied Piper and Hooli tenants and both have different webhooks (`piedpier.com/webhook` and `hooli.com/webhook`) and each is configured to listen only to their tenant for the `user.create` webhook event. In this case, piedpiper.com/webhook would receive only Pied Piper user creation event information; likewise hooli.com/webhook will receive only webhooks for the `user.create` event from the Hooli tenant. +As of version 1.37.0 if you have multiple webhooks assigned to different tenants but configured for the same event, such as `user.create`, only the events matching both tenant and type will be delivered. For example, imagine you have Pied Piper and Hooli tenants and both have different webhooks (`piedpier.com/webhook` and `hooli.com/webhook`) and each is configured to listen only to their tenant for the `user.create` webhook event. In this case, `piedpiper.com/webhook` would receive only Pied Piper user creation event information; likewise `hooli.com/webhook` will receive only webhooks for the `user.create` event from the Hooli tenant. Prior to version 1.37.0 if you have multiple tenants listening for the same event, they will all receive that event and can filter on the provided tenantId to determine if they should handle the event. diff --git a/astro/src/content/docs/extend/examples/api-gateways/index.mdx b/astro/src/content/docs/extend/examples/api-gateways/index.mdx index 194977322e..91061a245a 100644 --- a/astro/src/content/docs/extend/examples/api-gateways/index.mdx +++ b/astro/src/content/docs/extend/examples/api-gateways/index.mdx @@ -54,7 +54,7 @@ Here's a sequence diagram with an example API gateway protecting two services. The location of the token in the request is typically in one of two places: * The `Authorization` header -* A secure, `HTTPOnly` cookie +* A secure, `HttpOnly` cookie The former is compatible with a variety of API gateways and open source libraries. diff --git a/astro/src/content/docs/extend/examples/modeling-organizations.mdx b/astro/src/content/docs/extend/examples/modeling-organizations.mdx index ca605b6d34..dce8b468d1 100644 --- a/astro/src/content/docs/extend/examples/modeling-organizations.mdx +++ b/astro/src/content/docs/extend/examples/modeling-organizations.mdx @@ -1,50 +1,54 @@ --- title: Modeling Organizations -description: Using FusionAuth's Entity Management feature to model organizations and users that belong to organizations. +description: Using the FusionAuth Entity Management feature to model organizations and users that belong to organizations. navcategory: developer section: extend subcategory: examples +codeRoot: https://raw.githubusercontent.com/fusionauth/fusionauth-example-modeling-organizations/main --- import PremiumEditionBlurb from 'src/content/docs/_shared/_premium-edition-blurb.astro'; +import {RemoteCode} from '@fusionauth/astro-components'; -A common use-case for B2B businesses is to model their customers and the employees of those customers. This concept isn't limited just to SaaS businesses either as many companies sell products and services to other companies. The employees, contractors, and other types of users at these customers (i.e. other companies) need access to various applications to do their work. +Business-to-business (B2B) enterprises commonly model the profiles of their customers and the roles of customers' employees. This practice isn't limited to SaaS businesses, as many companies sell products and services to other companies and need to ensure that employees, contractors, and other user groups can access the necessary applications to do their work. -An example of this is a CRM. Let's say you are building a hot new CRM called AwesomeCRM. Your customers will be other businesses and let's say one is called ClownShoes.com. ClownShoes employs 10 salespeople and they will all need access to your CRM. However, each one might have different permissions. To layer in even more complexity, ClownShoes uses an outsourced CRO service called Big Bucks CRO. Jane is a fractional CRO with Big Bucks and she will also need access to your CRM, but she might be working with 10 or more clients, including ClownShoes. You'll need to ensure Jane can access all these accounts and has the correct permissions for each, which might be different for each of her clients. +Let's consider a CRM example to illustrate organization modeling. You're building a hot new CRM called AwesomeCRM. Your customers are other businesses, and one is Pied Piper. Pied Piper employs ten salespeople, and they each need access to your CRM, but each salesperson may have different permissions. Additionally, Pied Piper uses an outsourced CRO service called Big Bucks CRO. Jane is a fractional CRO with Big Bucks, and she also needs access to your CRM. Besides Pied Piper, Jane works with ten or more clients (like Aviato and Hooli). You need to ensure Jane can access all her clients' accounts and has the correct permissions for each. -As you can see, this structure introduces a lot of complexity. This is where FusionAuth's [Entity Management](/docs/get-started/core-concepts/entity-management) feature comes in handy. Entity Management allows you to create objects (i.e. Entities) and grant Users permissions to them. Users aren't limited to having permissions to just one Entity; instead they can be granted different permissions to different Entities. +A structure like this CRM introduces a lot of complexity. This is where FusionAuth's [Entity Management](/docs/get-started/core-concepts/entity-management) feature comes in handy. Entity Management allows you to create objects (that is, Entities) and grant Users permissions to them. Users aren't limited to having permissions to just one Entity; Users can be granted different permissions to different Entities. -This guide will walk you through implementing the use-case described above with Entity Management using the FusionAuth APIs, you can also see more in our [core concepts for Entity Management](/docs/get-started/core-concepts/entity-management). +This guide will walk you through implementing the use case described above with Entity Management using the FusionAuth APIs. See the [core concepts for Entity Management](/docs/get-started/core-concepts/entity-management) documentation for more information. + +You can take a look at the companion application that implements the concepts in this guide at [https://github.com/fusionauth/fusionauth-example-modeling-organizations](https://github.com/fusionauth/fusionauth-example-modeling-organizations). The application repo includes a Kickstart file with all the settings detailed in the steps below and a Docker Compose file to run FusionAuth locally. Follow the steps in the [companion application README](https://github.com/fusionauth/fusionauth-example-modeling-organizations/blob/main/README.md) to get up and running. Let's get started. ## Create An Entity Type -The first step is to create an Entity Type. Entity types define a class of entities along with the permissions that can be granted. You can create Entity Types using the API, but in most cases, Entity Types are only created once, so you can use the admin UI for that. If you prefer to use the APIs, you'll find [that API here](/docs/apis/entities/entity-types). +The first step is to create an Entity Type. Entity types define a class of entities along with the permissions that can be granted. You can create Entity Types using the API but in most cases, Entity Types are only created once, so you can use the admin UI for that. If you prefer to use the APIs, you'll find [the API you need here](/docs/apis/entities/entity-types). -Let's create an Entity Type called `Customers`. You can name it something else if you prefer since the name is just for display purposes. Here's what this looks like: +Create an Entity Type and give it a name. In the image below, the new Entity Type is called `Customers`, but the name is just for display purposes, so you can give it any name. ![Entity Type creation](/img/guides/organizations/entity-type.png) -You have defined 5 different permissions for your `Customers` type and those are: +Five different permissions for the `Customers` type are defined here. -* Admin - this permission allows the User to do anything with the account -* Sales - this permission is for salespeople and allows them to do things like create contacts, companies, deals, etc. -* Billing- this permission allows the User to manage billing things like invoices, credit cards, etc. -* Reports - this permission allows the User to manage reports -* Viewer - this permission allows the User to view but not touch +* **Admin:** Allows the User to do anything with the account. +* **Sales:** For salespeople, allows the User to do things like create contacts, companies, deals, and so on. +* **Billing:** Allows the User to manage billing things like invoices, credit cards, and so on. +* **Reports:** Allows the User to manage reports. +* **Viewer:** Allows the User to view but not edit. -The names for permissions are also arbitrary and mostly for display purposes, so feel free to name things whatever you want. +The names for permissions are also arbitrary and mostly for display purposes, so feel free to name your permissions categories whatever you want. -After you create the Entity Type, we need to copy its Id for the next step. +After you create the Entity Type, copy its Id for the next step. ## Creating Entities -Now that you have an entity type, we can start creating entities. The process of creating Entities is usually part of the signup process or some other type of on-boarding process. This will depend on how your business handles creating accounts for your customers. For AwesomeCRM, you'll collect this information when the user signs up. During this signup process, you'll create the Entity and then grant the newly created User permissions to that Entity. This will model the fact that the user who signs up is always the first Admin of the account. +Now that you have an Entity Type, you can start creating Entities. The process of creating Entities is usually part of a signup or other onboarding process and depends on how your business handles creating accounts for your customers. For AwesomeCRM, you'll collect account information when the user signs up. During the signup process, you'll create the Entity and then grant the newly created User permissions to that Entity. In this model, the first user to sign up is the first Admin of the account. -To accomplish both of these tasks, you'll call FusionAuth APIs. To create the Entity for this new customer, we'll call the [Create Entity API](/docs/apis/entities/entities#create-an-entity). Here's what your JSON will look like: +To create the Entity for a new customer, call the [Create an Entity API](/docs/apis/entities/entities#create-an-entity). Your JSON should look similar to below. ```json { @@ -57,9 +61,9 @@ To accomplish both of these tasks, you'll call FusionAuth APIs. To create the En } ``` -This JSON will create an Entity with the newly created Entity Type from above with the name `Pied Piper`. Entity names are not unique, so you don't need to worry about multiple users conflicting with respect to their company name. +This JSON will create an Entity with the name `Pied Piper` with the newly created Entity Type from the previous step. Entity names are not unique, so you don't need to worry about multiple users conflicting with respect to their company name. -You'll need to parse the response to capture the Id of this newly created Entity. Here's how the JSON response looks: +Parse the response to capture the Id of this newly created Entity. The JSON response should look like this. ```json { @@ -85,11 +89,11 @@ You'll need to parse the response to capture the Id of this newly created Entity } ``` -Extract the `id` from this JSON and store it in a variable. +Extract the `id` from the JSON and store it in a variable. ## Create Entity Grants -The final step during the signup process will be to assign the correct permissions for the user to their entity. To accomplish this, you will call the [Grant API](/docs/apis/entities/grants#grant-a-user-or-entity-permissions-to-an-entity). In order to call this API, you will need the entity and user Ids. Here's how the JSON will look for the grant request: +The final step during the signup process assigns the correct permissions for the User to their Entity. To do this, call the [grant permissions API](/docs/apis/entities/grants#grant-a-user-or-entity-permissions-to-an-entity). You will need the Entity and User Ids to call this API. The JSON for the grant request will look like this. ```json { @@ -102,29 +106,29 @@ The final step during the signup process will be to assign the correct permissio } ``` -You'll notice that the JSON only includes the User Id. The Entity Id is added to the URL when calling this API like this: +Notice that the JSON only includes the User Id. The Entity Id is added to the URL when calling this API, like this. ```http -POST /api/entity//grant +POST /api/entity//grant ``` -It's important to note that the User Id can be determined in a number of different ways, depending on how your registration process is set up. If you are using FusionAuth for registration, you can extract the User Id from the JWT access token that FusionAuth provides at the end of the OAuth workflow. The user Id is stored in the `sub` claim. Or you can use the [User Info](/docs/lifecycle/authenticate-users/oauth/endpoints#userinfo) or [Introspect](/docs/lifecycle/authenticate-users/oauth/endpoints#introspect) APIs with the access token to retrieve the user details. All of these places will contain the user Id. +Note that the User Id can be determined several different ways, depending on how your registration process is set up. If you are using FusionAuth for registration, you can extract the User Id from the JWT access token that FusionAuth provides at the end of the OAuth workflow. The User Id is stored in the `sub` claim. Or you can use the [UserInfo](/docs/lifecycle/authenticate-users/oauth/endpoints#userinfo) or [Introspect](/docs/lifecycle/authenticate-users/oauth/endpoints#introspect) APIs with the access token to retrieve the User details. -Now you have constructed all the necessary pieces to model the customers of AwesomeCRM and the users that have access to the customer accounts. +Now you have constructed all the necessary pieces to model the customers of AwesomeCRM and the Users that have access to the customer accounts. ## Login -Now that your data model is prepared, you need to handle login events. When a user logs in, your application needs to know what organization they belong to. Generally, this information is stored in a cookie or in a server-side session, such that it is available on each request to the application. +Now that your data model is prepared, you need to handle login events. When a user logs in, your application needs to know what organization they belong to. Generally, this information is stored in a cookie or a server-side session so that it is available on each request to the application. -To get this information from FusionAuth, you will call the [Search Grants](/docs/apis/entities/grants#search-for-grants) API. This API allows you to retrieve all of the grants that a specific user has to any Entities. This API doesn't take a JSON body, but we will supply the User Id on the URL. The URL looks like this: +To get this information from FusionAuth, call the [search grants API](/docs/apis/entities/grants#search-for-grants), which allows you to retrieve all the Grants a specific User has to any Entities. This API doesn't take a JSON body. Supply the User Id in the URL as below. ```http GET /api/entity/grant/search?userId={userId} ``` -You will replace the `userId` parameter with the Id of the user that is currently logged in. In the same manner as above, this information can be retrieved from the access token JWT or the [User Info](/docs/lifecycle/authenticate-users/oauth/endpoints#userinfo) or [Introspect](/docs/lifecycle/authenticate-users/oauth/endpoints#introspect) APIs. +Replace the `userId` parameter with the Id of the user that is currently logged in. Retrieve the User's organization information from the access token JWT or the [UserInfo](/docs/lifecycle/authenticate-users/oauth/endpoints#userinfo) or [Introspect](/docs/lifecycle/authenticate-users/oauth/endpoints#introspect) APIs. -The response from this API looks like this: +The response from the search grants API looks like this. ```json { @@ -165,15 +169,41 @@ The response from this API looks like this: } ``` -You can see that the permissions are available in the response. You can extract the permissions and use them to authorize actions that the user takes or APIs they are calling. In this example, the User has the `Admin` permissions, which means they are likely allowed to do anything they wish. +You can see that the permissions are available in the response. You can extract the permissions and use them to authorize actions that the user takes or APIs they call. In this example, the User has `Admin` permission, which means they are allowed to do anything they wish. + +You can store the `grant` object (or some portion of it) in various locations for easy access, for example, in a cookie (encrypted is preferred), a server-side session, or a database. The [search grants API](/docs/apis/entities/grants#search-for-grants) is designed to be queried frequently and returned quickly. Depending on the scale of the application and where FusionAuth is deployed, you could query this API for each request, ensuring that the User's permissions are always the most current. + +In the companion application, the `grant` object is loaded via a middleware function and appended to the `user` object so it is available in the `req` object for each request. This middleware function is called `loadGrants` and is shown below. + + + +The `loadGrants` function is then added to the Express `app` request pipeline: + + + + +The `loadGrants` middleware function first checks if the user is authenticated before trying to retrieve the Grants, as the User is needed to find the Grants. Therefore, immediately before authentication with Passport in the `passport.authenticate` callback pipeline, the `loadGrants` middleware exits early because the User is not yet available. To tack the Grants onto the user object in this special request flow, the `loadGrants` middleware function is added to the `passport.authenticate` callback pipeline. -The `grant` object, or some portion of it, can be stored in any number of locations for easy access. You could store it in a cookie (encrypted is preferred), a server-side session, or a database. The [Search Grants API](/docs/apis/entities/grants#search-for-grants) is designed to be queried repeatedly and returned quickly, so depending on the scale of the application and where FusionAuth is deployed, you could also query this API for each request. This has the benefit of ensuring that the User's permissions are always the most current version. + + + +Once the Grant with permissions is loaded, you can use it to authorize actions in your application. For example, you can check if the user has the `billing` permission before allowing them to view the billing page. + +The companion application uses another custom middleware function called `checkGrantPermissions` to check if the user has the required permission to access a route. + + + +This middleware function can be used on individual routes as below. + + + +Notice that [all routes in the companion application](https://github.com/fusionauth/fusionauth-example-modeling-organizations/tree/main/complete-application/routes) are protected by the `checkGrantPermissions` middleware function, with the appropriate permissions required to access the route. ## Multiple Organizations -The final component that will be covered in this guide is handling multiple organizations for a single user. AwesomeCRM works with many partners and often these partners work with many clients. This means that a user at a partner company might be working with multiple organizations at the same time. To handle this scenario, you need to ensure you can handle multiple results from the [Retrieve Grants](/docs/apis/entities/grants#retrieve-grants) API. +The final component to cover in this guide is handling multiple organizations for a single User. AwesomeCRM works with many partners, and often these partners work with many clients. This means that a user at a partner company might be working with multiple organizations at the same time. To handle this scenario, you need to ensure you can handle multiple results from the [Retrieve Grants API](/docs/apis/entities/grants#retrieve-grants). -Here's an example of the response from the [Retrieve Grants](/docs/apis/entities/grants#retrieve-grants) API when a user has multiple organizations (many properties have been trimmed for brevity): +Here's an example of the response from the [Retrieve Grants API](/docs/apis/entities/grants#retrieve-grants) when a User has multiple organizations (many properties have been trimmed for brevity). ```json { @@ -214,23 +244,39 @@ Here's an example of the response from the [Retrieve Grants](/docs/apis/entities } ``` -This response indicates that the User belongs to 3 organizations and has various permissions for each. To manage this in your AwesomeCRM application, you can present an option to the user when they log in, to select the company they'd like to work on initially. This option screen might look like this: +This response indicates that the user belongs to three organizations and has different permissions for each. To manage this in your AwesomeCRM application, you can provide users with an option to select the company they would like to work on when they log in, as in the example below. ![Company Selection](/img/guides/organizations/account-select.png) + +Notice that in the companion app `passport.authenticate` pipeline, when the user is authenticated the first time, the first Grant is selected as the default Entity for the user and added to the `req.session` object on the `selectedGrant` property. + + + +When the user selects another Entity to work on from the index page, the `selectedGrant` is updated with the new Entity. + + + ## Managing Users -Often applications provide the ability for users to manage other users on their account. This is accomplished in much the same way as described above. To add a user to an organization, you can use the [Grant API](/docs/apis/entities/grants#grant-a-user-or-entity-permissions-to-an-entity). To remove a user from an organization, you can use the [Delete a Grant](/docs/apis/entities/grants#delete-a-grant) API. If you need to adjust the permissions a user has to an organization, you can use the same [Grant API](/docs/apis/entities/grants#grant-a-user-or-entity-permissions-to-an-entity) from above. The Grant API is an upsert, which means that if a grant already exists, it will update its attributes. +Applications often allow Users to manage other Users on their account. -## Changing An Organization +* Add a User to an organization using the [grant permissions API](/docs/apis/entities/grants#grant-a-user-or-entity-permissions-to-an-entity). +* Remove a User from an organization using the [Delete a Grant API](/docs/apis/entities/grants#delete-a-grant). +* Adjust the permissions a User has to an organization using the [grant permissions API](/docs/apis/entities/grants#grant-a-user-or-entity-permissions-to-an-entity). The grant permissions API is an upsert, which means that if a Grant already exists, it will update its attributes. + +In the companion app, managing Users is demonstrated in the [`routes/users.js` file](https://github.com/fusionauth/fusionauth-example-modeling-organizations/blob/main/complete-application/routes/users.js). There is a trick to getting all Users filtered by FusionAuth application. By default, getting Users from FusionAuth will return all Users in the containing tenant. You will need to use a search query combined with the [Search for Users API](/docs/apis/users#search-for-users) to find all Users in the particular application. The companion app demonstrates this in the `GET /users` route, using an [Elasticsearch query](/docs/lifecycle/manage-users/search/user-search-with-elasticsearch) to filter Users by application. + +After filtering for the Users you want to manage, use the [grant search API function](/docs/apis/entities/grants#search-for-grants) to retrieve the Grants for each User. In the companion application, Grants are managed for a single Entity (or company) at a time. Since the API returns all Grants to all Entities associated with a User, the application filters the Grants to only show the Grant for the selected Entity. + + -Beyond managing users, some applications provide the ability to rename or modify a user's organization. To update an Entity, you can use the [Update an Entity](/docs/apis/entities/entities#update-an-entity) API. This allows any attribute of the Entity to be updated, including custom data. ## Custom Data And Search -Custom data on an entity can be used to store additional information about the Entity, such as various ids (Stripe, QuickBooks, NetSuite, etc), organization attributes (locations, parent company, etc), or just about anything that is needed. Custom data on an Entity is indexed within FusionAuth, which means it is also searchable using the [Entity Search API](/docs/apis/entities/entities#search-for-entities). +Custom data on an Entity can be used to store additional information about the Entity, like various Ids (for Stripe, QuickBooks, or NetSuite), organization attributes (locations, parent company, and so on), or just about anything you need. Custom data on an Entity is indexed within FusionAuth, which means it is also searchable using the [Search for Entities API](/docs/apis/entities/entities#search-for-entities). -Let's say that your organizations have a custom attribute for the address like this: +For example, say your organizations have a custom attribute for addresses like below. ```json { @@ -249,16 +295,27 @@ Let's say that your organizations have a custom attribute for the address like t ``` -You can search for this attribute using this request: +You can search for the address attribute using a request like this. ```http GET /api/entity/search?queryString=data.address.city:denver ``` -This uses the [Elasticsearch query string query syntax](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax). +This request uses the [Elasticsearch query string query syntax](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax). + +The companion application stores the address of the company in the Entity custom data, which is displayed on the `Admin` page. The custom data is returned with the Entity when it is retrieved using the [Retrieve an Entity API](/docs/apis/entities/entities#retrieve-an-entity) and doesn't need to be loaded separately. + +## Changing An Organization + +Beyond managing users, some applications allow you to rename or modify a User's organization. Use the [Update an Entity API](/docs/apis/entities/entities#update-an-entity) to update any Entity attribute, including custom data. + +This is demonstrated in the companion app in the [`routes/admin.js` file](https://github.com/fusionauth/fusionauth-example-modeling-organizations/blob/main/complete-application/routes/admin.js). This route can update the Entity name and the company address. Use the `PATCH` HTTP method for this type of operation, as it allows you to update only the fields that have changed, even when updating custom data. + + + ## Conclusion -This is just one of the nearly infinite uses for FusionAuth's Entity Management feature. It allows applications to easily implement a data model for organizations and permissions and grant the permissions to users. Some other uses for Entities include IOT (permissions to devices), machine-to-machine clients (OAuth Client Credentials), [SCIM](/docs/lifecycle/migrate-users/scim/) clients, and many more. +This is just one of the many uses for the FusionAuth Entity Management feature, allowing you to easily implement a data model for organizations and permissions and grant the permissions to users in your application. Other uses for Entity Management include IOT (permissions to devices), machine-to-machine clients (OAuth Client Credentials), [SCIM](/docs/lifecycle/migrate-users/scim/) clients, and many more. + -Enjoy and happy coding! diff --git a/astro/src/content/docs/get-started/core-concepts/applications.mdx b/astro/src/content/docs/get-started/core-concepts/applications.mdx index ba4596cafa..9758632550 100644 --- a/astro/src/content/docs/get-started/core-concepts/applications.mdx +++ b/astro/src/content/docs/get-started/core-concepts/applications.mdx @@ -183,7 +183,7 @@ The multi-factor configuration allows you to provide Application specific multi- * No application policy selected. Multi-factor authentication is managed by the tenant. * Enabled. A challenge will be required during login when an eligible method is available. * Disabled. A challenge will not be required during login. - * Required. A challenge will be required during login.   + * Required. A challenge will be required during login.  
    When On login policy is set to `Enabled` or `Required`, the following field will be displayed. This value will control how the two-factor trust value is utilized. diff --git a/astro/src/content/docs/get-started/core-concepts/entity-management.mdx b/astro/src/content/docs/get-started/core-concepts/entity-management.mdx index 08ebd5d08e..c24fe6c8f7 100644 --- a/astro/src/content/docs/get-started/core-concepts/entity-management.mdx +++ b/astro/src/content/docs/get-started/core-concepts/entity-management.mdx @@ -9,6 +9,7 @@ import APIBlock from 'src/components/api/APIBlock.astro'; import APIField from 'src/components/api/APIField.astro'; import Aside from 'src/components/Aside.astro'; import Icon from 'src/components/icon/Icon.astro' +import ScimServerPermissions from 'src/content/docs/_shared/_scim-server-permissions.md' @@ -182,28 +183,11 @@ The default entity types are named **[FusionAuth Default] SCIM client** and **[F Home Screen SCIM Entity Types -### SCIM server permissions - -Below is a list of available permissions that can be included in your SCIM server entity type. Each controls access to a single API endpoint. You can choose to create as few or as many of these as you require. The names must match exactly. - - -| Name | Access to API | -|-------------------------------------|--------------------------------------------------------------------------------------------------------------------------| -| `scim:enterprise:user:create` | [Create an Enterprise User](/docs/apis/scim/scim-enterprise-user#create-an-enterpriseuser) | -| `scim:enterprise:user:read` | [Retrieve an Enterprise User](/docs/apis/scim/scim-enterprise-user#retrieve-an-enterpriseuser) | -| `scim:enterprise:user:update` | [Update an Enterprise User](/docs/apis/scim/scim-enterprise-user#update-an-enterpriseuser) | -| `scim:enterprise:user:delete` | [Delete an Enterprise User](/docs/apis/scim/scim-enterprise-user#delete-an-enterpriseuser) | -| `scim:group:create` | [Create a Group](/docs/apis/scim/scim-group#create-a-group) | -| `scim:group:read` | [Retrieve a Group](/docs/apis/scim/scim-group#retrieve-a-group) | -| `scim:group:update` | [Update a Group](/docs/apis/scim/scim-group#update-a-group) | -| `scim:group:delete` | [Delete a Group](/docs/apis/scim/scim-group#delete-a-group) | -| `scim:resource-types:read` | [Retrieve Resource Types](/docs/apis/scim/scim-service-provider#retrieve-resource-types) | -| `scim:schemas:read` | [Retrieve Schemas](/docs/apis/scim/scim-service-provider#retrieve-schemas) | -| `scim:service-provider-config:read` | [Retrieve Service Provider Configuration](/docs/apis/scim/scim-service-provider#retrieve-service-provider-configuration) | -| `scim:user:create` | [Create a User](/docs/apis/scim/scim-user#create-a-user) | -| `scim:user:read` | [Retrieve a User](/docs/apis/scim/scim-user#retrieve-a-user) | -| `scim:user:update` | [Update a User](/docs/apis/scim/scim-user#update-a-user) | -| `scim:user:delete` | [Delete a User](/docs/apis/scim/scim-user#delete-a-user) | +[Learn more about SCIM](/docs/lifecycle/migrate-users/scim/). + +### SCIM Server Permissions + + ## Limitations diff --git a/astro/src/content/docs/get-started/core-concepts/hosted-login-vs-api-login.mdx b/astro/src/content/docs/get-started/core-concepts/hosted-login-vs-api-login.mdx index d0cd7a2110..63f9fff008 100644 --- a/astro/src/content/docs/get-started/core-concepts/hosted-login-vs-api-login.mdx +++ b/astro/src/content/docs/get-started/core-concepts/hosted-login-vs-api-login.mdx @@ -24,7 +24,7 @@ Hosted login pages are a popular choice for many developers. This is especially |Includes single sign-on (SSO) between different apps.|Upgrades can be problematic unless you're using Simple Themes.| |Localization support.|Limited workflow customization.| |New workflows added regularly so you gain function without added development work.|| -|Doesn't exclude API usage. You can add custom logic such as reidrects or requiring MFA for certain groups.|| +|Doesn't exclude API usage. You can add custom logic such as redirects or requiring MFA for certain groups.|| ### Example Hosted Login Page on Mobile The image below shows the mobile login experience for [Audacy](https://audacy.com). As discussed in the preceding chart, you can see the address bar and UX components that are from the system browser, rather than the native UX components that your customers will see in your application. diff --git a/astro/src/content/docs/get-started/core-concepts/integration-points.mdx b/astro/src/content/docs/get-started/core-concepts/integration-points.mdx index 839fa5e4e7..fd66d5f5e5 100644 --- a/astro/src/content/docs/get-started/core-concepts/integration-points.mdx +++ b/astro/src/content/docs/get-started/core-concepts/integration-points.mdx @@ -75,7 +75,7 @@ But what should you do with it? After all, an access token is a bearer token, an Recommended storage mechanisms include: -* sending the token down to the browser as a `Secure`, `HTTPOnly` cookie. If you don't require cross-site cookie sharing, set `SameSite` to `Strict`. Otherwise, set `SameSite` to `Lax`, which will share the cookies in certain situations. Learn more about [`SameSite` settings](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite). +* sending the token down to the browser as a `Secure`, `HttpOnly` cookie. If you don't require cross-site cookie sharing, set `SameSite` to `Strict`. Otherwise, set `SameSite` to `Lax`, which will share the cookies in certain situations. Learn more about [`SameSite` settings](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite). * storing it server side, in a session. The session is typically managed by a framework, and ideally adheres to the same cookie storage recommendations. Learn more about [server side sessions](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html). Please consult your framework documentation around securing sessions and data in sessions. *Table 1. JWT Storage Options* @@ -121,7 +121,7 @@ For an example of how the hosted login pages help with common workflows, please ## Hosted Backend -The Authorization Code grant requires the use of a server side application to do the token exchange. This is often called the "backend". This server side code can securely hold secrets, which a client such as a single-page application (SPA) cannot. It also can send the access token to a SPA as a secure, `HTTPOnly` cookie. +The Authorization Code grant requires the use of a server side application to do the token exchange. This is often called the "backend". This server side code can securely hold secrets, which a client such as a single-page application (SPA) cannot. It also can send the access token to a SPA as a secure, `HttpOnly` cookie. Running your own backend offers you a lot of flexibility. However, it is not the correct solution for all situations. diff --git a/astro/src/content/docs/get-started/core-concepts/limitations.mdx b/astro/src/content/docs/get-started/core-concepts/limitations.mdx index a64446e1ce..5011cdbba2 100644 --- a/astro/src/content/docs/get-started/core-concepts/limitations.mdx +++ b/astro/src/content/docs/get-started/core-concepts/limitations.mdx @@ -42,7 +42,7 @@ FusionAuth has the following known limits: FusionAuth stores most data in a database. Lengths of specific fields are documented in the database schema for your database type. Please [download the database schema for your version of FusionAuth](/direct-download) to review length limits for a particular column. -Many varchar columns have a length of 191. Why 191? In MySQL when using a `utf8mb4` (4 byte character set) on an indexed column, MySQL limits the usable characters to 191 to account for the overhead of the 4 byte addressing. The InnoDB MySQL engine has a max index length of 767 bytes (for mysql 5.7.9, the earliest version of MySQL which [Fusionauth supports](/docs/get-started/download-and-install/system-requirements)). Because we are using `utf8mb4` which allows up to 4 bytes per character, we end up with 767/4 ~ 191, so we set the column length to that. +Many varchar columns have a length of 191. Why 191? In MySQL when using a `utf8mb4` (4 byte character set) on an indexed column, MySQL limits the usable characters to 191 to account for the overhead of the 4 byte addressing. The InnoDB MySQL engine has a max index length of 767 bytes (for mysql 5.7.9, the earliest version of MySQL which [FusionAuth supports](/docs/get-started/download-and-install/system-requirements)). Because we are using `utf8mb4` which allows up to 4 bytes per character, we end up with 767/4 ~ 191, so we set the column length to that. ## API Keys diff --git a/astro/src/content/docs/get-started/core-concepts/roles.mdx b/astro/src/content/docs/get-started/core-concepts/roles.mdx index 4f3632091b..526d851b3a 100644 --- a/astro/src/content/docs/get-started/core-concepts/roles.mdx +++ b/astro/src/content/docs/get-started/core-concepts/roles.mdx @@ -87,45 +87,46 @@ Below are all the roles available in FusionAuth. Please note the additional expl _FusionAuth application roles_ -| Name | Id | Description | -|----------------------------|----------------------------------------|------------------------------------------------------------------------------------| -| `admin` | `631ecd9d-8d40-4c13-8277-80cedb8236e2` | Can manage everything, including creating new users with administrator privileges. | -| `acl_manager` | `631ecd9d-8d40-4c13-8277-80cedb823712` | Can add and edit IP access control lists. | -| `acl_deleter` | `631ecd9d-8d40-4c13-8277-80cedb823711` | Can delete IP access control lists. | -| `api_key_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236e3` | Can add and edit API keys. | -| `application_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236e4` | Can delete applications. | -| `application_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236e5` | Can add and edit applications. | -| `audit_log_viewer` | `631ecd9d-8d40-4c13-8277-80cedb8236e6` | Can view audit logs. | -| `connector_deleter` | `631ecd9d-8d40-4c13-8277-80cedb823700` | Can delete Connectors. | -| `connector_manager` | `631ecd9d-8d40-4c13-8277-80cedb823701` | Can add and edit Connectors. | -| `consent_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236fc` | Can delete consents. | -| `consent_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236fd` | Can add and edit consents. | -| `email_template_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236e7` | Can add and edit email templates. | -| `entity_manager` | `631ecd9d-8d40-4c13-8277-80cedb823706` | Can add and edit entities. | -| `event_log_viewer` | `631ecd9d-8d40-4c13-8277-80cedb8236fa` | Can view the event log. | -| `form_deleter` | `631ecd9d-8d40-4c13-8277-80cedb823702` | Can delete forms and form fields. | -| `form_manager` | `631ecd9d-8d40-4c13-8277-80cedb823703` | Can add and edit forms and form fields. | -| `group_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236f6` | Can delete groups. | -| `group_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f5` | Can add and edit groups. | -| `key_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236fb` | Can add and edit keys. | -| `lambda_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f9` | Can add and edit lambdas. | -| `message_template_deleter` | `631ecd9d-8d40-4c13-8277-80cedb823709` | Can delete message templates. | -| `message_template_manager` | `631ecd9d-8d40-4c13-8277-80cedb823710` | Can add and edit message templates. | -| `messenger_deleter` | `631ecd9d-8d40-4c13-8277-80cedb823707` | Can delete messengers. | -| `messenger_manager` | `631ecd9d-8d40-4c13-8277-80cedb823708` | Can add and edit messengers. | -| `reactor_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236ff` | Can add and edit reactor settings. | -| `report_viewer` | `631ecd9d-8d40-4c13-8277-80cedb8236e8` | Can view reports. | -| `system_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236e9` | Can add and edit system configuration. | -| `tenant_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236f8` | Can delete tenants. | -| `tenant_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f7` | Can add and edit tenants. | -| `theme_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236fe` | Can add and edit themes. | -| `user_action_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236f0` | Can delete user actions. | -| `user_action_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f1` | Can add and edit user actions. | -| `user_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236f2` | Can delete users. | -| `user_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f3` | Can add and edit users.

    Please note that because this role can fully manage users, it is similar to `admin`. The `user_support_manager` is recommended in most cases.| -| `user_support_manager` | `631ecd9d-8d40-4c13-8277-80cedb823704` | Allows for a limited scope of user management. See below. | -| `user_support_viewer` | `631ecd9d-8d40-4c13-8277-80cedb823705` | Can view user information. | -| `webhook_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f4` | Can add or edit webhooks. | +| Name | Id | Description | +|----------------------------|----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `admin` | `631ecd9d-8d40-4c13-8277-80cedb8236e2` | Can manage everything, including creating new users with administrator privileges. | +| `acl_manager` | `631ecd9d-8d40-4c13-8277-80cedb823712` | Can add and edit IP access control lists. | +| `acl_deleter` | `631ecd9d-8d40-4c13-8277-80cedb823711` | Can delete IP access control lists. | +| `api_key_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236e3` | Can add and edit API keys. | +| `application_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236e4` | Can delete applications. | +| `application_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236e5` | Can add and edit applications. | +| `audit_log_viewer` | `631ecd9d-8d40-4c13-8277-80cedb8236e6` | Can view audit logs. | +| `connector_deleter` | `631ecd9d-8d40-4c13-8277-80cedb823700` | Can delete Connectors. | +| `connector_manager` | `631ecd9d-8d40-4c13-8277-80cedb823701` | Can add and edit Connectors. | +| `consent_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236fc` | Can delete consents. | +| `consent_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236fd` | Can add and edit consents. | +| `email_template_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236e7` | Can add and edit email templates. | +| `entity_manager` | `631ecd9d-8d40-4c13-8277-80cedb823706` | Can add and edit entities. | +| `event_log_viewer` | `631ecd9d-8d40-4c13-8277-80cedb8236fa` | Can view the event log. | +| `form_deleter` | `631ecd9d-8d40-4c13-8277-80cedb823702` | Can delete forms and form fields. | +| `form_manager` | `631ecd9d-8d40-4c13-8277-80cedb823703` | Can add and edit forms and form fields. | +| `group_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236f6` | Can delete groups. | +| `group_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f5` | Can add and edit groups. | +| `key_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236fb` | Can add and edit keys. | +| `lambda_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f9` | Can add and edit lambdas. | +| `message_template_deleter` | `631ecd9d-8d40-4c13-8277-80cedb823709` | Can delete message templates. | +| `message_template_manager` | `631ecd9d-8d40-4c13-8277-80cedb823710` | Can add and edit message templates. | +| `messenger_deleter` | `631ecd9d-8d40-4c13-8277-80cedb823707` | Can delete messengers. | +| `messenger_manager` | `631ecd9d-8d40-4c13-8277-80cedb823708` | Can add and edit messengers. | +| `reactor_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236ff` | Can add and edit reactor settings. | +| `report_viewer` | `631ecd9d-8d40-4c13-8277-80cedb8236e8` | Can view reports. | +| `system_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236e9` | Can add and edit system configuration. | +| `tenant_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236f8` | Can delete tenants. | +| `tenant_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f7` | Can add and edit tenants. | +| `theme_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236fe` | Can add and edit themes. | +| `user_action_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236f0` | Can delete user actions. | +| `user_action_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f1` | Can add and edit user actions. | +| `user_deleter` | `631ecd9d-8d40-4c13-8277-80cedb8236f2` | Can delete users. | +| `user_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f3` | Can add and edit users.

    Please note that because this role can fully manage users, it is similar to `admin`. The `user_support_manager` is recommended in most cases. | +| `user_support_manager` | `631ecd9d-8d40-4c13-8277-80cedb823704` | Allows for a limited scope of user management. See below. | +| `user_support_viewer` | `631ecd9d-8d40-4c13-8277-80cedb823705` | Can view user information. | +| `webhook_event_log_viewer` | `631ecd9d-8d40-4c13-8277-80cedb823713` | Can view the webhook event log. | +| `webhook_manager` | `631ecd9d-8d40-4c13-8277-80cedb8236f4` | Can add or edit webhooks. | ## Special Role - user_support_manager diff --git a/astro/src/content/docs/get-started/core-concepts/tenants.mdx b/astro/src/content/docs/get-started/core-concepts/tenants.mdx index 01a9c9f695..22eb70de8e 100644 --- a/astro/src/content/docs/get-started/core-concepts/tenants.mdx +++ b/astro/src/content/docs/get-started/core-concepts/tenants.mdx @@ -281,7 +281,7 @@ Once you have configured your email settings, you may test your configuration wi * Enabled. A challenge will be required during login when an eligible method is available. * Disabled. A challenge will not be required during login. - * Required. A challenge will be required during login.   + * Required. A challenge will be required during login.  
    @@ -652,6 +652,9 @@ The SCIM server configuration to enable incoming SCIM client provisioning reques When an `applicationId` is provided, the application configuration will take precedence. In almost all cases you will want to leave this enabled to require the use of an API key.
    + + The lambda assigned to perform extended validation during login requests. + ##### Access control lists settings @@ -758,6 +761,9 @@ The Rate limit settings allow you to set a number of times an action can be atte The number of seconds before the External Authentication identifier is no longer valid to complete the Authentication request. + + The number of seconds before the Login Timeout identifier is no longer valid to complete post-authentication steps in the OAuth workflow. + The number of seconds before the One Time Password identifier is no longer valid to complete a Login request. @@ -788,6 +794,12 @@ The Rate limit settings allow you to set a number of times an action can be atte The number of seconds before the Two Factor Trust is no longer valid and the user will be prompted for Two Factor during login. + + The number of seconds before the WebAuthn authentication challenge is no longer valid and the user will need to restart the authentication workflow. + + + The number of seconds before the WebAuthn registration challenge is no longer valid and the user will need to restart the credential registration workflow. + diff --git a/astro/src/content/docs/get-started/core-concepts/users.mdx b/astro/src/content/docs/get-started/core-concepts/users.mdx index 348e6835f0..8b7edd4e51 100644 --- a/astro/src/content/docs/get-started/core-concepts/users.mdx +++ b/astro/src/content/docs/get-started/core-concepts/users.mdx @@ -37,7 +37,7 @@ Below is a visual reminder of the relationships between FusionAuth's primary cor This page describes the admin UI for creating and managing users. -{/* These are not capitalized because we are matching the exact names for the tabs in the admin ui. */} +{/* These are not capitalized because we are matching the exact names for the tabs in the admin UI. */} ### List of Users @@ -752,7 +752,7 @@ Here's a table with the strengths and challenges of each option. | [Tenants](#tenants) | True separation of users, API keys, connectors and other user related configuration | Cross-tenant user access, users can't be moved between tenants without resetting password | | [Applications and Registrations](#applications-and-registrations) | Inherits settings from containing tenant, can separate users based on registration, with paid plan can configure application specific themes, unlimited roles| If FusionAuth SSO enabled user can SSO between each application, must check tokens in application | | [Groups](#groups) | Contained in a tenant, can apply application roles to all members | Can't apply registrations to all members of a group, need lambda API call to add membership to tokens | -| [Entities And Grants](#entities-and-grants) | Fine grained permissions, searchable, can cross-cut tenants and applications, can manage permissions between users and entities or entities and entities | Requires proprietary APIs to manage, no inheritance of permissions, need lambda API call to add membership to tokens | +| [Entities And Grants](#entities-and-grants) | Fine grained permissions, searchable, can cross-cut applications, can manage permissions between users and entities or entities and entities | Requires proprietary APIs to manage, no inheritance of permissions, need lambda API call to add membership to tokens | | [User.data](#the-userdata-field) | Searchable, arbitrary JSON that you control, easily added to tokens | Pure data so all authorization decisions need to be made by your application, need to be careful with data types | ### Tenants @@ -761,7 +761,7 @@ Each FusionAuth tenant is a logical grouping of users, configuration and applica Users are tenant scoped. This means a user with the same identifier (email, username, etc) in two different tenants is a different account. They can have different passwords, identity provider links and profile attributes. -You can search for users across tenants using the [User Search API)(/docs/apis/users#search-for-users). +You can search for users across tenants using the [User Search API](/docs/apis/users#search-for-users). An example use case is a private label SaaS application for managing todos and tasks. You want a user to sign up for two or more different instances of your SaaS and never know that there is a shared identity store behind them. For example, richard@piedpiper.com can sign up for the Pied Piper Todo application and the Hooli Todo Application with the same email address, but different passwords, MFA methods and more. diff --git a/astro/src/content/docs/get-started/download-and-install/database.mdx b/astro/src/content/docs/get-started/download-and-install/database.mdx index 62ad3a07d0..40f0d6110c 100644 --- a/astro/src/content/docs/get-started/download-and-install/database.mdx +++ b/astro/src/content/docs/get-started/download-and-install/database.mdx @@ -40,7 +40,7 @@ If you are installing MySQL on a platform that does not supports RPM or DEB pack #### MySQL and Unicode