diff --git a/.github/workflows/contentcheck.yml b/.github/workflows/contentcheck.yml index ed47d6e42a..6e2c2e6075 100644 --- a/.github/workflows/contentcheck.yml +++ b/.github/workflows/contentcheck.yml @@ -19,7 +19,7 @@ jobs: - name: Check for blog posts that have incorrect categories run: | find astro/src/content/blog/ -type f -name "*.md*" |grep -v swp | xargs grep '^categories:'|sed 's/.*categories: //'|sed 's/, /\n/g'|sort -u > out - RES=`diff out .github/known-blog-categories.txt` + RES=`diff out config/contentcheck/known-blog-categories.txt` exit $RES shell: bash - name: Grep for absolute URLs referencing FusionAuth.io diff --git a/.github/workflows/devlinkcheck.yml b/.github/workflows/devlinkcheck.yml index 0ff3a6a70c..39e41b9ecf 100644 --- a/.github/workflows/devlinkcheck.yml +++ b/.github/workflows/devlinkcheck.yml @@ -16,5 +16,5 @@ jobs: - uses: actions/checkout@v4 - uses: filiph/linkcheck@3.0.0 with: - arguments: https://fusionauth.dev/docs/ --skip-file .github/linkcheck-skip.txt --connection-failures-as-warnings + arguments: https://fusionauth.dev/docs/ --skip-file config/linkcheck/linkcheck-skip.txt --connection-failures-as-warnings name: linkcheck diff --git a/.github/workflows/exampleappscheck.yml b/.github/workflows/exampleappscheck.yml index 6603852214..77a32464fa 100644 --- a/.github/workflows/exampleappscheck.yml +++ b/.github/workflows/exampleappscheck.yml @@ -3,7 +3,7 @@ name: example_app_check on: pull_request: paths: - - '.github/scripts/count-repos.sh' + - 'src/scripts/count-repos.sh' - '.github/workflows/exampleappcheck.yml' - 'astro/src/content/json/exampleapps.json' - 'astro/src/content/quickstarts/**' @@ -18,4 +18,4 @@ jobs: - uses: actions/checkout@v4 - name: Check for example app completeness - run: .github/scripts/count-repos.sh + run: src/scripts/count-repos.sh diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index b1be7c3614..2d5fbac57c 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -19,5 +19,5 @@ jobs: - uses: actions/checkout@v4 - uses: filiph/linkcheck@3.0.0 with: - arguments: https://fusionauth.io/ --skip-file .github/linkcheck-skip.txt --connection-failures-as-warnings + arguments: https://fusionauth.io/ --skip-file config/linkcheck/linkcheck-skip.txt --connection-failures-as-warnings name: linkcheck diff --git a/.github/workflows/updatesitemap.yml b/.github/workflows/updatesitemap.yml index bd688856cc..a555538b1d 100644 --- a/.github/workflows/updatesitemap.yml +++ b/.github/workflows/updatesitemap.yml @@ -21,11 +21,11 @@ jobs: with: node-version: 20 cache: 'npm' - cache-dependency-path: '.github/scripts/publish_sitemap/package-lock.json' + cache-dependency-path: '.src/scripts/publish_sitemap/package-lock.json' - name: Install dependencies - run: cd .github/scripts/publish_sitemap && npm install + run: cd src/scripts/publish_sitemap && npm install - name: Update sitemap env: GOOGLE_SEARCH_CONSOLE_JSON_KEY: ${{ secrets.GOOGLE_SEARCH_CONSOLE_JSON_KEY }} - run: node .github/scripts/publish_sitemap/publish_sitemap.js + run: node src/scripts/publish_sitemap/publish_sitemap.js shell: bash diff --git a/.spellcheck.yaml b/.spellcheck.yaml index 044f01c7bc..806d620bee 100644 --- a/.spellcheck.yaml +++ b/.spellcheck.yaml @@ -8,7 +8,7 @@ matrix: dictionary: encoding: utf-8 wordlists: - - .github/knownwords.txt + - config/spellcheck/knownwords.txt pipeline: - pyspelling.filters.url: - pyspelling.filters.html: diff --git a/.vale.ini b/.vale.ini index 13be19eb30..3f50db5454 100644 --- a/.vale.ini +++ b/.vale.ini @@ -1,4 +1,4 @@ -StylesPath = .github/vale/styles +StylesPath = config/vale/styles Vocab = FusionAuth MinAlertLevel = error diff --git a/DocsDevREADME.md b/DocsDevREADME.md index 285d79f49f..c2027e3323 100644 --- a/DocsDevREADME.md +++ b/DocsDevREADME.md @@ -175,7 +175,7 @@ Follow everything in the `Content Style Guidelines` section. - For site navigation, use double quotes: Navigate to "Tenants" and then to the "Password" tab. - For field names, use double quotes: "Login Identifier Attribute". - For values, use back ticks: `userPrincipalName`. -- Put each blog post into one or more of the known categories. [Here's the list](https://github.com/FusionAuth/fusionauth-site/blob/main/.github/known-blog-categories.txt). You can separate categories with commas. +- Put each blog post into one or more of the known categories. [Here's the list](https://github.com/FusionAuth/fusionauth-site/blob/main/config/contentcheck/known-blog-categories.txt). You can separate categories with commas. - Use tags. They are separated with commas. These are freeform, so feel free to add multiple and choose what works. The first one is what is used to show related posts, unless there's a `featuredTag` value in the front matter. You can [learn more about the logic by reviewing the layout](https://github.com/FusionAuth/fusionauth-site/blob/main/astro/src/layouts/Blog.astro). - You can use the `get-images-from-markdown.rb` script to extract images from markdown and store them in a directory. - All references to `stackoverflow.com` should be updated and direct to the community forum at `https://fusionauth.io/community/forum/` @@ -452,9 +452,9 @@ The main configuration file is located at [`.vale.ini`](./.vale.ini), where we s ### Rules -- The rules _(or, as Vale calls them, "styles")_ are located at [`.github/vale/styles`](./.github/vale/styles). -- Right now, we're using [`write-good`](./.github.vale/styles/write-good), a collection of simple rules to avoid common mistakes and awkward sentences. -- We also have a custom vocabulary at [`.github/vale/styles/config/vocabularies/FusionAuth/accept.txt`](./.github/vale/styles/config/vocabularies/FusionAuth/accept.txt) with known words. +- The rules _(or, as Vale calls them, "styles")_ are located at [`config/vale/styles`](./config/vale/styles). +- 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/). ### GitHub Actions @@ -488,7 +488,7 @@ $ vale --filter=".Name == 'Vale.Spelling'" astro/path/to/file Whenever you receive an error, you need to determine if you should: - Actually fix the word (e.g. if you received an error like _"Use 'Id' instead of 'ID'."_); or -- Add a known word to [`the vocabulary`](./.github/vale/styles/config/vocabularies/FusionAuth/accept.txt) if it's a language, library, company name, etc. But make sure you have the correct capitalization to avoid having duplicates there; or +- Add a known word to [`the vocabulary`](./config/vale/styles/config/vocabularies/FusionAuth/accept.txt) if it's a language, library, company name, etc. But make sure you have the correct capitalization to avoid having duplicates there; or - In case of custom Astro components, you'd probably need to add a new `TokenIgnores` item in [`.vale.ini`](./.vale.ini). ## Pull request review process diff --git a/astro/public/img/blogs/announcing-152/fusionauth-1-52.png b/astro/public/img/blogs/announcing-152/fusionauth-1-52.png new file mode 100644 index 0000000000..5e6364a1e1 Binary files /dev/null and b/astro/public/img/blogs/announcing-152/fusionauth-1-52.png differ diff --git a/astro/public/img/blogs/announcing-152/fusionauth-platypus.jpg b/astro/public/img/blogs/announcing-152/fusionauth-platypus.jpg new file mode 100644 index 0000000000..230571569a Binary files /dev/null and b/astro/public/img/blogs/announcing-152/fusionauth-platypus.jpg differ diff --git a/astro/public/img/blogs/fusionauth-inteligov/fusionauth-inteligov.png b/astro/public/img/blogs/fusionauth-inteligov/fusionauth-inteligov.png new file mode 100644 index 0000000000..b54cd26112 Binary files /dev/null and b/astro/public/img/blogs/fusionauth-inteligov/fusionauth-inteligov.png differ diff --git a/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-add-route.png b/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-add-route.png new file mode 100644 index 0000000000..7276fc5746 Binary files /dev/null and b/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-add-route.png differ diff --git a/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-create-worker.png b/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-create-worker.png new file mode 100644 index 0000000000..13d2cebf60 Binary files /dev/null and b/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-create-worker.png differ diff --git a/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-pages-overview.png b/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-pages-overview.png new file mode 100644 index 0000000000..9ce5c8134e Binary files /dev/null and b/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-pages-overview.png differ diff --git a/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-preview-worker.png b/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-preview-worker.png new file mode 100644 index 0000000000..93e6d4074d Binary files /dev/null and b/astro/public/img/docs/extend/examples/api-gateways/cloudflare-workers-preview-worker.png differ diff --git a/astro/public/img/docs/extend/examples/api-gateways/new-user.png b/astro/public/img/docs/extend/examples/api-gateways/new-user.png new file mode 100644 index 0000000000..58f00ec709 Binary files /dev/null and b/astro/public/img/docs/extend/examples/api-gateways/new-user.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/added-roles.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/added-roles.png new file mode 100644 index 0000000000..6c819725d0 Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/added-roles.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/connector-added.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/connector-added.png new file mode 100644 index 0000000000..615b1386ba Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/connector-added.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/connector-policy.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/connector-policy.png new file mode 100644 index 0000000000..2b34d6560c Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/connector-policy.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/connector.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/connector.png new file mode 100644 index 0000000000..557c033bf4 Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/connector.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/create-connector.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/create-connector.png new file mode 100644 index 0000000000..6059cb287c Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/create-connector.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/env-settings.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/env-settings.png new file mode 100644 index 0000000000..c12167bb5b Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/env-settings.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/goto-builder.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/goto-builder.png new file mode 100644 index 0000000000..9a1cc9501b Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/goto-builder.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/imported-users.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/imported-users.png new file mode 100644 index 0000000000..9c0c4dfb5e Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/imported-users.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/login-url.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/login-url.png new file mode 100644 index 0000000000..4a89127cc1 Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/login-url.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/permissions.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/permissions.png new file mode 100644 index 0000000000..93102edb2b Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/permissions.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/signup.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/signup.png new file mode 100644 index 0000000000..5c0e750774 Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/signup.png differ diff --git a/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/users.png b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/users.png new file mode 100644 index 0000000000..632c7075dd Binary files /dev/null and b/astro/public/img/docs/lifecycle/migrate-users/provider-specific/frontegg/users.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/add-metrics-dashboard.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/add-metrics-dashboard.png new file mode 100644 index 0000000000..5eadc1adcf Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/add-metrics-dashboard.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/aws-get-region.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/aws-get-region.png new file mode 100644 index 0000000000..d1b2207e91 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/aws-get-region.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/cloudwatch-dashboard-custom-logger.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/cloudwatch-dashboard-custom-logger.png new file mode 100644 index 0000000000..6af23cc5fb Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/cloudwatch-dashboard-custom-logger.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/cloudwatch-dashboard.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/cloudwatch-dashboard.png new file mode 100644 index 0000000000..fccd421987 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/cloudwatch-dashboard.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/cloudwatch-fusionauth-applications-id.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/cloudwatch-fusionauth-applications-id.png new file mode 100644 index 0000000000..b65b127afe Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/cloudwatch-fusionauth-applications-id.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-api-key-fusionauth.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-api-key-fusionauth.png new file mode 100644 index 0000000000..a14aec177d Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-api-key-fusionauth.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-aws-account.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-aws-account.png new file mode 100644 index 0000000000..dce4b0b3a9 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-aws-account.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-aws-cloudwatchagnetrole.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-aws-cloudwatchagnetrole.png new file mode 100644 index 0000000000..470a98aa80 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-aws-cloudwatchagnetrole.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-dashboard-widget-custom-logger.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-dashboard-widget-custom-logger.png new file mode 100644 index 0000000000..3277892a17 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-dashboard-widget-custom-logger.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-dashboard-widget.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-dashboard-widget.png new file mode 100644 index 0000000000..09510d1f8a Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-dashboard-widget.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-ec2-success.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-ec2-success.png new file mode 100644 index 0000000000..c414373e8d Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-ec2-success.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-ecs-instance-settings-1.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-ecs-instance-settings-1.png new file mode 100644 index 0000000000..3ebebf674c Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-ecs-instance-settings-1.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-key-pair.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-key-pair.png new file mode 100644 index 0000000000..f07b68be71 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-key-pair.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-log-table-widget.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-log-table-widget.png new file mode 100644 index 0000000000..b66f57e47e Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/create-log-table-widget.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/ec2-instance-overview.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/ec2-instance-overview.png new file mode 100644 index 0000000000..d328481b0e Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/ec2-instance-overview.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/login-record-api-key-fusionauth.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/login-record-api-key-fusionauth.png new file mode 100644 index 0000000000..330f35b1d7 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/login-record-api-key-fusionauth.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/navigate-iam-roles.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/navigate-iam-roles.png new file mode 100644 index 0000000000..9c81789829 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/navigate-iam-roles.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/open-port-9011.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/open-port-9011.png new file mode 100644 index 0000000000..8eb2293f13 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/open-port-9011.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/select-dashboard-options.png b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/select-dashboard-options.png new file mode 100644 index 0000000000..1f43134847 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/cloudwatch/select-dashboard-options.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic10.png b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic10.png new file mode 100644 index 0000000000..e8a8b53527 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic10.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic2.png b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic2.png new file mode 100644 index 0000000000..d16473fa23 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic2.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic3.png b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic3.png new file mode 100644 index 0000000000..1eb4fd6420 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic3.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic4.png b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic4.png new file mode 100644 index 0000000000..b90be37707 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic4.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic5.png b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic5.png new file mode 100644 index 0000000000..94145359f2 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic5.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic6.png b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic6.png new file mode 100644 index 0000000000..b881f35f86 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic6.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic7.png b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic7.png new file mode 100644 index 0000000000..f2296db0eb Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic7.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic8.png b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic8.png new file mode 100644 index 0000000000..6e57921e8c Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic8.png differ diff --git a/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic9.png b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic9.png new file mode 100644 index 0000000000..a649f263a7 Binary files /dev/null and b/astro/public/img/docs/operate/secure-and-monitor/elastic/elastic9.png differ diff --git a/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram1.astro b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram1.astro new file mode 100644 index 0000000000..2024725b8f --- /dev/null +++ b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram1.astro @@ -0,0 +1,27 @@ +--- +import Diagram from 'src/components/mermaid/FlowchartDiagram.astro'; + +const { alt } = Astro.props; + +//language=Mermaid +const code = ` +graph TB + subgraph I[Your server] + direction TB + subgraph G[Docker] + H[(PostgreSQL)] + end + subgraph C[Docker] + A(FusionAuth) + end + end + C --> G + style I fill:#999 +`; +--- + + \ No newline at end of file diff --git a/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram2.astro b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram2.astro new file mode 100644 index 0000000000..94c32099c3 --- /dev/null +++ b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram2.astro @@ -0,0 +1,33 @@ +--- +import Diagram from 'src/components/mermaid/FlowchartDiagram.astro'; + +const { alt } = Astro.props; + +//language=Mermaid +const code = ` +graph TD + subgraph E[Elastic Server] + J(Kibana) --> B[(Elasticsearch)] + J --> F(Fleet) + end + subgraph I[Your server] + subgraph G[Docker] + H[(PostgreSQL)] + end + subgraph C[Docker] + A(FusionAuth) + D(Elastic Agent) + end + end + A --> G + D --> E + style I fill:#999 + style E fill:#999 +`; +--- + + \ No newline at end of file diff --git a/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram3.astro b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram3.astro new file mode 100644 index 0000000000..26efff5600 --- /dev/null +++ b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram3.astro @@ -0,0 +1,29 @@ +--- +import Diagram from 'src/components/mermaid/FlowchartDiagram.astro'; + +const { alt } = Astro.props; + +//language=Mermaid +const code = ` +graph TD + subgraph E[Elastic Server] + J(Kibana) --> B[(Elasticsearch)] + J --> F(Fleet) + end + subgraph I[Your server] + H[(PostgreSQL)] + A(FusionAuth) + D(Elastic Agent) + end + A --> H + D --> E + style I fill:#999 + style E fill:#999 +`; +--- + + \ No newline at end of file diff --git a/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram4.astro b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram4.astro new file mode 100644 index 0000000000..b796358284 --- /dev/null +++ b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram4.astro @@ -0,0 +1,36 @@ +--- +import Diagram from 'src/components/mermaid/FlowchartDiagram.astro'; + +const { alt } = Astro.props; + +//language=Mermaid +const code = ` +graph TD + subgraph E[Elastic Server] + J(Kibana) --> B[(Elasticsearch)] + J --> F(Fleet) + end + subgraph I[Your server] + subgraph G[Docker] + H[(PostgreSQL)] + end + subgraph C[Docker] + A(FusionAuth) + end + subgraph K[Docker] + D(Elastic Agent) + end + end + K --> E + K --> C + C --> G + style I fill:#999 + style E fill:#999 +`; +--- + + \ No newline at end of file diff --git a/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram5.astro b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram5.astro new file mode 100644 index 0000000000..4bd3d60766 --- /dev/null +++ b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram5.astro @@ -0,0 +1,35 @@ +--- +import Diagram from 'src/components/mermaid/FlowchartDiagram.astro'; + +const { alt } = Astro.props; + +//language=Mermaid +const code = ` +graph TD + subgraph Z[Elastic Server] + X(Kibana) --> W[(Elasticsearch)] + X --> Y(Fleet) + end + subgraph I[Your server] + subgraph G[Docker] + H[(PostgreSQL)] + end + subgraph C[Docker] + A(FusionAuth) + end + subgraph E[Docker] + B(Custom metric getter code) + end + end + C --> G + B --> |API call| C + B --> |API call| W + style I fill:#999 +`; +--- + + \ No newline at end of file diff --git a/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram6.astro b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram6.astro new file mode 100644 index 0000000000..5a01d8fc73 --- /dev/null +++ b/astro/src/components/docs/operate/secure-and-monitor/elasticDiagram6.astro @@ -0,0 +1,39 @@ +--- +import Diagram from 'src/components/mermaid/FlowchartDiagram.astro'; + +const { alt } = Astro.props; + +//language=Mermaid +const code = ` +graph TD + subgraph Z[Elastic Server] + X(Kibana) --> W[(Elasticsearch)] + X --> Y(Fleet) + end + subgraph I[Your server] + subgraph G[Docker] + H[(PostgreSQL)] + end + subgraph C[Docker] + A(FusionAuth) + end + subgraph E[Docker] + B(Custom metric getter code) + end + subgraph M[Docker] + N(Elastic Agent) + end + end + C --> G + M --> Z + B --> |API call| C + B --> |API call| W + style I fill:#999 +`; +--- + + \ No newline at end of file diff --git a/astro/src/content/articles/identity-basics/magic-links.md b/astro/src/content/articles/identity-basics/magic-links.md index b02f41c620..be015eb7fa 100644 --- a/astro/src/content/articles/identity-basics/magic-links.md +++ b/astro/src/content/articles/identity-basics/magic-links.md @@ -24,17 +24,17 @@ The process starts when a user inputs their email address into a login form. The By doing so, magic links leverage the security of the user's email provider. If someone can access the magic link, they already have access to the user's email. If the user's email account is compromised, then they likely have bigger problems than someone accessing your service. The magic link is a one-time URL that can only be used once. This means that if someone steals a magic link that has already been used, they cannot use it again. This means that the user gets the ease of logging in to your system without having to present a credential. But they still benefit from the security around the email account, including any protections the email provider has put in place or MFA the user has added. -## Benefits Of Using Magic Links +## What Are The Benefits Of Using Magic Links -### User Experience (UX): +### How Do Magic Links Impact User Experience (UX)? It's no secret that users often struggle with password management. The average user is registered on dozens of online platforms, each requiring a unique password. Remembering these is often challenging, leading to frequent password resets, which further degrade user experience. Magic links simplify this process, requiring only access to an email account. -### Security: +### Are Magic Links Secure? Despite being the standard for years, passwords are a known security weak point. Users often reuse passwords across platforms or opt for easy-to-remember (and easy-to-guess) options. By using magic links, we eliminate the risk of password reuse or theft. In addition, the temporary nature of magic links also acts as a security advantage, as each link expires after use or after a set period, whichever happens first. This prevents attackers from using them for malicious purposes. -### Development Simplicity: +### How Hard Is It To Implement Magic Links? Implementing a secure password-based system can be a challenge. It involves creating secure password storage, implementing encryption, managing password resets, etc. In comparison, magic link systems can be simpler to implement and maintain. They don't require any changes to existing infrastructure, which makes them a good choice for small and medium businesses. In addition, they can be implemented with fewer resources than other security solutions such as software-based two-factor authentication (2FA) systems or hardware tokens. ## Are Magic Links Better Than Passwords? @@ -55,15 +55,15 @@ To sum up, while passwords have long been the foundation of the authentication p While magic links provide an attractive alternative to traditional passwords and forgot password links, it's crucial to consider potential drawbacks. -### Email Account Dependence: +### Are Magic Links Reliant On Email Accounts? Magic links rely on the security of the user's email account. If a user's email account is compromised, all services using magic links are potentially at risk. It's thus crucial to encourage users to protect their email accounts with strong security measures, like two-factor authentication. Also, some email providers will pre-fetch all links in all emails, which may expire magic links. Make sure you consider this in your implementation. -### Phishing Attacks: +### Do Magic Links Prevent Phishing Attacks? Users might be tricked into clicking on malicious links masquerading as magic links. Training users to identify genuine magic links and raising awareness about such threats is essential. -### Security: +### What Are Security Considerations of Magic Links? If the user's email account is compromised, all services using magic links are potentially at risk. This issue can be mitigated by encouraging users to protect their email accounts with strong security measures like two-factor authentication and keeping the lifetime of a magic link low. @@ -97,4 +97,4 @@ Finally, it's important to continuously monitor and update the magic link system Magic links provide a promising alternative to traditional password-based authentication, offering improved user experience and security. As developers, it's our role to adapt to these changing paradigms to offer the best possible security solutions to our users. As we move towards a passwordless future, magic links are certainly worth considering. They're easy to implement, they don't require any special permissions, and they provide a seamless user experience. -Before switching over, ensure your team understands the benefits, risks, and implementation process. Remember, the goal is not just to follow trends but to enhance the overall security and usability of your systems. Embrace the magic of these links, and let's stride towards a more secure digital future. \ No newline at end of file +Before switching over, ensure your team understands the benefits, risks, and implementation process. Remember, the goal is not just to follow trends but to enhance the overall security and usability of your systems. Embrace the magic of these links, and let's stride towards a more secure digital future. diff --git a/astro/src/content/articles/oauth/saml-vs-oauth.mdx b/astro/src/content/articles/oauth/saml-vs-oauth.mdx index b29389010f..7f3a510b0e 100644 --- a/astro/src/content/articles/oauth/saml-vs-oauth.mdx +++ b/astro/src/content/articles/oauth/saml-vs-oauth.mdx @@ -19,11 +19,11 @@ SAML, or Security Assertion Markup Language, also lets you log in to multiple si SAML is primarily an authentication system, while OAuth is an authorization system. [*Authentication*](/articles/authentication/common-authentication-implementation-risks) is about confirming the user’s identity. [*Authorization*](/docs/get-started/core-concepts/authentication-authorization#overview) is about deciding what services they can access. -## Workflows +## What Are Common SAML and OAuth Workflows? Let’s take a look at how the two systems let you access websites and applications. These are common systems, though [other workflows are possible](https://www.ibm.com/docs/en/tfim/6.2.2.6?topic=overview-oauth-20-workflow). -## Security Assertion Markup Language (SAML) Definition +## What Is Security Assertion Markup Language (SAML)? When a user interacts with SAML, both a service provider and [identity provider](/docs/apis/identity-providers/) are involved. The service provider is typically the website the user is interacting with. @@ -38,7 +38,7 @@ When the right credentials are provided, the identity provider responds with a S If the user is already authenticated, they’re not asked for their credentials, which saves time and improves the user experience. -## Open Authorization (OAuth) Definition +## What is Open Authorization (OAuth)? There are two versions of OAuth, and there are [differences](https://www.synopsys.com/blogs/software-security/oauth-2-0-vs-oauth-1-0/) between them. This article focuses on version 2.0, which has been around since 2012. An updated version 2.1 [has been proposed](/articles/oauth/differences-between-oauth-2-oauth-2-1) but not yet approved. @@ -72,7 +72,7 @@ This allows users to gain access through a familiar UI, and their primary creden This information is a core source of revenue for companies like Facebook. While some users may not be keen on the [potential lack of privacy](https://www.wired.com/story/security-risks-of-logging-in-with-facebook/), those users are [in the minority](https://www.webmarketingpros.com/gigya-survey-shows-social-login-use-skyrocketing-on-sites-and-apps/). However, these concerns are part of why some companies are choosing to run their own OAuth servers. -## Comparison of OAuth and SAML +## What Are the Differences Between SAML and OAuth? Let’s talk about what function each system performs. @@ -95,11 +95,11 @@ SAML, though an authentication-based protocol, can also be used to provide other Using OAuth for authorization together with SAML for authentication is perfectly feasible. The [Microsoft identity platform](https://docs.microsoft.com/en-us/azure/active-directory/develop/authentication-vs-authorization), for example, uses them both. -## Typical Use Cases +## What are Some Typical Use Cases for SAML and OAuth? Let’s look at some of the ways these systems are used. -### SAML +### Typical SAML Use Cases SAML allows users to conveniently access multiple resources [safely and securely](https://www.onelogin.com/learn/saml). It can reduce support requests since users don’t need to create and store credentials for every service they use. It tends to be popular with groups that need to regularly grant access to specific sets of resources, as it minimizes the work involved. @@ -120,7 +120,7 @@ Large cloud platforms often allow users to sign in via SAML. In addition to bein [Zendesk](/docs/lifecycle/authenticate-users/integrations/saml/zendesk) is a typical example. You can [add attributes](https://support.zendesk.com/hc/en-us/articles/4408887505690-Enabling-SAML-single-sign-on) to SAML-enabled users, allowing you to store things like contact details, team membership, access levels, or whatever other data you require. -### OAuth +### Typical OAuth Use Cases OAuth allows developers to authenticate users without demanding their credentials. This lets them learn more about their users, but doesn’t require that users create a new login or provide details they’ve entered elsewhere. Perhaps more importantly, it also means developers can provide key functionality without having to build it themselves. @@ -154,7 +154,7 @@ Single-page applications (SPAs) contain all their logic on the frontend. That ma You can sidestep this problem by using OAuth with a backend for frontend (BFF) component. The component can manage OAuth tokens for your SPA [using encrypted, same-site cookies](https://curity.io/resources/learn/spa-best-practices/). -## Conclusion - When Should You Use SAML or OAuth? +## When Should You Use SAML or OAuth? SAML and OAuth are different solutions to similar problems. They’re different animals, but their territories overlap at times, and you can frequently find them together. diff --git a/astro/src/content/blog/announcing-fusionauth-1-52.mdx b/astro/src/content/blog/announcing-fusionauth-1-52.mdx new file mode 100644 index 0000000000..578401dfa1 --- /dev/null +++ b/astro/src/content/blog/announcing-fusionauth-1-52.mdx @@ -0,0 +1,26 @@ +--- +publish_date: 2024-08-06 +title: Announcing FusionAuth 1.52.0 - Passkeys for Everyone! +description: This update brings passkeys to the free Community Edition of FusionAuth, enhancing security for everyone. +authors: Brad McCarty +image: /img/blogs/announcing-152/fusionauth-1-52.png +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. + +So, with that in mind, we have dubbed [FusionAuth v 1.52.0](/download) "The Passkey Platypus." After all, we too are highly opinionated, and it’s our opinion that including passkeys as a feature of our free Community Edition is a good idea. For those of you who want to read all of the fine print, you’ll get that in our [release notes](/docs/release-notes/). + +![Passkeys are for everyone](/img/blogs/announcing-152/fusionauth-platypus.jpg) + +If you’re already using the Community Edition, you’ll need to upgrade to 1.52.0 to get passkeys. Regardless of whether you’re a new or existing user, you’ll need to register for a free license of FusionAuth. Our Admin UI will walk you through the process. Your free license is good forever, and will remain active as we add even more features to the Community Edition over time. + +Okay, chances are good that someone reading this is asking "why should I care about passkeys?" The answer? [24 billion compromised passwords](/blog/why-passkeys-matter) in a single year. The era of passwords is [coming to an end](/password-history). Passkeys offer a more secure, passwordless authentication method that reduces the risk of breaches while improving the experience for your customers. + +We're committed to helping you provide safer, more secure (and dare we say pleasant?) login experiences. By making passkeys available to every FusionAuth user, we're taking another step toward eliminating the risks of traditional passwords. + +So, what are you waiting for? [Download](/download) FusionAuth or upgrade to version 1.52.0 to provide your users with a superior login experience. Activating passkeys is simple—just toggle the switch in the FusionAuth UI. For detailed instructions, check out our [documentation on Authentication with WebAuthn and Passkeys](/docs/lifecycle/authenticate-users/passwordless/webauthn-passkeys). diff --git a/astro/src/content/blog/inteligov-fusionauth-sso.mdx b/astro/src/content/blog/inteligov-fusionauth-sso.mdx new file mode 100644 index 0000000000..b57c299fc2 --- /dev/null +++ b/astro/src/content/blog/inteligov-fusionauth-sso.mdx @@ -0,0 +1,97 @@ +--- +publish_date: 2024-08-07 +title: Inteligov Uses FusionAuth For Custom SSO, Opening Up A New Revenue Stream +description: Inteligov uses FusionAuth for all things authentication, including custom single sign-on solutions for customers. These opened up a new revenue stream for his company. +authors: Dan Moore +image: /img/blogs/fusionauth-inteligov/fusionauth-inteligov.png +categories: Community +tags: community story, i18n, sso, azure ad, google, saas, rails, self-hosted +excerpt_separator: "{/* more */}" +--- + +Raphael Caldas is a FusionAuth community member and CEO of Inteligov. He chatted with us over email about how he and his team are using FusionAuth to meet their auth needs. + +{/* more */} + +*This interview has been lightly edited for clarity and length.* + +------- + +**Dan:** Can you tell me a bit about Inteligov? What is the company's mission? + +**Raphael:** Inteligov is a SaaS solution that helps private organizations, NGO and government branches monitor political and regulatory risks in Brazil. With our tools, our clients can monitor new bills and regulations, as well as legislative activities focused on their topics and agenda. Our mission is to facilitate the dialogue between the public and private sectors, driving social and economic improvement through a more qualified public policy landscape. + +**Dan:** Very cool! What is an example of a legislative activity you tracked and/or an impact that knowing about it had on an organization? + +**Raphael:** When COVID hit, [Sympla](https://www.sympla.com.br/), a huge Brazilian ticketing firm, had their activities severely impacted with tremendous revenue loss. They started spending around 15h per week monitoring 10 cities to understand when they could reopen events in these major centers. When we onboarded them, they started monitoring over 2,000 cities while spending only 50 minutes per week on this activity, which allowed them to reopen events more quickly and preserve their bottom line. + +> [FusionAuth] allowed us not only to provide custom SSO solutions to enterprise customers using Google Workspace and Microsoft Active Directory, but it also allowed us to charge for these integrations, opening up an unexpected revenue stream. + +**Dan:** Tell me about your role at Inteligov. + +**Raphael:** I founded the company in 2014 and have been serving as the CEO ever since. + +**Dan:** What led you to found the company? Was there an experience where you ran into an issue that made you want to build a company? + +**Raphael:** I'm a lawyer and learnt programming as a child. I was a consultant in government relations and used some scripts to help me gather information. When [Operation Car Wash](https://en.wikipedia.org/wiki/Operation_Car_Wash) hit, I soon understood that organizations would have to rethink the way they established relationships with the government and that my more "data driven" and "auditable" approach could be beneficial. + +That's when I decided to transform that mass of scripts into a SaaS product. + +**Dan:** How do you use FusionAuth? OAuth? User management? Social sign-on? Something else? + +**Raphael:** We use Fusionauth for authentication in all its varieties. + +> Cost, functionality and the presence of an active community were the main drivers [of choosing FusionAuth]. + +**Dan:** Are you using it for mobile apps? Web apps? Internal applications? + +**Raphael:** We use it for client facing applications on the web and also on mobile apps (but basically using a web view). + +**Dan:** What problems did we solve for you? + +**Raphael:** It simplifies handling multiple applications with users having a single login. It also provides social sign-on as well as the ability to easily implement custom enterprise authentication solutions. + +**Dan:** How were you solving them before FusionAuth? + +**Raphael:** For authentication with email/password we were using a traditional library for our framework. + +**Dan:** Which framework are you building on? + +**Raphael:** Our main monoliths are all built on Ruby on Rails, and we use React Native for our mobile apps. + +> I can't precisely estimate how much time and money [FusionAuth] saved us, but it was a lot. We managed to provide authorization with magic links, Google, Microsoft and Slack out of the box. + +**Dan:** Why did you choose FusionAuth over the alternatives? + +**Raphael:** Cost, functionality and the presence of an active community were the main drivers. Even before we adopted Fusionauth, we submitted the [localization for Brazilian Portuguese](https://github.com/FusionAuth/fusionauth-localization/blob/main/theme/messages_pt_BR.properties) and the PR was readily reviewed and accepted which was really nice - since we had previous experience with projects that are simply stalled regarding user contribution. + +**Dan:** Thank you so much for your contribution! + +**Raphael:** Don't mention it! Such a small thing compared to everything you guys bring to the table... And I loved the model and already suggested it to 2 or 3 software companies who struggle with i18n. + +**Dan:** How much time and money would you say FusionAuth has saved you? + +**Raphael:** I can't precisely estimate how much time and money it saved us, but it was a lot. We managed to provide authorization with magic links, Google, Microsoft and Slack out of the box. + +Furthermore it allowed us not only to provide custom SSO solutions to enterprise customers using Google Workspace and Microsoft Active Directory, but it also allowed us to charge for these integrations, opening up an unexpected revenue stream. + +> [I've] already suggested [FusionAuth] to 2 or 3 software companies who struggle with i18n. + +**Dan:** How do you run FusionAuth (Kubernetes, standalone server, behind a proxy, etc)? + +**Raphael:** We self-host FusionAuth. + +**Dan:** Any general feedback/areas to improve? + +**Raphael:** The experience has been really great so far. There are only 2 points brought up: + +* Make it easier to use secure headers out of the box. Would be great for FusionAuth to be able to set headers (CSP, X-Frame-Options, etc). +* In a penetration test report the exposure of the `client_id` parameter in the URL was pointed out as a vulnerability: information Leakage via URL query strings. Any way to handle that would be great. + +**Dan:** Thanks for your feedback! _[Ed note. Track the [first request in this GitHub issue](https://github.com/FusionAuth/fusionauth-issues/issues/1510)]_ + +------- + +We love sharing community stories. You can check out [Inteligov's website](https://www.inteligov.com.br/) if you'd like to learn more about them. + + diff --git a/astro/src/content/docs/_shared/_admin-user-form.mdx b/astro/src/content/docs/_shared/_admin-user-form.mdx index 220d99a30d..e3a726dd8d 100644 --- a/astro/src/content/docs/_shared/_admin-user-form.mdx +++ b/astro/src/content/docs/_shared/_admin-user-form.mdx @@ -16,6 +16,12 @@ user.data.favoriteColor=Favorite Color This field is not localizable, so you'll only need to modify the default messages file. [Learn more about modifying the messages file in your theme](/docs/customize/look-and-feel/localization#messages). +You can also add a tooltip by adding a related key to the messages file: + +``` +{tooltip}user.data.favoriteColor=A user's favorite color. This is used to generate a custom logo with the correct color scheme. +``` + Configure the FusionAuth admin UI to use these forms by navigating to Tenants -> Your Tenant -> General and then to the Form settings section. Set the Admin user form field to your new form. Learn more in the [Tenant documentation](/docs/get-started/core-concepts/tenants#general). diff --git a/astro/src/content/docs/_shared/_admin-user-registration-form.mdx b/astro/src/content/docs/_shared/_admin-user-registration-form.mdx index e4ee1e175f..e47cf37438 100644 --- a/astro/src/content/docs/_shared/_admin-user-registration-form.mdx +++ b/astro/src/content/docs/_shared/_admin-user-registration-form.mdx @@ -14,6 +14,13 @@ You should modify your theme to add labels for these custom fields for proper di registration.data.backgroundColor=Desired Background Color ``` +You can also add a tooltip by adding a related key to the messages file: + +``` +{tooltip}registration.data.backgroundColor=The desired background color. This will be used in the application and should be a hex code. +``` + + This field is not localizable, so you'll only need to modify the default messages file. [Learn more about modifying the messages file in your theme](/docs/customize/look-and-feel/localization#messages). Then, configure the FusionAuth admin UI to use these forms by navigating to Applications -> Your Application -> Registration and then to the Form settings section. Set the Admin Registration field to your new form. diff --git a/astro/src/content/docs/_shared/_framework-integration-tutorial-list.mdx b/astro/src/content/docs/_shared/_framework-integration-tutorial-list.mdx index eea46437f0..5e806732eb 100644 --- a/astro/src/content/docs/_shared/_framework-integration-tutorial-list.mdx +++ b/astro/src/content/docs/_shared/_framework-integration-tutorial-list.mdx @@ -1,5 +1,5 @@ -* [Java Spring Quickstart](/docs/quickstarts/quickstart-springboot-web) -* [Express Quickstart](/docs/quickstarts/quickstart-javascript-express-web +* [Java Spring Quickstart](/docs/quickstarts/quickstart-java-springboot-web) +* [Express Quickstart](/docs/quickstarts/quickstart-javascript-express-web) * [Python Django Quickstart](/docs/quickstarts/quickstart-python-django-web) * [Python Flask Quickstart](/docs/quickstarts/quickstart-python-flask-web) * [React Quickstart](/docs/quickstarts/quickstart-javascript-react-web) diff --git a/astro/src/content/docs/_shared/_licensed-edition-blurb-api.mdx b/astro/src/content/docs/_shared/_licensed-edition-blurb-api.mdx new file mode 100644 index 0000000000..fd76d5349a --- /dev/null +++ b/astro/src/content/docs/_shared/_licensed-edition-blurb-api.mdx @@ -0,0 +1 @@ +**Note:** A license is required to utilize {props.feature} diff --git a/astro/src/content/docs/_shared/_licensed-edition-blurb.mdx b/astro/src/content/docs/_shared/_licensed-edition-blurb.mdx new file mode 100644 index 0000000000..b9f59fd4a8 --- /dev/null +++ b/astro/src/content/docs/_shared/_licensed-edition-blurb.mdx @@ -0,0 +1,6 @@ +import Breadcrumb from 'src/components/Breadcrumb.astro'; +import EditionBlurb from './_edition-blurb.astro'; + + + This feature is available to licensed FusionAuth instances as of version {props.version}. A free license is available in the Plan tab for any user who registers in the account portal. + diff --git a/astro/src/content/docs/apis/_application-request-body.mdx b/astro/src/content/docs/apis/_application-request-body.mdx index d9cb474394..4556e9fff7 100644 --- a/astro/src/content/docs/apis/_application-request-body.mdx +++ b/astro/src/content/docs/apis/_application-request-body.mdx @@ -5,6 +5,7 @@ import DeprecatedSince from 'src/components/api/DeprecatedSince.astro'; import InlineField from 'src/components/InlineField.astro'; import JSON from 'src/components/JSON.astro'; import EnterpriseEditionBlurbApi from 'src/content/docs/_shared/_enterprise-edition-blurb-api.astro'; +import LicensedEditionBlurbApi from 'src/content/docs/_shared/_licensed-edition-blurb-api.mdx'; import TenantApplicationEmailConfiguration from 'src/content/docs/apis/_tenant-application-email-configuration.mdx'; import PremiumEditionBlurbApi from 'src/content/docs/_shared/_premium-edition-blurb-api.astro'; import JwtAlgorithm from 'src/content/docs/apis/_jwt_algorithm.mdx'; @@ -667,15 +668,15 @@ import Xmlsignaturec14nmethodValues from 'src/content/docs/_shared/_xmlSignature Whether the WebAuthn bootstrap workflow is enabled for this application. This overrides the tenant configuration. Has no effect if application.webAuthnConfiguration.enabled is `false`. - + Indicates if this application enables WebAuthn workflows based on the configuration defined here or the Tenant WebAuthn configuration. If this is `false`, WebAuthn workflows will be enabled based on the Tenant configuration. If `true`, WebAuthn workflows will be enabled according to the configuration of this application. - + Whether the WebAuthn reauthentication workflow is enabled for this application. This overrides the tenant configuration. Has no effect if application.webAuthnConfiguration.enabled is `false`. - + 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. diff --git a/astro/src/content/docs/apis/_tenant-request-body.mdx b/astro/src/content/docs/apis/_tenant-request-body.mdx index a207726977..368aa8714a 100644 --- a/astro/src/content/docs/apis/_tenant-request-body.mdx +++ b/astro/src/content/docs/apis/_tenant-request-body.mdx @@ -7,6 +7,7 @@ import EventTypes from 'src/content/docs/apis/_event-types.mdx'; import ExpiryUnit from 'src/content/docs/apis/_expiry_unit.mdx'; import InlineField from 'src/components/InlineField.astro'; import JSON from 'src/components/JSON.astro'; +import LicensedEditionBlurbApi from 'src/content/docs/_shared/_licensed-edition-blurb-api.mdx'; import PremiumEditionBlurbApi from 'src/content/docs/_shared/_premium-edition-blurb-api.astro'; import RecaptchaValues from 'src/content/docs/_shared/_recaptcha-values.mdx'; import TenantApplicationEmailConfiguration from 'src/content/docs/apis/_tenant-application-email-configuration.mdx'; @@ -304,14 +305,14 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; The time in seconds until a WebAuthn authentication challenge is no longer valid and the User will be required to restart the WebAuthn authentication ceremony by creating a new challenge. This value also controls the timeout for the client-side WebAuthn `navigator.credentials.get` API call. Value must be greater than 0. - + The time in seconds until a WebAuthn registration challenge is no longer valid and the User will be required to restart the WebAuthn registration ceremony by creating a new challenge. This value also controls the timeout for the client-side WebAuthn `navigator.credentials.create` API call. Value must be greater than 0. - + @@ -913,7 +914,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; The recommended value for the bootstrap workflow is `any`. - + @@ -923,7 +924,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; Whether or not this tenant has the WebAuthn bootstrap workflow enabled. The bootstrap workflow is used when the user must "bootstrap" the authentication process by identifying themselves prior to the WebAuthn ceremony and can be used to authenticate from a new device using WebAuthn. - + @@ -936,21 +937,21 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; It is _highly_ recommended to use the `required` option for the bootstrap workflow. - + Determines if debug should be enabled for this tenant to create an event log to assist in debugging WebAuthn errors. - + Whether or not this tenant has WebAuthn enabled globally. - + @@ -963,7 +964,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; The recommended value for the reauthentication workflow is `platform`. - + @@ -973,7 +974,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; Whether or not this tenant has the WebAuthn reauthentication workflow enabled. The reauthentication workflow will automatically prompt a user to authenticate using WebAuthn for repeated logins from the same device. - + @@ -986,7 +987,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; It is _highly_ recommended to use the `required` option for the reauthentication workflow. - + @@ -995,7 +996,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; When this parameter is omitted, FusionAuth will use `null` for the Relying Party Id in passkey creation and request options. A `null` value in the [WebAuthn JavaScript API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API) will use the browser origin. - + @@ -1004,7 +1005,7 @@ import TransactionTypes from 'src/content/docs/apis/_transaction-types.mdx'; When this parameter is omitted, FusionAuth will use the tenant.issuer value. - + diff --git a/astro/src/content/docs/apis/groups.mdx b/astro/src/content/docs/apis/groups.mdx index ae9867cf71..f02284abd3 100644 --- a/astro/src/content/docs/apis/groups.mdx +++ b/astro/src/content/docs/apis/groups.mdx @@ -332,7 +332,7 @@ When calling the API using a `GET` request you will send the search criteria on 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: @@ -343,6 +343,8 @@ When calling the API using a `GET` request you will send the search criteria on * `userId` - the unique Id of the User For example, to order the results by the insert instant in descending order, the value would be provided as `insertInstant DESC`. The final string is optional, can be set to `ASC` or `DESC`, or omitted and will default to `ASC`. + + Prior to version `1.52.0` this defaults to `insertInstant ASC`. The offset row to return results from. If the search has 200 records in it and this is 50, it starts with row 50. @@ -367,7 +369,7 @@ When calling the API using a `POST` request you will send the search criteria in 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: @@ -378,6 +380,8 @@ When calling the API using a `POST` request you will send the search criteria in * `userId` - the unique Id of the User For example, to order the results by the insert instant in descending order, the value would be provided as `insertInstant DESC`. The final string is optional, can be set to `ASC` or `DESC`, or omitted and will default to `ASC`. + + Prior to version `1.52.0` this defaults to `insertInstant ASC`. The offset row to return results from. If the search has 200 records in it and this is 50, it starts with row 50. diff --git a/astro/src/content/docs/apis/users.mdx b/astro/src/content/docs/apis/users.mdx index 33dbd564b1..99970d77f0 100644 --- a/astro/src/content/docs/apis/users.mdx +++ b/astro/src/content/docs/apis/users.mdx @@ -338,7 +338,7 @@ The response for this API contains the information for the User that was reactiv ## Import Users -This API is used to bulk import multiple Users into FusionAuth. Each User must have at least an **email** or a **username**. This request is useful for migrating data from an existing database into FusionAuth. Additionally, you can provide an Id for each User inside the JSON User object of the request body. When using this API you should import with batches of less than 10,000 users per request. After completing an import you should [reindex of the Elasticsearch database](/docs/lifecycle/manage-users/search/search#reindexing-elasticsearch) as well. +This API is used to bulk import multiple Users into FusionAuth. Each User must have at least an **email** or a **username**. This request is useful for migrating data from an existing database into FusionAuth. Additionally, you can provide an Id for each User inside the JSON User object of the request body. When using this API you should import with batches of less than 10,000 users per request. After completing an import you should [reindex of the Elasticsearch database](/docs/lifecycle/manage-users/search/search#reindexing-elasticsearch) as well. ### Request diff --git a/astro/src/content/docs/apis/webauthn.mdx b/astro/src/content/docs/apis/webauthn.mdx index e7810e1b01..3d148aca33 100644 --- a/astro/src/content/docs/apis/webauthn.mdx +++ b/astro/src/content/docs/apis/webauthn.mdx @@ -3,7 +3,7 @@ title: WebAuthn description: Learn about the APIs for starting and completing WebAuthn ceremonies and retrieving, importing and deleting WebAuthn passkeys. section: apis --- -import AdvancedEditionBlurb from 'src/content/docs/_shared/_advanced-edition-blurb.astro'; +import LicensedEditionBlurb from 'src/content/docs/_shared/_licensed-edition-blurb.mdx'; import APIBlock from 'src/components/api/APIBlock.astro'; import APIField from 'src/components/api/APIField.astro'; import API from 'src/components/api/API.astro'; @@ -28,7 +28,7 @@ import WebauthnsResponseBody from 'src/content/docs/apis/_webauthns-response-bod import XFusionauthTenantIdHeaderScopedOperation from 'src/content/docs/apis/_x-fusionauth-tenant-id-header-scoped-operation.mdx'; import XFusionauthTenantIdRequired from 'src/content/docs/apis/_x-fusionauth-tenant-id-required.mdx'; - + ## Overview diff --git a/astro/src/content/docs/customize/email-and-messages/configure-email.mdx b/astro/src/content/docs/customize/email-and-messages/configure-email.mdx index 50f4e8f539..2f9d339657 100644 --- a/astro/src/content/docs/customize/email-and-messages/configure-email.mdx +++ b/astro/src/content/docs/customize/email-and-messages/configure-email.mdx @@ -1,5 +1,5 @@ --- -title: Configure the SMTP Server +title: Configure The SMTP Server description: Learn how to enable and configure the SMTP server. section: customize subcategory: email and messages @@ -11,87 +11,458 @@ import InlineField from 'src/components/InlineField.astro'; ## Overview -Before email templates and other email features may be utilized, you must first enable and configure an SMTP server. +Before you can use email templates and other email features in FusionAuth, you must first enable and configure a Simple Mail Transfer Protocol (SMTP) server. -To enable and configure the SMTP server navigate to Tenants -> Email. +This guide briefly explains SMTP security and SMTP providers, describes in detail how to configure the most popular SMTP providers with FusionAuth, and lists best practices to consider when working with email. -Email Settings +SMTP providers handle two types of email: marketing (like newsletters and sale advertisements) and transactional (like account notifications and password resets). FusionAuth is concerned only with transactional email. -Enable email by clicking on the *Enabled* toggle, and save your settings once you have completed your configuration. +## Understand Email Security + +Email service providers (ESPs) such as Gmail, Yahoo Mail, and Proton Mail rely on several methods to prevent spam and phishing emails from being sent to their users. As of 2024, these methods have become even stricter. Google [requires SMTP providers to allow users to send only from their own registered domains](https://help.brevo.com/hc/en-us/articles/14925263522578-Prepare-for-Gmail-and-Yahoo-s-new-requirements-for-email-senders) to reduce spam. + +Here are the ways ESPs implement email security: +- **Rate limits:** Emails that are received too frequently or show sudden spikes in volume are blocked. +- **IP address block lists:** Emails received from dynamic IP addresses, those known to send spam, or those with a low reputation are added to lists that receivers use to reject mail. +- **DNS records of email senders:** Emails must have valid records for Sender Policy Framework (SPF) (RFC 7208), Domain Keys Identified Mail (DKIM) (RFC 6376), and Domain-based Message Authentication, Reporting, and Conformance (DMARC) (RFC 7489). + +SPF, DKIM, and DMARC are TXT records you need to add to the DNS records for your domain. Your SMTP provider will tell you what records to add. + +- An SPF record looks like `v=spf1 ip4:129.6.100.200 ip6:2610:20:6005:100::20 -all` and lists the IP addresses permitted to send email on behalf of the domain. ESPs should reject emails arriving from an IP address other than these. +- A DKIM record looks like `k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQ8c7wIDAQAB` and specifies a public key. The SMTP provider will sign the sender address of an email with the corresponding private key. ESPs should reject emails with an invalid sender address signature. +- A DMARC record looks like `v=DMARC1; p=none; rua=mailto:rua@dmarc.brevo.com` and specifies the policies supported by the email sender and where to send rejected email for analysis by the sender. + +Together, these three records allow an ESP to know that the email server and sender are valid and what responses the sender supports if an invalid email is received. + +You might also encounter the term Author Domain Signing Practices (ADSP), an optional extension to DKIM that enables a domain to publish the signing practices it adopts when relaying mail on behalf of associated authors. + +## Which Provider To Choose? + +An SMTP provider is an online service that sends email on your behalf. In return for payment, an SMTP provider guarantees you a service that provides IP addresses with a high reputation. + +Some providers are easy to test, requiring nothing more than registering with an email address. Others require comprehensive company details, your verified phone number, domain verification, having a professional business website, and communicating with support agents. The easiest providers to configure are: +- MailerSend — Requires only an email address. +- Gmail — Requires phone verification, and email is intended only for small tests. Not for production use. +- AWS SES — Requires email and domain verification. +- Postmark — Requires email and domain verification. +- Resend — Requires email and domain verification. + +Postmark had especially clear documentation and an easy setup experience. + +The more difficult providers are: +- Brevo +- Mailgun (Sinch) +- SendGrid (Twilio) + +These providers automatically disable your account on signup and require you to contact their support to have it activated. This involves having a business website ready for review, explaining what your purpose in sending email is, and explaining how you obtained your recipients' email addresses. However, Mailgun and Brevo support were friendly and quick, and unlocked the FusionAuth test account after reasonable discussion. SendGrid is the most onerous provider, with full company details needed for every sender address. + +The worst provider is Mailchimp (Mandrill). Mailchimp was the only SMTP provider that refused to provide FusionAuth an account, giving no explanation and accusing us of sharing prohibited content. Mailchimp support was poor — entirely automated, and no human could be contacted. + +Be aware that providers can cancel your account at any time, without explanation or a chance to appeal. This can cripple your business. + +Choose an SMTP provider that you feel is trustworthy. At the time of writing, these were the scores on https://www.trustpilot.com for each provider in this guide: + +| Provider | Score | Link | +|----------------------|-----------|-----------------------------------------------------| +| Mailgun (Sinch) | 4.4 | https://www.trustpilot.com/review/mailgun.com | +| Brevo | 4.2 | https://www.trustpilot.com/review/www.brevo.com | +| Postmark | 3.5 | https://www.trustpilot.com/review/postmarkapp.com | +| Resend | 3.2 | https://www.trustpilot.com/review/resend.com | +| MailerSend | 2.8 | https://www.trustpilot.com/review/mailersend.com | +| Mailchimp (Mandrill) | 1.3 | https://www.trustpilot.com/review/www.mailchimp.com | +| SendGrid (Twilio) | 1.2 | https://www.trustpilot.com/review/sendgrid.com | +| AWS SES | No review | | + +These scores, especially the low ones for Mailchimp and SendGrid, are consistent with the experiences we had writing this guide. + +When comparing pricing, note that some providers charge a flat monthly fee, and some charge only for the number of emails you send. One provider might be cheaper than another for small volumes of email, but more expensive for large volumes. + +## Can You Use A Self-Hosted SMTP Server? + +It is possible to send email through an SMTP server hosted on your server using an application like [Postfix](https://www.postfix.org/documentation.html), [Haraka](https://haraka.github.io/getting_started), [mailcow](https://docs.mailcow.email/), or [Mail-in-a-Box](https://mailinabox.email/guide.html). Hosting your own server will cost you nothing more than a few dollars a month for a cloud server, or nothing if you already have a server for other applications. + +However, over time, hosting your own SMTP server will almost certainly cost you more time and money than paying a dedicated email company to handle mail for you. Below are some things you'll need to handle if you want to self-host: +- Deliverability: Email service providers block or filter emails from dynamic IP addresses and untrusted servers. You need to maintain IP reputation, implement SPF, DKIM, and DMARC properly, and handle feedback loops with ESPs (bounces and spam requests). +- Scalability: As email volume grows, you need to scale your infrastructure. +- Technical expertise: Properly configuring and maintaining an email server requires understanding both the software and the network infrastructure. You need to continuously monitor your server and ensure it is available with 100% uptime. +- Security: Your server must be secured against unauthorized access and data must be protected against breaches, requiring regular security audits and updates. +Using your own SMTP server is appropriate if you are using FusionAuth for a hobby project or a small team where all users know to check their spam folders. -### SMTP Settings +## SMTP Settings + +Below are descriptions of the SMTP settings you will configure in FusionAuth in the following section. The hostname of the SMTP server. This will be provided by your SMTP provider. - The port of the SMTP server. This will be provided by your SMTP provider. Ports `25`, `465` and `587` are the well known ports used by SMTP, it is possible your provider will utilize a different port. + The port of the SMTP server. This will be provided by your SMTP provider. Ports `25`, `465`, and `587` are well-known ports used by SMTP, but your provider may use a different port. - In most cases you will be using TLS to connect to your SMTP server, and the port will generally be `587` or `465`. + In most cases, you will use TLS to connect to your SMTP server and the port will be `587` or `465`. - The username used to authenticate to the SMTP server. This will be provided by your SMTP provider. + The username used to authenticate with the SMTP server. This will be provided by your SMTP provider. - When enabled, you may modify the SMTP password, when the Password field is not displayed the current password will not be modified. + When enabled, you may modify the password used to authenticate with the SMTP server. When the Password field is not displayed, the current password cannot be modified. - The new password to use for the outgoing SMTP mail server authentication. This field is only required when Change password is checked. + The new password to use for outgoing SMTP mail server authentication. This field is only required when Change password is checked. The security type when using an SSL connection to the SMTP server. This value should be provided by your SMTP provider. - Generally speaking, if using port `25` you will select `None`, if using port of `465` you will select `SSL` and if using port `587` you will select `TLS`. It is possible your provider will be different, follow your providers instruction. + Generally, you will select `None` if using port `25`, `SSL` if using port `465`, and `TLS` if using port `587`. Your provider may be different; follow your provider's instructions. * `None` * `SSL` * `TLS` - The default From Address used in sending emails when a from address is not provided for an individual email template. This is an email address (i.e. **jared@piedpiper.com**). + The default `From Address` used when sending emails if a from address is not provided for an individual email template. This is an email address (for example, **jared@piedpiper.com**). - The default From Name used in sending emails when a from name is not provided on an individual email template. This is the display name part of the email address (i.e. **Jared Dunn** <jared@piedpiper.com>). + The default `From Name` used when sending emails if a from name is not provided on an individual email template. This is the display name part of the email address (for example, **Jared Dunn** <jared@piedpiper.com>). - One or more line separated SMTP headers to be added to each outgoing email. The header name and value should be separated by an equals sign. (i.e. `X-SES-CONFIGURATION-SET=Value`). + One or more line-separated SMTP headers to be added to each outgoing email. The header name and value should be separated by an equals sign, for example, `X-SES-CONFIGURATION-SET=Value`. When enabled, SMTP and JavaMail debug information will be output to the Event Log. -## SMTP Providers +## How To Configure SMTP Providers In FusionAuth + +To enable and configure the FusionAuth SMTP server, navigate to Tenants -> Edit -> Email. + +Email Settings + +Enable email by clicking on the *Enabled* toggle, and save your settings once you have completed your configuration. + +To avoid disrupting your application's current DNS records, you may want to point FusionAuth SMTP fields to a temporary subdomain. For example, if your application is hosted at `myapp.com`, you can create `testemail.myapp.com`, and point the SMTP service and FusionAuth there while testing. + +Strict SMTP providers require you to have a trustworthy-looking domain and website before they activate your account. + +There is a troubleshooting section below this one if you encounter errors while trying to send a test email. + + + + -### SendGrid +The SMTP providers are presented in alphabetical order below. -SendGrid is a commonly used SMTP provider and integrates well with FusionAuth. To setup SendGrid, [follow these instructions](https://docs.sendgrid.com/for-developers/sending-email/integrating-with-the-smtp-api). +### AWS SES +- Create an account at https://aws.amazon.com. +- In your account dashboard, search for SES and start the account setup wizard by clicking Get set up on the left sidebar. + - Add your email and domain. + - Verify your email when AWS emails you a link. + - Add the DNS records AWS SES gives you to your domain's DNS settings. + - After a few minutes, the SES Verify sending domain status should change from `Verification pending` to `Verified`. +- Browse to SMTP settings in the AWS sidebar. +- Click Create SMTP credentials and note the created SMTP credentials. +- In your tenant's email tab in the FusionAuth web interface, set the following values: + - Host: `email-smtp.eu-west-1.amazonaws.com` (use your host from the SMTP settings page) + - Port: `587` + - Username: Your username from the SMTP credentials page + - Password: Your SMTP password from the credentials page + - Security: `TLS` + - Default from address: `me@myapp.com` (use your verified domain) +- Click Send test email to test that the settings work. You must send to an email address verified with SES. Use the address you gave when creating your SES account. +- Click the save icon at the top right. -Other resources related to SendGrid are linked below: +SES is more complicated than the other SMTP services. If the troubleshooting section at the bottom of this article does not help you, please consult the [SES documentation](https://docs.aws.amazon.com/ses/latest/dg/troubleshoot-verification.html). -1. https://docs.sendgrid.com/for-developers/sending-email/getting-started-with-transactional-emails -2. https://docs.sendgrid.com/for-developers/sending-email/sender-identity -3. https://docs.sendgrid.com/ui/account-and-settings/how-to-set-up-domain-authentication +### Brevo (Previously Sendinblue) -Using dedicated IP addresses for any SendGrid account will build email reputation over time (improving email deliverability). And lastly, to control spoofing, phishing, and spam, it is recommended to set up [SPF](https://docs.sendgrid.com/ui/account-and-settings/spf-records) and [DKIM](https://docs.sendgrid.com/ui/account-and-settings/dkim-records) records for the primary email domain (such as `example-company.com`). Emails should also be sent from an address such as `no-reply@example-company.com`. +- Create an account at https://app.brevo.com. +- If Brevo suspends your account for violating the terms of service, contact support on [this page](https://www.brevo.com/contact) to activate it. +- Browse to https://app.brevo.com/senders/domain/list. + - Add your domain name. + - In your website domain manager, add the DNS records from the domain authentication page. + - Once you have entered the DNS records and saved, start the verification process on the Brevo page. It should take a minute. +- Browse to https://app.brevo.com/senders/list. + - Add sender: `me@myapp.com` (use your domain name). + - In Brevo, authenticate your email address. +- Browse to https://app.brevo.com/settings/keys/smtp and note your SMTP settings. +- In your tenant's email tab in the FusionAuth web interface, set the following values: + - Host: `smtp-relay.brevo.com` + - Port: `587` + - Username: Your Brevo SMTP login from the settings page + - Password: Your SMTP key value from the settings page + - Security: `TLS` + - Default from address: Any address is allowed +- Click Send test email to test that the settings work, then click the save icon at the top right. ### Gmail -Gmail is a commonly used SMTP service. Gmail is not recommended for production use, since it has a [number of limits](https://support.google.com/a/answer/166852). However, it can be useful to test email functionality. +As well as being a popular ESP, Gmail can be used by programs to send email through SMTP. Gmail is not recommended for production use, since it has a [number of limits](https://support.google.com/a/answer/166852). However, it can be useful to test email functionality. + +For Gmail, use [application passwords](https://support.google.com/accounts/answer/185833) or you may get a generic `Unable to send email via JavaMail / Prime Messaging Exception` error. The application passwords support article says you need to enable two-factor authentication, then create an app password on the security tab. However, there is no `App password` setting on the tab. You need to browse to https://myaccount.google.com/apppasswords manually to create one. + +- In your tenant's email tab in the FusionAuth web interface, set the following values: + - Host: `smtp.gmail.com` + - Port: `587` + - Username: Your full Gmail address (including @gmail.com) + - Password: Your app password (including spaces) + - Security: `TLS` + - Default from address: Your full Gmail address +- Click Send test email to test that the settings work, then click the save icon at the top right. + +### Mailchimp (Previously Mandrill) + +Mailchimp is currently integrating its transactional email marketing plugin, Mandrill, into its main brand. At the time of writing, you need to create an account with Mailchimp, then log in to Mandrill afterwards. + +Mailchimp refused to provide FusionAuth with an account while writing this article. The steps below should work, but we were unable to send a test email to be certain. + +- Sign up for an account at https://login.mailchimp.com/signup/?entrypoint=mandrill&locale=en. +- If Mailchimp suspends your account for violating the terms of service, click View issues at the top of the Mailchimp website, then Resolve at the bottom of the page to contact support. +- Log in to https://mandrillapp.com/settings/sending-domains and add your domain name in the text field at the bottom of the page. +- At the bottom of the page click View details for each record that needs to be verified. + - In your website domain manager, add the DNS records from the domain authentication page. + - Once you have entered the DNS records and saved, start the verification process on the Mailchimp page. It should take a minute. +- Browse to https://mandrillapp.com/settings/index and note your SMTP settings. Create a new API key at the bottom of the page. +- In your tenant's email tab in the FusionAuth web interface, set the following values: + - Host: `smtp.mandrillapp.com` + - Port: `587` + - Username: Enter anything + - Password: Your API key + - Security: `TLS` + - Default from address: Use an address at your domain +- Click Send test email to test that the settings work, then click the save icon at the top right. + +### MailerSend + +- Create an account at https://app.mailersend.com. +- Browse to [Email -> Domains](https://app.mailersend.com/domains) and click Manage on the trial domain MailerSend created for you. +- Under SMTP, click Generate new user and then enter the SMTP name for the user. +- MailerSend will generate the user credentials and you can save them. +- In your tenant's email tab in the FusionAuth web interface, set the following values: + - Host: `smtp.mailersend.net` + - Port: `587` + - Username: Your username from the User page + - Password: Your password from the User page + - Security: `TLS` + - Default from address: Use your MailerSend trial, such as `fa@trial-o89qngkvfrwlwr32.mlsender.net` +- Click Send test email to test that the settings work, then click the save icon at the top right. +- To use your real domain, browse to [Email -> Domains](https://app.mailersend.com/domains). + - Click Add domain. + - On the Domain verification page, you are given DNS records to add to your domain. + - In your domain manager website, add these records. + - Once you have entered the DNS records and saved, start the verification process at the bottom of the MailerSend page. It should take a minute and you will be emailed when verification is done. + - Click Generate new user for this domain and use the SMTP details in FusionAuth. + +### Mailgun (Sinch) + +- Create an account at https://signup.mailgun.com/new/signup. +- If you are only testing Mailgun, you can use the sandbox domain name Mailgun creates for you to send emails. If you have paid for an account, you should add and verify your company's real domain. +- Add your domain name under Sending -> Add new domain in the Mailgun dashboard at https://app.mailgun.com/mg/sending/new-domain. + - In your domain manager website, add the DNS records from the domain authentication page. + - Once you have entered the DNS records and saved, start the verification process on the Mailgun page. It should take a minute. +- If you are using an unpaid account, you need to add authorized email receivers. Browse to Domains -> Overview and ensure the sandbox domain is selected. Add the email address where you want to receive a test email from FusionAuth. + - Click the verification link in the email you receive to authorize your address. +- Browse to https://app.mailgun.com/mg/sending/domains. Click the gear icon to the right of your domain name and select Settings to browse to a page like https://app.mailgun.com/app/sending/domains/myapp.com/settings. Select the SMTP credentials tab. +- In your tenant's email tab in the FusionAuth web interface, set the following values: + - Host: `smtp.mailgun.org` + - Port: `587` + - Username: Your login name. If using an unpaid account you must use the sandbox domain. + - Password: Get this by pushing Reset password in Mailgun and copying the value you are given. + - Security: `TLS` + - Default from address: Use your Username value from above +- Click Send test email to test that the settings work, then click the save icon at the top right. Enter your authorized email address for the test email, so you can test it arrives. + +### Postmark + +- Create an account at https://account.postmarkapp.com/sign_up and enter your domain name. +- Verify your email address. +- Browse to https://account.postmarkapp.com/signature_domains. + - Click DNS Settings above your domain name. + - In your domain manager website, add the DNS records from the domain authentication page. + - Once you have entered the DNS records and saved, start the verification process on the Postmark page. It should take a minute. +- To see your SMTP settings, browse to https://account.postmarkapp.com/servers, then click My First Server -> Default Transactional Stream -> Setup Instructions -> SMTP. +- In your tenant's email tab in the FusionAuth web interface, set the following values: + - Host: `smtp.postmarkapp.com` + - Port: `587` + - Username: Your username from the settings page + - Password: Your password from the settings page + - Security: `TLS` + - Default from address: Any address is allowed +- Click Send test email to test that the settings work, then click the save icon at the top right. + +While in the Postmark sandbox mode before account approval, you may not send emails to addresses outside your domain. These addresses will be shown in the Activity tab of your server on Postmark. + +### Resend + +- Create an account at https://resend.com. +- Browse to https://resend.com/domains. +- In your website domain manager, add the records from Resend at the link above. + - You need to set only the DKIM and SPF fields for testing. The DMARC field is optional and required only for your production server. + - Once you have entered the DNS records and saved, return to https://resend.com/domains and start the verification process. It should take a few minutes. +- Browse to https://resend.com/api-keys and create a key with sending access only. +- Browse to https://resend.com/settings/smtp and note your SMTP details. +- In your tenant's email tab in the FusionAuth web interface, set the following values: + - Host: `smtp.resend.com` + - Port: `587` + - Username: `resend` + - Password: Your API key + - Security: `TLS` + - Default from address: Use an email address at your domain +- Click Send test email to test that the settings work, then click the save icon at the top right. + +For an overview of all the records Resend asks you to set on your domain, please read their [documentation](https://resend.com/docs/dashboard/domains/introduction). For more general information, read the [Resend documentation on SMTP](https://resend.com/docs/send-with-smtp). + +### SendGrid (Twilio) + +- Create an account at https://signup.sendgrid.com. +- Verify your email address. +- Browse to https://app.sendgrid.com/settings/sender_auth/senders/new and create a new sender. + - Enter all company details and click Create. + - Verify your sender email address. +- Browse to https://app.sendgrid.com/settings/sender_auth and under Authenticate Your Domain, click Get Started. + - In your domain manager website, add the DNS records from the domain authentication page. + - Once you have entered the DNS records and saved, start the verification process on the SendGrid page. It should take a minute. +- To see your SMTP settings, browse to https://app.sendgrid.com/guide/integrate/langs/smtp. + - Create an API key. +- In your tenant's email tab in the FusionAuth web interface, set the following values: + - Host: `smtp.sendgrid.net` + - Port: `587` + - Username: apikey + - Password: Your API key from the settings page + - Security: `TLS` + - Default from address: Your verified sender created earlier +- Click Send test email to test that the settings work, then click the save icon at the top right. + +## Troubleshoot + +Below are some common errors you might get when configuring SMTP and how to fix them. + +### Authentication Error + +```text +Unable to send email via JavaMail + +Prime Messaging Exception +535 Authentication failed. +``` + +This error indicates that your username or password is incorrect. Re-enter them carefully with no excess whitespace and try again. + +If the error looks like the one below, you need to set up a [Google application password](https://support.google.com/accounts/answer/185833). + +```text +Prime Messaging Exception +535-5.7.8 Username and Password not accepted. For more information, go to +535 5.7.8 https://support.google.com/mail/?p=BadCredentials +``` + +### Account Suspended + +```text +Unable to send email via JavaMail + +Prime Messaging Exception +502 5.7.0 Your SMTP account is not yet activated. Please contact us at contact@sendinblue.com to request activation. +``` + +Some providers automatically disable your account at registration. Contact support at your provider to have it activated. + +### Socket Timeout + +```text +Error: + +Unable to send email via JavaMail + +Prime Messaging Exception +Exception reading response +Cause: SocketTimeoutException: Read timed out +``` + +You may need to change the port number. Try `587`. + +### Domain Not Verified + +```text +Unable to send email via JavaMail + +Prime Messaging Exception +450 The resend.com domain is not verified. Please, add and verify your domain on https://resend.com/domains +``` + +You need to verify your domain with your SMTP provider by setting DNS records on your web host. + +Be aware that DNS records take time to change. If you make a change to a record that your SMTP provider needs to validate, you may have to wait an hour to a day for caches to refresh before you can use the new value. + +### Email Address Not Verified + +```text +Unable to send email via JavaMail + +Prime Messaging Exception +554 Message rejected: Email address is not verified. The following identities failed the check in region EU-WEST-1: address/fa@simplelogin.com +``` + +```text +Unable to send email via JavaMail + +Prime Messaging Exception +421 Domain fa.dns-dynamic.net is not allowed to send: Free accounts are for test purposes only. Please upgrade or add the address to authorized recipients in Account Settings. +``` + +This error is only likely if you use AWS or Mailgun, which require your sender address to be verified when testing until your service leaves the testing sandbox. To fix this error, send the FusionAuth test email to the same address that you verified when creating the SES service in AWS or add the address to the list of authorized recipients in Mailgun. + +### Email Doesn't Arrive + +Try the following: +- Wait longer. +- Check that you entered the receiver email address correctly. +- Email an address that is authorized and verified by your SMTP provider, such as the one on your authenticated domain that you used to register your account. Check if the provider has an authorized recipient section and add the address there. +- Check if your SMTP provider received the request and the status is not `Bounced`. +- Check your spam folder in your email client, or other folders if you have filters enabled. +- Disable webhooks in FusionAuth, in case a failed webhook is causing complications. + +## SMTP Best Practices + +This section lists some recommendations by SMTP providers for transactional emails. Your primary aim should be to keep your sender reputation high to avoid emails being marked as spam. + +- Ensure that you add all SPF, DKIM, DMARC, and MX records to your DNS records. +- For extra trustworthiness and brand building, set up Brand Indicators for Message Identification (BIMI), which enables email inboxes to display a brand’s logo next to the company’s authenticated email messages. +- Send emails only to people who have requested to receive them. Always first send a confirmation link to confirm their address is valid. +- Follow your SMTP provider's documentation to configure analytics for your emails (click tracking). +- Track your emails and adjust your sending based on feedback from ESPs and recipients. Don't send emails to recipients who have unsubscribed or complained of spam. Monitor the results of email sending on your SMTP provider's analytics web page. +- Send as few emails to users as possible to avoid emails being marked as spam. Keep your email content as short as possible to avoid wasting your users' time. +- Always include a link to unsubscribe in your emails. +- Always test new email templates by emailing them to yourself on a test FusionAuth server before enabling them in production. Check that fields are populated correctly. +- Send multipart emails using both text and HTML or text only. ESPs do not trust HTML-only email and block images by default. Preview how your emails look with tools like [Litmus](https://www.litmus.com/email-testing). +- Too many links and images trigger spam flags at ESPs. Misspellings and spammy words ("buy now!", "Free!") are spam flags, as are ALL CAPS AND EXCLAMATION MARKS!!!!!!!!!!!!! +- Don't use URL shortening services for links. Use your domain's full URL. +- The domains in the `from` field, `return-path`, and `message-id` should match the domain you are sending from. +- Send transactional and marketing emails through different IP addresses, as marketing email is more likely to be marked as spam. FusionAuth uses only transactional email. +- For similar reasons, send your transactional email and your marketing email through different subdomains. Your domain and your IP address both have reputations with ESPs. +- Do not use a `noreply` email address as your sender. Instead, route all customer replies to your support team. + +### Shared IP Addresses + +Most SMTP providers allow you to send through an individual IP address dedicated to your account or an IP address (or pool of addresses) shared by multiple SMTP accounts. If you are sending low volumes of email (less than 5000 per day), a shared IP address is a good choice. Shared addresses are less expensive than dedicated addresses. The address is already known and trusted by ESPs, so your emails are unlikely to be sent to spam folders. -For Gmail, use [application passwords](https://support.google.com/accounts/answer/185833), otherwise you may get a generic `Unable to send email via JavaMail / Prime Messaging Exception` error. +If an SMTP account starts sending spam and decreases the address's reputation, the SMTP provider will take action, either canceling the client's account or moving them to a lower-reputation IP address pool. +Mailgun recommends one dedicated IP address for every million messages sent per month. diff --git a/astro/src/content/docs/extend/examples/api-gateways/cloudflare-api-gateway.mdx b/astro/src/content/docs/extend/examples/api-gateways/cloudflare-api-gateway.mdx new file mode 100644 index 0000000000..cea99be74f --- /dev/null +++ b/astro/src/content/docs/extend/examples/api-gateways/cloudflare-api-gateway.mdx @@ -0,0 +1,317 @@ +--- +title: Cloudflare Worker Functions (API Gateway) +description: Learn about the Cloudflare Worker Functions and JWT integration. +navcategory: developer +section: extend +subcategory: examples +tertcategory: api gateways +--- +import Aside from 'src/components/Aside.astro'; +import InlineField from 'src/components/InlineField.astro'; +import InlineUIElement from 'src/components/InlineUIElement.astro'; +import ScrollRef from 'src/components/ScrollRef.astro'; +import FrameworkIntegrationTutorialList from 'src/content/docs/_shared/_framework-integration-tutorial-list.mdx'; + +## Overview + +Cloudflare is a global cloud platform designed to make everything you connect to the internet secure, private, fast, and reliable. Creating an API Gateway app on Cloudflare is a great way to manage, secure, and optimize your APIs. Cloudflare offers several services that can help you achieve this, such as Cloudflare Workers, Cloudflare Gateway, and Cloudflare Load Balancing. + +You can set up Cloudflare Workers to handle authentication and authorization to a resource through JSON Web Tokens (JWTs) issued to a user by an identity provider. + +This guide will show you how to set up Cloudflare Workers and use FusionAuth as the identity provider to protect a Worker function running on your Cloudflare. + +Please note that there are many ways to integrate FusionAuth with Cloudflare. For this guide, we chose to use a Worker function created on the Cloudflare portal, but you can also use Wrangler, the Cloudflare Workers command-line interface (CLI). Find more info on Wrangler in the [Cloudflare documentation](https://developers.cloudflare.com/workers/wrangler/). + +## Prerequisites + +* A FusionAuth instance running on a publicly accessible URL. You can spin up a [basic FusionAuth Cloud instance](/pricing) or [install it on any server](/docs/get-started/download-and-install). You can also tunnel to your local instance of FusionAuth through a tool like [ngrok](https://ngrok.com). +* A [Cloudflare account](https://dash.cloudflare.com/login). + + +## Set Up FusionAuth + +First, you need to make sure the JWT issuer setting is correct for your FusionAuth instance. Navigate to Tenants -> Your Tenant and change the issuer to the URL of your FusionAuth instance. For example, you can set a value like `https://local.fusionauth.io` if your FusionAuth instance is accessible at `https://local.fusionauth.io`. Note down this value, as you'll set it in the Cloudflare Worker function later. + +If you are running FusionAuth locally and want to expose it publicly using ngrok, you can run the following command. + +```shell +ngrok http 9011 +``` + +This command assumes your local FusionAuth instance is running on port 9011, which is the default for local FusionAuth installations. Look for the `Forwarding` line in the output. It should look something like this: + +``` +Forwarding https://7817-102-218-66-2.eu.ngrok.io -> http://localhost:9011 +``` + +The ngrok forwarding address will be publicly accessible and you can use this URL in place of `` in this guide. + + +Next, you need to configure an application that will issue tokens to access the Cloudflare function. Navigate to Applications and create a new application. Fill out the Name field and select a Tenant if you have more than one. Click on the OAuth tab and make sure that `Authorization Code` and `Refresh Token` grants are enabled under Enabled grants. + +Your application should look like this. + +The FusionAuth example configuration + +On the JWT tab, toggle the Enabled switch and set the Access Token signing key and Id Token signing key to `Auto generate a new key on save...`. + +The JWT configuration + +Click the Save button to save the application. + +You will be redirected to the page that lists all your applications. Click the Edit button next to the application you just created. Note down the Client Id value to use in the step. + +Extracting the Client Id and secret + +For testing, you'll need to link a FusionAuth user to your application. You can either use the existing user you used to log in to FusionAuth or create a new isolated user. + +To create a new user, navigate to Users in the sidebar and click the green + button at the top right of the screen. Choose the appropriate tenant and fill in the Email. To set the password for the user directly without sending an email, toggle the Send email to set up password switch. Record this user email and password, as you'll use it to obtain a token. + +Creating a new user + +Now select the Registrations tab. Click Add registrations and select the FusionAuth application you set up earlier. Alternatively, to link your existing user, navigate to the user list by selecting Users on the left sidebar. Find your user and click the Manage action button on the user. Select the Registrations tab. Click Add registrations and select the FusionAuth application you set up earlier. + +The application registrations tab + +Next, set up an API key. On the left sidebar, select Settings -> API Keys. Click the green + button at the top left to create a new key. Give the key a description, like `API Gateway Key`. Select the tenant that you created the FusionAuth application under. + +Then, on Endpoints, allow `POST` on the `/api/login` route. This key will only be allowed to call this endpoint with the `POST` method. + +Enabling the login API + +Save the API key. You should now see a list of all API keys. Click on the lock icon next to the key field for the key you just created and copy the API key for later use. Make sure you get the API key value and not the API key Id. + +Enabling the login API + + +## Set Up Cloudflare + +Navigate to your [Cloudflare dashboard](https://dash.cloudflare.com/login) and log in or create a [Cloudflare account](https://developers.cloudflare.com/fundamentals/setup/account/create-account/) if you haven't got one already. + + +### Create A Cloudflare Worker Function + +On the left-hand sidebar, navigate to Workers & Pages -> Overview. Click the Get Started button if you are setting up a worker for the first time, or the Create Application button to get to the Create Worker screen. + +Cloudflare Workers & Pages overview page + +Click the Create Worker button. + +Give the worker a descriptive name (we will use `privatefunction`) and click the Deploy button at the bottom to deploy the function. The default script is fine for now, you will update it in the next step. + +Create a Cloudflare worker + +Test that the deployed function is working by clicking on the preview link provided on the next page. + +Preview a Cloudflare worker + +A new browser tab will open containing the text "Hello world!" + +Return to the Worker configuration page and click the Edit Code button. Replace the initial `Hello World` code with the code below to handle authorization requests to FusionAuth. Remember to update the code with your values for `fusionAuthApiKey`, `fusionAuthClientId`, and `fusionAuthUrl`. + + +```javascript title="Worker function to handle claims requests and validate the token" + +// Replace with your FusionAuth values +const fusionAuthApiKey = ''; +const fusionAuthClientId = ''; +const fusionAuthUrl = ''; + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); + +async function handleRequest(request) { + const { pathname } = new URL(request.url); + + // Check if the request is for the /api/claims endpoint + if (pathname === "/api/claims") { + let authToken = request.headers.get("Authorization"); + if (authToken && authToken.startsWith("Bearer ")) { + authToken = authToken.slice(7); + } + // Verify the authentication token + const verificationResponse = await verifyAuthToken(authToken); + if (verificationResponse.active === true) { + // Call your Worker API function and pass the claims + return handleClaimsAPI(verificationResponse); + } else { + return new Response("Unauthorized", { status: 401 }); + } + } else { + return new Response("Not found", { status: 404 }); + } +} + +async function verifyAuthToken(authToken) { + const url = `${fusionAuthUrl}/oauth2/introspect`; + const options = { + method: "POST", + headers: { + Authorization: `Bearer ${fusionAuthApiKey}`, + "Content-Type": "application/x-www-form-urlencoded", + }, + body: `token=${authToken}&client_id=${fusionAuthClientId}`, + }; + + try { + const response = await fetch(url, options); + if (!response.ok) { + return { error: "Invalid response" }; + } + return await response.json(); + } catch (error) { + console.error("Error making fetch request:", error); + return { error: "Invalid JSON response" }; + } +} + +async function handleClaimsAPI(claims) { + // Your Worker API function logic + const response = { + statusCode: 200, + body: JSON.stringify(claims), + }; + return new Response(response.body, { status: response.statusCode }); +} +``` + +This Cloudflare Worker function code sets up an API gateway that integrates with FusionAuth for authentication and authorization. The API gateway accepts requests to the `/api/claims` endpoint. It verifies the authentication token using the FusionAuth API and, if it is valid, passes the claims to the `handleClaimsAPI` function, which represents the logic for your API endpoint. + +- The `fusionAuthApiKey`, `fusionAuthClientId`, and `fusionAuthUrl` values are used to communicate and authenticate with your FusionAuth instance. Replace the values with the values you noted when setting up FusionAuth earlier. +- The `addEventListener` function is used to listen for incoming requests and pass them to the `handleRequest` function. +- The `handleRequest` function is the main entry point for handling incoming requests. + - It checks if the request path matches `/api/claims`. If the path matches, it extracts the authentication token from the request headers. + - It calls the `verifyAuthToken` function to verify the authentication token with the FusionAuth API. + - If the token is valid `(verificationResponse.active === true)`, it calls the `handleClaimsAPI` function, passing the response claims as an argument. + - If the token is invalid, it returns an "Unauthorized" response with a 401 status code. + - If the request path doesn't match `/api/claims`, it returns a "Not found" response with a 404 status code. +- The `verifyAuthToken` function is responsible for verifying the authentication token with the FusionAuth API. + - It constructs the request options, including the FusionAuth API key, client Id, and the authentication token. + - It sends a POST request to the FusionAuth introspection endpoint `/oauth2/introspect` with the request options. + - If the response is valid JSON, it returns the parsed JSON data. + - If the response is not valid JSON, it returns an error object. +- The `handleClaimsAPI` function represents the logic for your API endpoint. + - It receives the claims from the verified authentication token. + - In this example, it constructs a response object with a 200 status code and the claims as the response body. + - It returns a new `Response` object with the response body and status code. + +When you have entered the code, click the Deploy button on the top right to redeploy the function. A new route will be available and the full URL to the claims endpoint should look something like `https://privatefunction..workers.dev/api/claims`. + +If you make a request to this route through a browser, Postman, or curl, you will receive a `401` HTTP status code and an `Unauthorized` message. We'll create a token next with FusionAuth to show how the route can be successfully called. + +Call the API gateway with the following curl command to test, replacing `` with your Worker URL, which should look like `https://privatefunction..workers.dev/api/claims`. + +```shell title="Calling the API Gateway endpoint " +curl --location --request GET '' +``` + +You should get an `Unauthorized` response. + + +### Testing With A Token From FusionAuth + +To access the secured Worker function, you'll need to get a valid token. Normally, your frontend app would use the Authorization Code Grant flow, which redirects a user to FusionAuth to log in, obtains a code, and then exchanges that code for a token, using a framework of your choice. [More on the Authorization Code grant](/docs/lifecycle/authenticate-users/oauth/). + +For this guide, we'll call the [FusionAuth Login API](/docs/apis/login) on behalf of a user to create a token directly. This is a more straightforward means of getting a token, but the generated token will be similar with either process. + +Using curl or Postman, make a POST request to your FusionAuth instance's `/api/login` endpoint. This will return a JWT in the response. + +```shell title="curl command to obtain a JWT token" +curl --location --request POST '/api/login' \ +--header 'Authorization: ' \ +--header 'Content-Type: application/json' \ +--data-raw ' { + "loginId": "", + "password": "", + "applicationId": "", + "noJWT" : false + }' +``` + +Replace the following values with the values you noted in the section. + +* `` is the URL of your FusionAuth installation. +* `` is the API key created earlier, enabled for login. +* `` is the email address of the user added earlier. +* `` is the password of the user added earlier. +* `` is the client Id of the FusionAuth application registered for the user. + +The response from FusionAuth should look similar to the following. + +```json title="FusionAuth Login API Response" +{ + "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImhDUjA4X3daR2s0OUFlYUFmRDY5ZmJKWmRGTSJ9.eyJhdWQiOiI2M2I3M2Y3Ni03NDAwLTQ4N2QtYjEyMi01NzA1Yjg0OGRhODAiLCJleHAiOjE2NzMzNjYyMDQsImlhdCI6MTY3MzM2MjYwNCwiaXNzIjoiaHR0cHM6Ly9mdXNpb25hdXRoLnJpdHphLmNvIiwic3ViIjoiMzk2MzAwMGYtNjg2ZC00MTY5LWI2MjgtOWM5YzQ1MzRiNzgwIiwianRpIjoiZDk3ZGIyZWYtZjExNS00ZDIxLWFlOTQtMDIyN2RmMGU4YzI5IiwiYXV0aGVudGljYXRpb25UeXBlIjoiUEFTU1dPUkQiLCJlbWFpbCI6ImJvYkBhd3MuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInByZWZlcnJlZF91c2VybmFtZSI6ImJvYmF3cyIsImFwcGxpY2F0aW9uSWQiOiI2M2I3M2Y3Ni03NDAwLTQ4N2QtYjEyMi01NzA1Yjg0OGRhODAiLCJyb2xlcyI6W10sImF1dGhfdGltZSI6MTY3MzM2MjYwNCwidGlkIjoiZjAwNGMxZmUtNDg0Yi05MDJjLWQ3Y2EtYmRiYzQ2NGRhMGI3In0.m7gzXhNLToPNVE1p5Vo2pLgP6WBcPNfS_zZJnJ81mdEgi6-orViz-tU8j0L8wva0-8KlMdy54cq_XjnDnYJ0aX90O4ZE_QVU5NuDDfzXH14wQtKQoIIydsB6ZvQoBt8JNFUHJb9ANLCGnfn6FVQKqPIzye18Gx_7wYSVokw3eLNFyzrq9dwOD5Q8V9gvZmXV2pTokQAtA7qFaadb2dIeFlSEB7wamKiZLXILjeWAeMbbvAAMQZWFh46UJjwr06QTd8PxQmRwDWWznJy1Vs8EAgZA4vkRSWnn3IbiaCtOaL1ANuEex6il7q32ahxj0Ncm9wn0DbDsQE9NB0CCNTSIhA", + "tokenExpirationInstant": 1673366204805, + "user": { + "sampleuserdata" : "..." + } +} +``` + +Copy the `token` value. This is a JWT, which we can use to access the API gateway function. + +Now call the API gateway with the following curl command: + +```shell +curl --location --request GET '' \ +--header 'Authorization: Bearer ' +``` + +* `` is the invoke URL for the claims endpoint saved earlier, for example, `https://privatefunction..workers.dev/api/claims`. +* `` is the JWT from the `/api/login` call. + +You should see the function return with a reflection of the claims it received. + +```json +{ + "active":true, + "applicationId":"18740210-b386-4679-a626-a84d9abdb8dd", + "aud":"18740210-b386-4679-a626-a84d9abdb8dd", + "auth_time":1716133402, + "authenticationType": "PASSWORD", + "email":"richard@example.com", + "email_verified":true, + "exp":1716137002, + "iat":1716133402, + "iss":"https://local.fusionauth.io", + "jti":"64d7e970-d0ff-4bbc-82b4-adc80413818e", + "preferred_username":"richard", + "roles":[], + "sub":"588155c8-b1df-4fb6-8c40-5f431e770644", + "tid":"31f7e6b3-9c71-4a7f-b1e2-45be0d7067d8" +} +``` + +## Troubleshooting + +* If you are running a local instance of FusionAuth, the Cloudflare Worker will not be able to reach the key sets needed to validate the JWT. You will either need to host FusionAuth on a publicly accessible URL or proxy your local instance through a tool like [ngrok](https://ngrok.com). +* Ensure that the generated FusionAuth application's Access Token signing key and Id Token signing key on the application's JWT tab are asymmetric (RS256). +* The JWT issued by the [FusionAuth Login API](/docs/apis/login) has an expiry. If you wait too long before using it to call the Cloudflare Worker, the token will expire and the call will fail. You can resolve this by rerunning the curl command to obtain a new JWT token and then use the new token. + +## Next Steps + +You can build a complete HTTP API using Cloudflare Workers, Cloudflare Gateway, Cloudflare Load Balancing, and FusionAuth without managing any servers. + +### Custom Domain + +To use a custom domain for your API (for example, `api.yourdomain.com`), set up a DNS record in the Cloudflare dashboard pointing your subdomain to `your-workers-subdomain.workers.dev`. + +### Configure Routes + +Set up routes to associate your Worker with your domain or subdomains. For example, you can route `https://api.yourdomain.com/*` to your Worker. + +Configure custom domains and routes in the Trigger section of the Settings tab for your Worker. Note that these options are only available if you have a domain set up in the Cloudflare environment. New domains may take some time to propagate. + + + +### Secure Your API With Cloudflare Gateway + +- Go to the Zero Trust dashboard in Cloudflare to set up security policies for your API. +- Define policies to restrict access to your API, such as IP filtering, token-based access, or integrating with certain identity providers for alternative web login methods. FusionAuth is not an option here, but it can manually be added as a login provider using OpenID connect as an alternative solution. + +Finally, you can configure FusionAuth to ensure that the user is registered for the Cloudflare application or [fire off webhooks](/docs/extend/events-and-webhooks/) when the user logs in. + +You used the FusionAuth API to create a test token on behalf of a user. For a production system, the token will be generated after a user signs in to your application through a frontend. Check out some of the framework integration tutorials to implement that: + + diff --git a/astro/src/content/docs/get-started/core-concepts/editions-features.mdx b/astro/src/content/docs/get-started/core-concepts/editions-features.mdx index 5543b99ef9..bead00b49c 100644 --- a/astro/src/content/docs/get-started/core-concepts/editions-features.mdx +++ b/astro/src/content/docs/get-started/core-concepts/editions-features.mdx @@ -9,6 +9,8 @@ import AdvancedEditionBlurbApi from 'src/content/docs/_shared/_advanced-edition- import EnterpriseEditionBlurb from 'src/content/docs/_shared/_enterprise-edition-blurb.astro'; import EnterpriseEditionBlurbApi from 'src/content/docs/_shared/_enterprise-edition-blurb-api.astro'; import Features from 'src/content/docs/_features.astro'; +import LicensedEditionBlurb from 'src/content/docs/_shared/_licensed-edition-blurb.mdx'; +import LicensedEditionBlurbApi from 'src/content/docs/_shared/_licensed-edition-blurb-api.mdx'; import LicensingPremiumFeaturesIntro from 'src/content/docs/_shared/_licensing-premium-features-intro.mdx'; import PremiumEditionBlurb from 'src/content/docs/_shared/_premium-edition-blurb.astro'; import PremiumEditionBlurbApi from 'src/content/docs/_shared/_premium-edition-blurb-api.astro'; @@ -23,6 +25,7 @@ There are four different editions. They are also called plans. * `Community` has all features not otherwise labeled in the documentation. +* `Licensed Community` has all licensed community features. * `Starter` has all premium features, but some may have some numeric or usage limits. * `Essentials` has all advanced and premium features, but some may have some numeric limits. * `Enterprise` has all enterprise, advanced and premium features and no limits. @@ -31,7 +34,11 @@ Please review the [pricing page](/pricing) for much more information on editions ## Feature List -Here are the major features available in each paid edition. +Here are the major features available in each licensed edition. + +### Licensed Community Features + + ### Premium Features @@ -51,6 +58,16 @@ The FusionAuth documentation calls out features not part of the Community editio If a feature you are using requires a license, you may also encounter an error message in the administrative user interface or in an API message. +### Licensed Community Features + +Throughout the documentation, you'll see features available to all licensed editions marked like so: + + + +In the API documentation, you'll see licensed features marked like this: + + + ### Premium Features Throughout the documentation, you'll see premium features marked like so: diff --git a/astro/src/content/docs/get-started/core-concepts/localization-and-internationalization.mdx b/astro/src/content/docs/get-started/core-concepts/localization-and-internationalization.mdx index 183abc9ccd..977d8f9d85 100644 --- a/astro/src/content/docs/get-started/core-concepts/localization-and-internationalization.mdx +++ b/astro/src/content/docs/get-started/core-concepts/localization-and-internationalization.mdx @@ -63,20 +63,22 @@ After you have set up your localized theme, set the tenant's Login The current list of languages is: -* English (`en`) * Arabic (`ar`) +* Chinese Simplified (`zh_CN`) +* Czech (`cz`) * Danish (`da`) -* German (`de`) -* Spanish (`es`) +* Dutch (`nl`) +* English (`en`) * Finnish (`fi`) * French (`fr`) +* German (`de`) * Indonesian (`id_ID`) * Italian (`it`) * Japanese (`ja`) -* Dutch (`nl`) * Polish (`pl`) * Portuguese - Brazilian (`pt_BR`) * Russian (`ru`) +* Spanish (`es`) * Swedish (`sv`) * Ukrainian (`ua`) @@ -86,6 +88,22 @@ Here's a brief video showing how to install translated messages in your theme. Visit the [fusionauth-localization GitHub repo](https://github.com/FusionAuth/fusionauth-localization/) to view the most up to date list of translations or to contribute one. +### Unsupported Languages + +There's a distinction in FusionAuth language support for the hosted login pages, which is the difference between internationalization and localization. This is discussed [above](#overview), but it is worth reiterating that both of these are true: + +* FusionAuth is built to support any language for the hosted login pages experience. Your end users can log in using a UX that is in their language. This is because the hosted login pages are internationalized. +* FusionAuth, however, does not provide translations for all human languages. The team only provides an English translation. There is a [fusionauth-localization GitHub repo](https://github.com/FusionAuth/fusionauth-localization/) which has community provided translations for the languages listed above. The team is happy to accept revisions or new translations. This is because the hosted login pages are not fully localized in all languages. + +Suppose you needed support for both Afrikaans and Zulu, but find that there are no translations available. To use FusionAuth with these languages, you would: + +* download the English messages file from the [GitHub repo](https://github.com/FusionAuth/fusionauth-localization/) and translate all messages using whatever resources or software you had access to +* install the new file in FusionAuth as documented above + +You could contribute the translated messages file back to the community, if you desired to, by opening a PR against the GitHub repo. + +You should review the content of the messages file to make sure it meets your branding requirements as well. You typically need to refine or modify the messages based on your product's tone, messaging and brand identity. + ## Emails and Other Messages FusionAuth sends emails and other messages on behalf of your application. An example would be a "Forgot Password" email. FusionAuth provides support for you to customize and localize these messages. diff --git a/astro/src/content/docs/get-started/core-concepts/premium-features.mdx b/astro/src/content/docs/get-started/core-concepts/premium-features.mdx index b844d34ff7..e3bd62d599 100644 --- a/astro/src/content/docs/get-started/core-concepts/premium-features.mdx +++ b/astro/src/content/docs/get-started/core-concepts/premium-features.mdx @@ -11,6 +11,10 @@ import Features from 'src/content/docs/_features.astro'; FusionAuth has a full-featured community edition, but some features are reserved for customer with a license key. This section outlines the features and how to use them. +### Licensed Community Features + + + ### Premium Features {/* Don't add a new feature here. Add it to the src/content/json/features.json file and the list will be generated. */} diff --git a/astro/src/content/docs/get-started/run-in-the-cloud/cloud.mdx b/astro/src/content/docs/get-started/run-in-the-cloud/cloud.mdx index 374238cc93..d8b5aa1560 100644 --- a/astro/src/content/docs/get-started/run-in-the-cloud/cloud.mdx +++ b/astro/src/content/docs/get-started/run-in-the-cloud/cloud.mdx @@ -14,7 +14,6 @@ import AccountSectionsOverview from 'src/content/docs/get-started/_account-secti import CloudUserNote from 'src/content/docs/get-started/_cloud-user-note.mdx'; import SettingUpPortalAccount from 'src/content/docs/get-started/_setting-up-portal-account.mdx'; - ## Overview FusionAuth Cloud is an entirely managed FusionAuth instance in the cloud. As the owner of that server, you have complete access to the administrative user interface and can create API keys and manage the instance via client libraries or APIs. But you have no access to the servers or networks where the instance runs. @@ -390,10 +389,11 @@ You can migrate the user data FusionAuth holds for you in a number of ways: * From a different auth provider into FusionAuth. * Away from FusionAuth to a different auth provider. -If you are interested in migrating to FusionAuth from an auth system other than FusionAuth, check out the [Migration Guide](/docs/lifecycle/migrate-users/). +If you want to retrieve your user data from FusionAuth Cloud in order to migrate to a different auth provider, see [Accessing User Data](#accessing-user-data). To retrieve user data from a self-hosted FusionAuth instance, query the database. + +### Migrating From A Different Auth Provider -If you want to retrieve your user data from FusionAuth Cloud in order to migrate to a different auth provider, see [Accessing User Data](#accessing-user-data). -To get user data from a self-hosted FusionAuth instance, query the database. +If you are interested in migrating to FusionAuth from an auth system other than FusionAuth, check out the [Migration Guide](/docs/lifecycle/migrate-users/). ### Migrating To FusionAuth Cloud @@ -422,7 +422,6 @@ After your data is uploaded, upgrade your deployment to any subsequent FusionAut | [ ] | Encrypted the database export. | | [ ] | Provided the decryption password via a separate communication channel. | - ### Migrating Away From FusionAuth Cloud To migrate from FusionAuth Cloud to a self-hosted instance, please request a database export, as documented in [Accessing User Data](#accessing-user-data). diff --git a/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/enterprise/samlv2-idp-initiated.mdx b/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/enterprise/samlv2-idp-initiated.mdx index 4d98b586a5..83f9cdaa83 100644 --- a/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/enterprise/samlv2-idp-initiated.mdx +++ b/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/enterprise/samlv2-idp-initiated.mdx @@ -7,14 +7,14 @@ subcategory: authenticate users tertcategory: identity providers quatercategory: enterprise --- -import AdvancedEditionBlurb from 'src/content/docs/_shared/_advanced-edition-blurb.astro'; +import PremiumEditionBlurb from 'src/content/docs/_shared/_premium-edition-blurb.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 Fields from '../_samlv2-integration-details-fields.mdx'; - + ## Overview diff --git a/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/gaming/epic-games.mdx b/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/gaming/epic-games.mdx index 8c45030766..7f218ceb8d 100644 --- a/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/gaming/epic-games.mdx +++ b/astro/src/content/docs/lifecycle/authenticate-users/identity-providers/gaming/epic-games.mdx @@ -7,14 +7,14 @@ subcategory: authenticate users tertcategory: identity providers quatercategory: gaming --- -import AdvancedEditionBlurb from 'src/content/docs/_shared/_advanced-edition-blurb.astro'; +import PremiumEditionBlurb from 'src/content/docs/_shared/_premium-edition-blurb.astro'; import Aside from 'src/components/Aside.astro'; import IdpApplicationConfiguration from 'src/content/docs/_shared/_idp-application-configuration.astro'; import IdpFormFields from 'src/content/docs/_shared/_idp-form-fields.astro'; import IdentityProviderOverviewDiagram from 'src/content/docs/_shared/_identity-provider-overview-diagram.astro'; import LoginApiIntegration from 'src/content/docs/_shared/_login-api-integration.astro'; - +