diff --git a/.github/knownwords.txt b/.github/knownwords.txt index 9f19ac0e31..bd4d6559e0 100644 --- a/.github/knownwords.txt +++ b/.github/knownwords.txt @@ -2786,4 +2786,11 @@ Salzman Tamás JavaMail HAProxy's - +XSLT +XSLTC +Xalan +bytecode +geoalexidis +sjswami +Kosovo +annismckenzie diff --git a/DocsDevREADME.md b/DocsDevREADME.md index 2a1e90b614..78561c1cd7 100644 --- a/DocsDevREADME.md +++ b/DocsDevREADME.md @@ -453,127 +453,24 @@ Prior to requesting review on a PR, please complete the following checklist. 4. If you are referring to any other UI element, such as a submit button or read-only name, use `[uielement]#Submit#` or (on the application view screen) `[uielement]#Introspect endpoint#`. -## Blog post review checklist - -1. Assign the relevant issue to yourself. -1. Work through the blog post as is. Make any updates you need to ensure the instructions work. **Test every instruction, please.** -1. Do not create a new blog post. Update the existing blog post. If you feel like the code and structure has changed radically enough that a new blog post is better, please contact Dan and discuss. -1. Update the install instructions to use the docker install. You can use `{% include posts/install-fusionauth.md %}` to do this easily. -1. If there are any remote code blocks, pull them in with the `remote_include` plugin from the example app. -1. Use the latest released, supported versions of the technology and underlying technologies. -1. Update any screenshots of the FusionAuth admin UI or resulting technology. -1. If there are any videos, remove those from the blog post if the UX has changed as a result of this review. -1. Update the example app in GitHub, if needed. If the technology is on an entirely different version, create a new example app. For instance, if the example uses React 16, and the latest version of React is React 18, don't try to update the existing example app. Instead, create a new repo with the name suffix `fusionauth-example-react-18`. -1. If the existing example app uses a technology that is no longer supported, note that so it can be removed from the FusionAuth site, a link in the repo to the supported example app can be added, and the old repo archived. -1. Update the example app URL and/or description in `site/_data/exampleapps.yaml`. If you created a new example app in GitHub, update the README of the old one to point to the new one, and archive the old one. -1. Add an updated_date to the blog posts front matter: `updated_date: 2023-03-16` -1. If there is an old blog post, add a link to the new blog post or docs page. See https://fusionauth.io/blog/2020/12/14/how-to-securely-implement-oauth-rails for an example of the callout which points to new doc. This is only applicable if there is an old blog post that uses radically different technology. For example, the rails posts used omniauth and the oauth2 gem, two radically different technologies. -1. Run the blog post through a spell and grammar checker. I like to use Google docs (just copy and paste the entire contents of the blog post into a google doc and then use "Tools" -> "Spelling and Grammar" -> "Spelling and Grammar Check". But other spell checks work too. -1. Update the quickstart page (`/docs/quickstarts/index.html`) to point to the updated blog post and remove the `coming-soon` class. -1. Ask for review. -1. Close out the issue after merging. +## Content checklist -## Quickstarts - -Quickstarts are any pages that are going under /docs/quickstarts that are not on the blog. - -For blog posts that are updated and linked under /docs/quickstarts, see `Blog post review checklist`. - -### Webapps - -Webapps are web applications that the user will log into. - -Model this after the ruby on [rails quickstart](https://fusionauth.io/docs/v1/tech/tutorials/integrate-ruby-rails). - -* Use markdown instead of asciidoc (the ruby quickstart needs to be ported over). -* Use a client library to configure the project; don't use the admin ui. Add any setup scripts (or reuse them if needed) to https://github.com/FusionAuth/fusionauth-example-client-libraries -* Make sure you create a sample project and include files from it (using `remote_include`) rather than inline the code. -* For the login integration, use a standard OIDC library, not the FusionAuth client library. -* Build the application from scratch, using whatever codegen tools are standard for the tech stack. -* Put a link to the GitHub example app repo -* Include an image at the end -* Build in a logout link using /oauth2/logout endpoint -* Use the includes under `site/_includes/docs/integration` for the first sections of the tutorial. Make sure you set the expected values in the front matter: - -
-... other front matter
-prerequisites: nodejs
-technology: react
-language: javascript
----
-
-## Integrate Your {{page.technology}} Application With FusionAuth
-
-{% include docs/integration/_intro.md %}
-
-## Prerequisites
-
-{% include docs/integration/_prerequisites.md %}
-
-## Download and Install FusionAuth
-
-{% include docs/integration/_install-fusionauth.md %}
-
-## Create a User and an API Key
-
-{% include docs/integration/_add-user.md %}
-
+This is for substantial content. +1. Create an [issue in fusionauth-site](https://github.com/FusionAuth/fusionauth-site/issues/new) +1. Write the piece. +1. Any screenshots should conform to screenshots standards outlined above. +1. Create a PR. Add the `content` label. +1. Ask another devrel to review it. Add them as a reviewer. If they don't review it in a timely fashion, ping them on slack. +1. Once it has been through tech review, send it through SEO review. Add an asana task, assign it to Brad, and put it under the SEO section in Asana. Put a due date of a week out. +1. Once it has been through SEO review, make any needed changes and then add it to the 'content calendar' asana board. Assign it to Emily so she can pick a publish date. +1. After a publish date has been set, she'll assign it back to you. +1. Publish it on that date. -### APIs +If the content is timely, you can skip some of these steps. Check with Dan or Emily about whether your content is timely. -APIS are JSON HTTP APIs that will validate a JWT and return a value. - -If you are doing a quickstart for an API, rather than for a web application, follow these guidelines: - -* Set up FusionAuth to set access token and refresh tokens as cookies using new hosted backend (full docs incoming, but you can see the PR here: https://github.com/FusionAuth/fusionauth-site/pull/2115 -* Make sure jwt is signed with rs256 key -* Write standalone service which returns 401 if user doesn't present a correct access token. -* Service should return JSON if jwt is valid. Check signature using lib and JWKS, not using validate endpoint. Also check audience, exp and issuer claims -* Add a small bit of js on the browser to call the API, if it gets a 401, should call the refresh endpoint. -* Put a link to the GitHub example app repo - -## Example apps - -Example apps should meet the following criteria: - -* Licensed under apache 2 -* use docker compose to install FusionAuth -* use kickstart to set up FusionAuth -* use a standard user, API key and application id -* use an RSA key -* document how to set things up in as few steps as possible in the readme -* link back to FusionAuth documentation for more details/context if needed - -The goal is to have someone: - -* find the repo -* clone it -* run `docker compose up` to get FusionAuth running -* use a native package manager (npm, bundler, etc, etc) to start up the application -* visit it in the browser or using curl as appropriate - -as soon as possible. - -### Kickstart - -Here's an example kickstart variables section: - -``` -{ - "applicationId": "E9FDB985-9173-4E01-9D73-AC2D60D1DC8E", - "apiKey": "this_really_should_be_a_long_random_alphanumeric_value_but_this_still_works", - "asymmetricKeyId": "#{UUID()}", - "defaultTenantId": "d7d09513-a3f5-401c-9685-34ab6c552453", - "adminEmail": "admin@example.com", - "adminPassword": "password", - "userEmail": "richard@example.com", - "userPassword": "password", - "userUserId": "00000000-0000-0000-0000-111111111111" -} -``` - -Here's a link to an example kickstart: https://github.com/FusionAuth/fusionauth-example-python-flask/blob/master/kickstart/kickstart.json +## Quickstarts -You'll need to change the redirect URLs at a minimum. +Quickstarts are any pages that are going under /docs/quickstarts that are not on the blog. +See https://github.com/FusionAuth/fusionauth-example-template/blob/master/QUICKSTART-INSTRUCTIONS.md for instructions on building out a quickstart. diff --git a/_config.yml b/_config.yml index 073d99be31..e8f64c2545 100644 --- a/_config.yml +++ b/_config.yml @@ -90,7 +90,7 @@ algolia: - adoc - html jekyll-minifier: - exclude: ["*.html","**/swagger*.js","**/swagger*.css"] + exclude: ["*.html","**/swagger*.js","**/swagger*.css","**/mermaid*.js"] uglifier_args: harmony: true jekyll-archives: diff --git a/astro/package-lock.json b/astro/package-lock.json index 835ed6835a..b3ac242685 100644 --- a/astro/package-lock.json +++ b/astro/package-lock.json @@ -353,44 +353,44 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", + "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", - "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.0", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.0", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.2", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -409,11 +409,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", - "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", + "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", "dependencies": { - "@babel/types": "^7.21.0", + "@babel/types": "^7.22.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -447,15 +447,15 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", + "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.9", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -473,63 +473,63 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-plugin-utils": { @@ -541,70 +541,70 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dependencies": { - "@babel/types": "^7.20.2" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", + "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.6", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", + "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-validator-identifier": "^7.22.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -613,9 +613,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", - "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", + "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", "bin": { "parser": "bin/babel-parser.js" }, @@ -656,31 +656,31 @@ } }, "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", - "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.1", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.2", - "@babel/types": "^7.21.2", + "version": "7.22.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", + "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.7", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/types": "^7.22.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -689,12 +689,12 @@ } }, "node_modules/@babel/types": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", - "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", + "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -769,9 +769,9 @@ "integrity": "sha512-8HqW8EVqjnCmWXVpqAOZf+EGESdkR27odcMMMGefgKXtar00SoYNSryGv//TELI4T3QFsECo78p+0lmalk/CFA==" }, "node_modules/@esbuild/android-arm": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.16.tgz", - "integrity": "sha512-gCHjjQmA8L0soklKbLKA6pgsLk1byULuHe94lkZDzcO3/Ta+bbeewJioEn1Fr7kgy9NWNFy/C+MrBwC6I/WCug==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", + "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", "cpu": [ "arm" ], @@ -784,9 +784,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.16.tgz", - "integrity": "sha512-wsCqSPqLz+6Ov+OM4EthU43DyYVVyfn15S4j1bJzylDpc1r1jZFFfJQNfDuT8SlgwuqpmpJXK4uPlHGw6ve7eA==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", + "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", "cpu": [ "arm64" ], @@ -799,9 +799,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.16.tgz", - "integrity": "sha512-ldsTXolyA3eTQ1//4DS+E15xl0H/3DTRJaRL0/0PgkqDsI0fV/FlOtD+h0u/AUJr+eOTlZv4aC9gvfppo3C4sw==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", + "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", "cpu": [ "x64" ], @@ -814,9 +814,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.16.tgz", - "integrity": "sha512-aBxruWCII+OtluORR/KvisEw0ALuw/qDQWvkoosA+c/ngC/Kwk0lLaZ+B++LLS481/VdydB2u6tYpWxUfnLAIw==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", + "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", "cpu": [ "arm64" ], @@ -829,9 +829,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.16.tgz", - "integrity": "sha512-6w4Dbue280+rp3LnkgmriS1icOUZDyPuZo/9VsuMUTns7SYEiOaJ7Ca1cbhu9KVObAWfmdjUl4gwy9TIgiO5eA==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", + "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", "cpu": [ "x64" ], @@ -844,9 +844,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.16.tgz", - "integrity": "sha512-x35fCebhe9s979DGKbVAwXUOcTmCIE32AIqB9CB1GralMIvxdnMLAw5CnID17ipEw9/3MvDsusj/cspYt2ZLNQ==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", + "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", "cpu": [ "arm64" ], @@ -859,9 +859,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.16.tgz", - "integrity": "sha512-YM98f+PeNXF3GbxIJlUsj+McUWG1irguBHkszCIwfr3BXtXZsXo0vqybjUDFfu9a8Wr7uUD/YSmHib+EeGAFlg==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", + "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", "cpu": [ "x64" ], @@ -874,9 +874,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.16.tgz", - "integrity": "sha512-b5ABb+5Ha2C9JkeZXV+b+OruR1tJ33ePmv9ZwMeETSEKlmu/WJ45XTTG+l6a2KDsQtJJ66qo/hbSGBtk0XVLHw==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", + "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", "cpu": [ "arm" ], @@ -889,9 +889,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.16.tgz", - "integrity": "sha512-XIqhNUxJiuy+zsR77+H5Z2f7s4YRlriSJKtvx99nJuG5ATuJPjmZ9n0ANgnGlPCpXGSReFpgcJ7O3SMtzIFeiQ==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", + "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", "cpu": [ "arm64" ], @@ -904,9 +904,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.16.tgz", - "integrity": "sha512-no+pfEpwnRvIyH+txbBAWtjxPU9grslmTBfsmDndj7bnBmr55rOo/PfQmRfz7Qg9isswt1FP5hBbWb23fRWnow==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", + "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", "cpu": [ "ia32" ], @@ -919,9 +919,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.16.tgz", - "integrity": "sha512-Zbnczs9ZXjmo0oZSS0zbNlJbcwKXa/fcNhYQjahDs4Xg18UumpXG/lwM2lcSvHS3mTrRyCYZvJbmzYc4laRI1g==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", + "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", "cpu": [ "loong64" ], @@ -934,9 +934,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.16.tgz", - "integrity": "sha512-YMF7hih1HVR/hQVa/ot4UVffc5ZlrzEb3k2ip0nZr1w6fnYypll9td2qcoMLvd3o8j3y6EbJM3MyIcXIVzXvQQ==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", + "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", "cpu": [ "mips64el" ], @@ -949,9 +949,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.16.tgz", - "integrity": "sha512-Wkz++LZ29lDwUyTSEnzDaaP5OveOgTU69q9IyIw9WqLRxM4BjTBjz9un4G6TOvehWpf/J3gYVFN96TjGHrbcNQ==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", + "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", "cpu": [ "ppc64" ], @@ -964,9 +964,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.16.tgz", - "integrity": "sha512-LFMKZ30tk78/mUv1ygvIP+568bwf4oN6reG/uczXnz6SvFn4e2QUFpUpZY9iSJT6Qpgstrhef/nMykIXZtZWGQ==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", + "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", "cpu": [ "riscv64" ], @@ -979,9 +979,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.16.tgz", - "integrity": "sha512-3ZC0BgyYHYKfZo3AV2/66TD/I9tlSBaW7eWTEIkrQQKfJIifKMMttXl9FrAg+UT0SGYsCRLI35Gwdmm96vlOjg==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", + "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", "cpu": [ "s390x" ], @@ -994,9 +994,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.16.tgz", - "integrity": "sha512-xu86B3647DihHJHv/wx3NCz2Dg1gjQ8bbf9cVYZzWKY+gsvxYmn/lnVlqDRazObc3UMwoHpUhNYaZset4X8IPA==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", + "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", "cpu": [ "x64" ], @@ -1009,9 +1009,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.16.tgz", - "integrity": "sha512-uVAgpimx9Ffw3xowtg/7qQPwHFx94yCje+DoBx+LNm2ePDpQXHrzE+Sb0Si2VBObYz+LcRps15cq+95YM7gkUw==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", + "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", "cpu": [ "x64" ], @@ -1024,9 +1024,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.16.tgz", - "integrity": "sha512-6OjCQM9wf7z8/MBi6BOWaTL2AS/SZudsZtBziXMtNI8r/U41AxS9x7jn0ATOwVy08OotwkPqGRMkpPR2wcTJXA==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", + "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", "cpu": [ "x64" ], @@ -1039,9 +1039,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.16.tgz", - "integrity": "sha512-ZoNkruFYJp9d1LbUYCh8awgQDvB9uOMZqlQ+gGEZR7v6C+N6u7vPr86c+Chih8niBR81Q/bHOSKGBK3brJyvkQ==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", + "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", "cpu": [ "x64" ], @@ -1054,9 +1054,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.16.tgz", - "integrity": "sha512-+j4anzQ9hrs+iqO+/wa8UE6TVkKua1pXUb0XWFOx0FiAj6R9INJ+WE//1/Xo6FG1vB5EpH3ko+XcgwiDXTxcdw==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", + "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", "cpu": [ "arm64" ], @@ -1069,9 +1069,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.16.tgz", - "integrity": "sha512-5PFPmq3sSKTp9cT9dzvI67WNfRZGvEVctcZa1KGjDDu4n3H8k59Inbk0du1fz0KrAbKKNpJbdFXQMDUz7BG4rQ==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz", + "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==", "cpu": [ "ia32" ], @@ -1084,9 +1084,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.16.tgz", - "integrity": "sha512-sCIVrrtcWN5Ua7jYXNG1xD199IalrbfV2+0k/2Zf2OyV2FtnQnMgdzgpRAbi4AWlKJj1jkX+M+fEGPQj6BQB4w==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", + "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", "cpu": [ "x64" ], @@ -2032,9 +2032,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.21.9", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", + "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", "funding": [ { "type": "opencollective", @@ -2043,13 +2043,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001503", + "electron-to-chromium": "^1.4.431", + "node-releases": "^2.0.12", + "update-browserslist-db": "^1.0.11" }, "bin": { "browserslist": "cli.js" @@ -2134,9 +2138,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001458", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz", - "integrity": "sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==", + "version": "1.0.30001517", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz", + "integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==", "funding": [ { "type": "opencollective", @@ -2145,6 +2149,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -3181,9 +3189,9 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.4.311", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.311.tgz", - "integrity": "sha512-RoDlZufvrtr2Nx3Yx5MB8jX3aHIxm8nRWPJm3yVvyHmyKaRvn90RjzB6hNnt0AkhS3IInJdyRfQb4mWhPvUjVw==" + "version": "1.4.476", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.476.tgz", + "integrity": "sha512-gzWl1m8pNy+5Kj17XcziNcbOhripjTqR2wAQmtdlFUngPYuFy7zUpJScVQAvCvQSFHNk3mS5fetNKW6BSpytFg==" }, "node_modules/elkjs": { "version": "0.8.2", @@ -3229,9 +3237,9 @@ "integrity": "sha512-2BMfqBDeVCcOlLaL1ZAfp+D868SczNpKArrTM3dhpd7dK/OVlogzY15qpUngt+LMTq5UC/csb9vVQAgupucSbA==" }, "node_modules/esbuild": { - "version": "0.18.16", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.16.tgz", - "integrity": "sha512-1xLsOXrDqwdHxyXb/x/SOyg59jpf/SH7YMvU5RNSU7z3TInaASNJWNFJ6iRvLvLETZMasF3d1DdZLg7sgRimRQ==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz", + "integrity": "sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -3240,28 +3248,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.16", - "@esbuild/android-arm64": "0.18.16", - "@esbuild/android-x64": "0.18.16", - "@esbuild/darwin-arm64": "0.18.16", - "@esbuild/darwin-x64": "0.18.16", - "@esbuild/freebsd-arm64": "0.18.16", - "@esbuild/freebsd-x64": "0.18.16", - "@esbuild/linux-arm": "0.18.16", - "@esbuild/linux-arm64": "0.18.16", - "@esbuild/linux-ia32": "0.18.16", - "@esbuild/linux-loong64": "0.18.16", - "@esbuild/linux-mips64el": "0.18.16", - "@esbuild/linux-ppc64": "0.18.16", - "@esbuild/linux-riscv64": "0.18.16", - "@esbuild/linux-s390x": "0.18.16", - "@esbuild/linux-x64": "0.18.16", - "@esbuild/netbsd-x64": "0.18.16", - "@esbuild/openbsd-x64": "0.18.16", - "@esbuild/sunos-x64": "0.18.16", - "@esbuild/win32-arm64": "0.18.16", - "@esbuild/win32-ia32": "0.18.16", - "@esbuild/win32-x64": "0.18.16" + "@esbuild/android-arm": "0.18.17", + "@esbuild/android-arm64": "0.18.17", + "@esbuild/android-x64": "0.18.17", + "@esbuild/darwin-arm64": "0.18.17", + "@esbuild/darwin-x64": "0.18.17", + "@esbuild/freebsd-arm64": "0.18.17", + "@esbuild/freebsd-x64": "0.18.17", + "@esbuild/linux-arm": "0.18.17", + "@esbuild/linux-arm64": "0.18.17", + "@esbuild/linux-ia32": "0.18.17", + "@esbuild/linux-loong64": "0.18.17", + "@esbuild/linux-mips64el": "0.18.17", + "@esbuild/linux-ppc64": "0.18.17", + "@esbuild/linux-riscv64": "0.18.17", + "@esbuild/linux-s390x": "0.18.17", + "@esbuild/linux-x64": "0.18.17", + "@esbuild/netbsd-x64": "0.18.17", + "@esbuild/openbsd-x64": "0.18.17", + "@esbuild/sunos-x64": "0.18.17", + "@esbuild/win32-arm64": "0.18.17", + "@esbuild/win32-ia32": "0.18.17", + "@esbuild/win32-x64": "0.18.17" } }, "node_modules/escalade": { @@ -5637,9 +5645,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" }, "node_modules/non-layered-tidy-tree-layout": { "version": "2.0.2", @@ -6732,9 +6740,9 @@ "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" }, "node_modules/rollup": { - "version": "3.26.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.3.tgz", - "integrity": "sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.27.0.tgz", + "integrity": "sha512-aOltLCrYZ0FhJDm7fCqwTjIUEVjWjcydKBV/Zeid6Mn8BWgDCUBBWT5beM5ieForYNo/1ZHuGJdka26kvQ3Gzg==", "bin": { "rollup": "dist/bin/rollup" }, @@ -7765,9 +7773,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", "funding": [ { "type": "opencollective", @@ -7776,6 +7784,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { @@ -7783,7 +7795,7 @@ "picocolors": "^1.0.0" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" diff --git a/astro/public/img/articles/login-failure/login-success-graph.png b/astro/public/img/articles/login-failure/login-success-graph.png new file mode 100644 index 0000000000..fe069edca4 Binary files /dev/null and b/astro/public/img/articles/login-failure/login-success-graph.png differ diff --git a/astro/public/img/icons/login-failures.svg b/astro/public/img/icons/login-failures.svg new file mode 100644 index 0000000000..e82ae49707 --- /dev/null +++ b/astro/public/img/icons/login-failures.svg @@ -0,0 +1,15 @@ + + + login-failures + + + + + + + + + + + + \ No newline at end of file diff --git a/astro/src/components/GitHubEdit.astro b/astro/src/components/GitHubEdit.astro new file mode 100644 index 0000000000..5dd85d95c1 --- /dev/null +++ b/astro/src/components/GitHubEdit.astro @@ -0,0 +1,49 @@ +--- +import type { AstroGlobal } from "astro"; + +/** Gets the URL to edit the page on GitHub */ + +export function getGithubEditUrl(Astro: Readonly) { + const slug = Astro.params?.slug; + const path = Astro.url.pathname; + const splitSlug = slug?.split("/"); + + // Each file layout is unique + let appendFile = ""; + if (path.includes("/articles/")) { + appendFile = splitSlug?.length + ? splitSlug?.length > 1 + ? path.replace(`${slug}`, "") + `${slug}.md` + : path + `index.mdx` + : path; + } else if (path.includes("/dev-tools/")) { + appendFile = splitSlug?.length + ? path.replace(/.$/, `.mdx`) + : path + `index.mdx`; + } else if (path.includes("/quickstarts/")) { + appendFile = splitSlug?.length + ? path.replace("/docs", "").replace(/.$/, `.mdx`) + : path.replace("/docs", ""); + } + return `https://github.com/FusionAuth/fusionauth-site/blob/master/astro/src/content${appendFile}`; +} +--- + +{ + ( + <> +

Contribute

+ + + ) +} diff --git a/astro/src/content/articles/authentication/login-failures.md b/astro/src/content/articles/authentication/login-failures.md new file mode 100644 index 0000000000..d781d118aa --- /dev/null +++ b/astro/src/content/articles/authentication/login-failures.md @@ -0,0 +1,139 @@ +--- +title: Why Login Failures Matter +description: Are you tracking your login failures? Learn about how to track them, why it matters, and what you should do to avoid login failure. +author: Hannah Sutor +section: Authentication +icon: /img/icons/login-failures.svg +--- + +Picture a chart representing user logins. It has a line, trending upwards and to the right. Growing over time, never dipping. + +![No dips here!.](/img/articles/login-failure/login-success-graph.png) + +When you care about providing great [authentication](/docs/v1/tech/core-concepts/authentication-authorization) experiences, like us (the few, the proud), there is nothing better than this chart - undeniable proof that our users are successfully logging in. And, more importantly, getting access to the features or data which that login process protects. That’s what most users are looking for, after all. + +The more people who successfully log in, the more confident we are that our solution can handle a large number of users and that users are able to enter the application smoothly. + +However, do you track login _failures_ as much as you pay attention to login _successes_? At first,it doesn’t sound as exciting. You definitely won’t be hoping for a line up and to the right. Instead, you'll be hoping for a line trending downwards. Or better yet, one never ascending in the first place. + +Tracking login failure rates is just as important, if not more important, than tracking login success numbers. Failures signify users are having difficulty accessing the application, and it’s our job to figure out why. And to fix it. + +## Define Login Failures + +Before you can measure, you have to decide on what you will consider a failure in the login process. A safe assumption is that any failed authentication event should be counted. Authentication is not as simple as a username and password pair, and scenarios around passwordless authentication and multi-factor authentication (MFA) need to be considered as well. If a user attempts to log in, uses their username/password pair successfully, but never completes MFA, this is considered a failure. + +There are some scenarios that are not quite failures, and not quite successes. These are also worth tracking, but require some nuance in instrumentation and reporting. Some examples: + +* User initiates an account recovery flow, but never completes it. +* A magic link email or SMS is sent, but never completed. +* If MFA is required, and user removes the current factor, but never adds another factor. +* A user was rate limited after suspicious behavior or for entering their credentials incorrectly. + +In all cases, the user is denied access to the application, but not in a typical manner. If you aren’t tracking login failures at all, don’t worry about these edge cases. But if you are and want to take the next step in terms of understanding your user’s experience, track these and think about how your user might perceive them. + +## Measuring Login Failure Rates + +The first step in working towards measuring failed authentication attempts is awareness - brought to you by this article! + +Next, walk through what you should be doing:: + +1. **Begin logging login activity, if you aren’t already.** Both successes and failures must be measured to understand the average login success ratio and the trend over time. Here are some common ways to capture this data: + +* [FusionAuth’s login failure webhook](/docs/v1/tech/events-webhooks/events/user-login-failed) fires an event when a login fails due to invalid credentials +* Okta gives admins access to a report that contains failed login information +* Auth0 provides events that give specific reasons why a login failed +* If you are using another provider, consult the documentation +* If you’re using a homegrown identity management system, make sure it includes login failure events and metadata around them + +2. **Be granular.** When a failure occurs, log the reason for the failure and metadata around the event. If you can’t piece together a hypothesis about the failure, you can’t fix it, so this part is really important. Some ideas for attributes to track: + +* User attributes: IP address, user agent/OS, the mapped location of the IP address, time of day, type of login (social sign on, [WebAuthn](/blog/2022/09/13/what-is-webauthn-why-do-you-care), magic link), which factor failed (if using [multi-factor authentication aka MFA](/glossary/multi-factor-authentication)) +* System level events: application version, client version, external factor such as a new source of traffic or promotion +* Remember that an incomplete login should also count as a failure - track these too! + +3. **Patience is key.** You’ll need at least 3 months of solid data before you can start to zoom in to identify meaningful trends. + +4. **Adjust your expectations based on your industry.** While it is difficult to find login failure rates based on your specific industry, they can range between 15-40%, based on the average of the stats between [this article](https://jsoverson.medium.com/what-your-login-success-rate-says-about-your-credential-stuffing-threat-1f10bc20eaee) and [this one](https://learn.fastly.com/rs/025-XKO-469/images/Detecting-Account-Takeovers-and-Defending-Your-Users-Signal-Sciences-2017.pdf). After tracking these numbers for a while, you’ll get a feel for when changes to your applications cause failure rates to change. + +5. **Pass it on.** When building your application, empower application administrators to monitor failure rates themselves. For example, Okta gives admins a report where they can view failures and successes. Most authentication as a service providers offer detailed log events that can be built as a dashboard or report for administrator consumption. + +Now that you know what you should be doing to track failures, let’s talk about why user authentication events fail. + +## Why Logins Fail + +There are a number of reasons why someone fails to log in. These range from system issues like performance to user confusion to obstacles from security measures. + +### Performance + +Technical problems, such as slow response times from the application, cause major user attrition. A[ report by Google](https://blog.google/products/ads-commerce/the-need-for-mobile-speed/) found that 53% of mobile users will leave a website if it takes longer than 3 seconds to load. Even if your application loads within a reasonable amount of time, you need to ensure that your login response is equally as zippy. + + +### Poor UX + +A poor user experience, often marked by unclear instructions and an overwhelming number of input fields, can cause frustration for users and lead to authentication failure. Poor UX can manifest in other ways, too: + +* Not providing an easy way to reset forgotten or lost passwords. When there is no clear way to reset a password or recover a username, users will quickly give up and exit the login flow. Give the user the option to resend recovery emails, and remind them to check spam folders. +* Inconsistent field lengths. When a new user registration form accepts a certain number of characters for the password field, and the login form accepts a different, smaller number, your user can be locked out even if they have correct credentials! Be sure that your field lengths are consistent for each field type, no matter where they are presented. +* Lack of tools for MFA recovery. Don’t forget that many accounts have MFA (we hope). Focusing only on username and password recovery leaves users who have lost their MFA devices unable to access their accounts. Simplify MFA recovery by forcing users to download recovery codes when they first set up MFA. +* Lack of feedback in the UI. Rather than wait for a user to submit the login form, validate and alert them of errors in real-time so that users can correct them quickly rather than wait until they submit the form. + +### Security Measures + +Ah, the age old struggle between security and usability. Those same security features that help to project our application also cause friction for users. A CAPTCHA may make sense if a user is logging in from an unusual IP address, but presents an additional obstacle to the user. + +A common security measure is to make a user click a magic link, sent to them via email or SMS, when a login looks suspicious. Any time a user has to go into another application (in this case, their email client or phone), just to use yours, they are at a higher risk of failed authentication. + +Unnecessary steps in the flow for security purposes will slow down the login process, leading to a higher chance of user attrition and error. Choose security measures wisely. + +An additional benefit of taking a baseline measurement as this article suggests above is that you can know how such measures affect your users. + +### User Problems + +You may do all you can to make the login process seamless for users, but failed attempts are a part of life. Why is that? + +On the other end of your shiny, awesome login form, is a flawed human being. We forget our credentials. We forget if we used Google, Facebook, or LinkedIn to sign in. We entered our username, then got distracted and forgot to come back to the tab. + +I could go on and on. Ultimately, expect that no matter how optimized your login process, there will be some percentage of failure due to the human condition. + + +## Why Be Aware? + +You might ask, why do I care about login failures? + +An authenticated user is more valuable to your business than an unauthenticated one. Once a user is tied to an identity, you can improve their experience: + +* You can personalize your application for them, lowering time to value. +* You can contact them if something goes wrong, or to nudge them back into your product. +* Authenticated users are much more likely to share valuable private data with your application by engaging with it. + +When you improve the percentage of successful logins, you are directly creating business value. + +Authentication is a high stakes, high visibility portion of your application. If a user can’t login, the application is dead in the water. When users can’t log in, they lose trust in your application - not to mention the general sense of annoyance that comes with wanting to access something that you can’t! + +Alerting on login failure rates can give you a heads up that something isn’t right. The sooner you know, the sooner you can do something about it. + +### Choosing Not To Invest In Login Failure Rates + +All things in software (and life) have tradeoffs, and tracking login failures is no exception. You may choose not to invest in this area for the following reasons: + +* **Other priorities with higher ROI**: You’ve done the work to understand what a failed login attempt costs your company, and you’ve determined that there are bigger fish to fry. +* **You’ve hit "good enough"**: There comes a point where you are no longer willing to invest in optimizing your login experience. Even if you had data pointing to issues, you wouldn’t do anything about it. + +## Take Action + +Once you implement tracking, you may determine that you want to do something to improve your login failure rates. Here are some ideas for how to increase successful logins. + +1. **Provide automated help to anyone struggling to log in.** Present tailored advice or reminders in the user experience based on the problem they’re experiencing. An example of this is offering to send a password reset email with one click after a certain number of failed login attempts. Or, if you’re noticing that legitimate-looking users are failing at the captcha step frequently, consider a [CAPTCHA alternative](https://www.w3.org/WAI/GL/wiki/Captcha_Alternatives_and_thoughts). + +2. **Give secure options for account credentials reset.** Once a problem has been detected, offer a login with a security code. Once the user is authenticated, allow them to modify their credentials so that they can remember them. For an added layer of security, send the user an email any time their username or password changes. In case it wasn’t them, they can be alerted of a possible malicious actor and take further steps such as changing their credentials or locking their account. + +3. **Give users options.** Passwordless options, like passkeys and magic links, can replace username and password combinations. You can also provide the ability for users to authenticate with pre-existing accounts using social sign in, SAML, and OAuth2. Since you have metrics captured, you can determine which of these is most effective for your userbase. + +4. **Keep users logged in if they choose.** Ensure your authentication system provides the ability for users to select “Remember me”. Long lived sessions reduce the need to log in, sometimes at the expense of security (tradeoffs, remember!). Administrators choose the maximum length of valid sessions before a user is forced to authenticate again. Here you’ll want to again balance between ease of use and security. + +## In Conclusion + +In the case of login failures, knowledge is power. Instrument your current login success and failure rates with granular data about each outcome. Understand why users are failing to authenticate, and take action accordingly. + +Doing so will lead to the positive business outcomes associated with authenticated users, and maybe some beautiful looking charts, too. + diff --git a/astro/src/layouts/Default.astro b/astro/src/layouts/Default.astro index 21cb6f2baa..479b6cfe4e 100644 --- a/astro/src/layouts/Default.astro +++ b/astro/src/layouts/Default.astro @@ -4,6 +4,7 @@ import CTA from '../components/CTA.astro'; import Head from '../components/Head.astro'; import Header from '../components/Header.astro'; import Navigation from '../components/Navigation.astro'; +import GitHubEdit from '../components/GitHubEdit.astro'; import Search from '../components/Search.astro'; import SectionNavigation from '../components/SectionNavigation.astro'; import TOC from '../components/TOC.astro'; @@ -49,6 +50,9 @@ cta = frontmatter.cta ? frontmatter.cta : cta; + + + diff --git a/astro/src/pages/docs/quickstarts/quickstart-sections.ts b/astro/src/pages/docs/quickstarts/quickstart-sections.ts index 4f7fc1c707..f7e544d766 100644 --- a/astro/src/pages/docs/quickstarts/quickstart-sections.ts +++ b/astro/src/pages/docs/quickstarts/quickstart-sections.ts @@ -178,6 +178,13 @@ const qsSections: QuickStartSection[] = [ faIcon: 'fa-g', navColor: 'blue', }, + { + href: '/docs/v1/tech/tutorials/integrate-express-api', + title: 'Express', + icon: '/img/icons/javascript.svg', + faIcon: 'fa-x', + navColor: 'fuchsia', + }, ], }, ]; diff --git a/site/_data/exampleapps.yaml b/site/_data/exampleapps.yaml index 48ea046759..bbec8d3a01 100644 --- a/site/_data/exampleapps.yaml +++ b/site/_data/exampleapps.yaml @@ -1,6 +1,6 @@ - url: https://github.com/fusionauth/fusionauth-example-gatsby - name: Gatsby OAuth + name: Gatsby OAuth description: An example of using Gatsby with the Authorization Code grant and PKCE language: javascript - url: https://github.com/fusionauth/fusionauth-example-ruby-jwt @@ -52,7 +52,7 @@ description: Creating new tenants in Ruby language: ruby - url: https://github.com/fusionauth/fusionauth-example-node - name: Node OAuth + name: Node OAuth description: Login with the Authorization Code grant language: javascript - url: https://github.com/fusionauth/fusionauth-example-family @@ -68,19 +68,19 @@ description: The Authorization Code grant using the React framework with the FusionAuth React SDK and an Express backend language: javascript - url: https://github.com/fusionauth/fusionauth-example-vue - name: Vue.js + name: Vue.js description: The Authorization Code grant using the Vue.js framework language: javascript - url: https://github.com/fusionauth/fusionauth-example-device-grant - name: Device grant - description: An example of the Device Authorization grant + name: Device grant + description: An example of the Device Authorization grant language: javascript - url: https://github.com/fusionauth/fusionauth-example-angular - name: Angular + name: Angular description: The Authorization Code grant using the Angular framework language: javascript - url: https://github.com/fusionauth/fusionauth-example-java - name: User and application management + name: User and application management description: Using the FusionAuth client library to add and remove users and applications language: java - url: https://github.com/fusionauth/fusionauth-example-password-encryptor @@ -100,7 +100,7 @@ description: Single sign-on with Laravel and FusionAuth language: php - url: https://github.com/fusionauth/fusionauth-example-netcore - name: User management + name: User management description: Managing users via the FusionAuth API language: netcore - url: https://github.com/fusionauth/fusionauth-example-dotnet-api @@ -117,18 +117,18 @@ language: netcore - url: https://github.com/fusionauth/fusionauth-example-asp-netcore name: ASP.NET Core webapp - description: An ASP.NET Core 3.1 web application using FusionAuth as the identity server + description: An ASP.NET Core 3.1 web application using FusionAuth as the identity server language: netcore - url: https://github.com/fusionauth/fusionauth-example-netcore6 name: ASP.NET Core v6 webapp - description: An ASP.NET Core 6 web application using FusionAuth as the identity server + description: An ASP.NET Core 6 web application using FusionAuth as the identity server language: netcore - url: https://github.com/fusionauth/fusionauth-example-asp-netcore5 name: ASP.NET Core 5.0 webapp - description: An ASP.NET Core 5.0 web application using FusionAuth as the identity server + description: An ASP.NET Core 5.0 web application using FusionAuth as the identity server language: netcore - url: https://github.com/fusionauth/fusionauth-example-kickstart - name: Kickstart + name: Kickstart description: Examples of Kickstart, a way to configure FusionAuth at startup language: config - url: https://github.com/FusionAuth/fusionauth-theme-helper @@ -144,11 +144,11 @@ description: Theming example using Kickstart language: config - url: https://github.com/FusionAuth/fusionauth-contrib - name: External application configuration + name: External application configuration description: Community supported application configuration (for proxies, etc) language: config - url: https://github.com/fusionauth/fusionauth-containers - name: Container configuration + name: Container configuration description: Community supported container configuration (for kubernetes, etc) language: config - url: https://github.com/fusionauth/fusionauth-example-python-django @@ -173,14 +173,14 @@ language: javascript - url: https://github.com/FusionAuth/fusionauth-example-node-services-gateway name: Microservices gateway - description: API gateway and microservices + description: API gateway and microservices language: javascript - url: https://github.com/FusionAuth/fusionauth-example-python-flask - name: Flask OAuth + name: Flask OAuth description: Login with the Authorization Code grant language: python - url: https://github.com/fusionauth/fusionauth-example-go - name: Golang OAuth + name: Golang OAuth description: Login with the Authorization Code grant language: go - url: https://github.com/fusionauth/fusionauth-example-php-connector @@ -188,7 +188,7 @@ description: Updating a legacy PHP app to OAuth and migrating users language: php - url: https://github.com/FusionAuth/fusionauth-example-python-hotspot - name: Wifi Hotspot + name: Wifi Hotspot description: Controlling a hotspot via FusionAuth language: python - url: https://github.com/FusionAuth/fusionauth-example-node-services-gateway-jwtauth @@ -196,11 +196,11 @@ description: API gateway and microservices secured using JWT auth language: javascript - url: https://github.com/FusionAuth/fusionauth-example-node-multi-tenant - name: Multi-tenant application + name: Multi-tenant application description: Two nodejs applications in different tenants, living in different domains. language: javascript - url: https://github.com/FusionAuth/fusionauth-import-scripts - name: Import scripts + name: Import scripts description: Example import scripts to ease migration. language: ruby - url: https://github.com/FusionAuth/fusionauth-example-flutter-dart @@ -259,6 +259,10 @@ name: Next.js Single Sign-On description: Single sign-on with Next.js and FusionAuth language: javascript +- url: https://github.com/FusionAuth/fusionauth-example-express-api + name: Express API + description: Express api which uses the Cookie Access Token + language: javascript - url: https://github.com/fusionauth/fusionauth-example-angular-guide name: Angular with the hosted backend description: The Authorization Code grant using the Angular framework with the FusionAuth Angular SDK and the hosted backend diff --git a/site/_includes/_head.liquid b/site/_includes/_head.liquid index 9c51481d7e..1d7ab06681 100644 --- a/site/_includes/_head.liquid +++ b/site/_includes/_head.liquid @@ -95,6 +95,7 @@ +