+ ```
+
+If the user is not logged in and clicks the `Login` link, they will be taken to the `AccountController` triggering the `Login` function. This function will take the values in the settings and issue the login dialog for the user.
+
+```c#
+public async Task Login(string returnUrl = "/")
+ {
+ var authenticationProperties = new AuthenticationProperties();
+ authenticationProperties.RedirectUri = returnUrl;
+
+ await HttpContext.ChallengeAsync("FusionAuth", authenticationProperties);
+ }
+```
+After the user is authenticated, it redirects them to the homepage again. This time they will be authenticated and will be presented with the `Profile` and `Logout` links.
+
+The `Logout` link will again take the user to the `AccountController` and perform the logout logic.
+
+```c#
+public async Task Logout()
+{
+ var authenticationProperties = new AuthenticationProperties();
+ authenticationProperties.RedirectUri = Url.Action("Index", "Home");
+
+ await HttpContext.SignOutAsync("FusionAuth", authenticationProperties);
+ await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
+}
+```
+
+The `Profile` link will take to user to the `AccountController` and attempt to return the `Profile` view. Notice the `Authorize` attribute above the function name. This attribute lets the application know not to issue this view unless the user is authenticated.
+
+```c#
+[Authorize]
+public IActionResult Profile()
+{
+ return View(User);
+}
+```
+
+For this template, the `Profile` simply returns some claims. However, in your application, this is where your secured application would start.
+
+
+
+## Conclusion
+Authentication and Authorization are a critical part of any application. You could create that all from scratch, but it often does not make sense to do so. When you decide to use FusionAuth, you could also create that integration from scratch as demonstrated in many of [FusionAuth's Quickstarts](/docs/quickstarts/). However, you don't need to. The point of the templates is to reduce the amount of time and overhead spent plumbing the application so you can concentrate on creating the parts of it that separate you from your competition. I hope the next time you sit down to write your latest and greatest .NET application you choose to utilize the power of the FusionAuth .NET Templates.
+
+## Next steps
+
+If you enjoyed this article, I suggest you download the FusionAuth .NET Templates and create your project with them. Please check out some of the other links and resources about FusionAuth and the .NET Templates.
+
+* [Download FusionAuth for Free](/download)
+* [FusionAuth .NET Templates in Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=FusionAuth.FusionAuthVSTemplates)
+* [FusionAuth .NET Templates in NuGet](https://www.nuget.org/packages/FusionAuth.Templates)
+* [FusionAuth - Getting Started](/docs/v1/tech/getting-started/)
+
diff --git a/astro/src/content/blog/fusionauth-longhornphp-2023.mdx b/astro/src/content/blog/fusionauth-longhornphp-2023.mdx
new file mode 100644
index 0000000000..703e6cafcc
--- /dev/null
+++ b/astro/src/content/blog/fusionauth-longhornphp-2023.mdx
@@ -0,0 +1,44 @@
+---
+publish_date: 2023-10-25
+title: "We'll see you at Longhorn PHP 2023"
+description: FusionAuth will be at Longhorn PHP. Say hi!
+authors: Dan Moore
+image: /img/blogs/longhorn-php-2023/longhorn-php-2023-event.png
+categories: Events
+tags: events, longhornphp, conference
+excerpt_separator: "{/* more */}"
+---
+
+Longhorn PHP is a long running community driven PHP conference taking place in Austin, Texas next week. I will be presenting and would love to see you there.
+
+{/* more */}
+
+## Why I am attending
+
+I was selected to give two different sessions, [one on JWTs](https://www.longhornphp.com/sessions#what-php-developers-need-to-know-about-jwts) and a [workshop on protecting your APIs](https://www.longhornphp.com/sessions#protecting-your-apis). I'm especially excited about the hands-on workshop, where users will, using a [web based training platform](https://instruqt.com/), explore various options of protecting an API written in PHP.
+
+For this workshop, we'll start with an unprotected Chuck Norris joke API. (A sample joke: "Chuck Norris makes onions cry."). Participants will then protect the API with a variety of methods, ending up with an API protected with an OAuth2 access token issued by an authorization server.
+
+I also look forward to connecting with the PHP community. I've worked in PHP off and on for decades. I wrote a raw PHP app in the early 2000s for a book club. I supported a local food directory in CakePHP for over a decade. And I've worked professionally with PHP solutions like Wordpress and Drupal.
+
+But I'm less familiar with more modern PHP frameworks and solutions like Laravel. When I've glanced at them, I've thought "that looks a lot like Rails" and my heart warms. So this is a great chance for me to learn more about what PHP folks are working on nowadays
+
+In particular, I'm looking forward to [Serializing Modern PHP](https://www.longhornphp.com/sessions#serializing-modern-php) and [Minimal vs. functional: “Clean” code as a practical – rather than aesthetic – virtue](https://www.longhornphp.com/sessions#minimal-vs-functional-clean-code-as-a-practical---rather-than-aesthetic---virtue), but there are of course a number of great sessions.
+
+## Community conferences
+
+It's great to be able to give talks about topics I'm interested in, but I'm also attending because community driven conferences are fantastic. We need more of them.
+
+* They're entry points for attendees into the wider developer community, especially newer developers
+* There are fewer developers than at bigger conferences, but the attendees are more engaged
+* You can interact with developers and users in a far more personal and high-bandwidth fashion
+* They're an important step on the ladder for newer speakers; more professional than a meetup, less intimidating than a large conference like Re:Invent or KubeCon
+
+We lost a lot of these events during the last few years. Community conferences are difficult to run, and require buckets of volunteer time and money. In my experience, no one does a community conference for the money.
+
+I'm glad I can attend Longhorn PHP and hope you can too. There are still [tickets available](https://ti.to/longhorn-php/longhorn-php-2023), including a virtual only option.
+
+## Meet up
+
+If you want to meet up with me at Longhorn PHP, I'll be around! Ping me on [LinkedIn](https://www.linkedin.com/in/mooreds/) or [Twitter/X](https://twitter.com/mooreds), or [fill out our contact form](/contact) and I'll see it.
+
diff --git a/astro/src/content/quickstarts/quickstart-golang-api.mdx b/astro/src/content/quickstarts/quickstart-golang-api.mdx
index 13b04b910c..229171ba5f 100644
--- a/astro/src/content/quickstarts/quickstart-golang-api.mdx
+++ b/astro/src/content/quickstarts/quickstart-golang-api.mdx
@@ -94,7 +94,7 @@ go run main.go
You can then follow the instructions in the Run the API section started at Get a Token.
-To create the application from scratch, make a directory for this API.
+To create the application from scratch, make a directory for this API.
```
mkdir your-application && cd your-application
@@ -194,7 +194,7 @@ There is a lot of code in this function. Let's break it down:
Now, you will add the code to set the public key. This function will accept the key Id from the token and call the authorization server to get the public key with that key Id and put it in the proper format to be used.
'
```
-The response should look look similar to below, however it has been formatted here for readability:
+The response should look similar to below, however it has been formatted here for readability:
```json
{
@@ -340,7 +340,7 @@ curl --location 'http://localhost:9001/make-change?total=3.24' \
--header 'Authorization: Bearer '
```
-The response should look look similar to below, however it has been formatted here for readability:
+The response should look similar to below, however it has been formatted here for readability:
```json
{
diff --git a/astro/src/content/quickstarts/quickstart-javascript-remix-web.mdx b/astro/src/content/quickstarts/quickstart-javascript-remix-web.mdx
new file mode 100644
index 0000000000..795d6df769
--- /dev/null
+++ b/astro/src/content/quickstarts/quickstart-javascript-remix-web.mdx
@@ -0,0 +1,315 @@
+---
+title: Remix
+description: Quickstart integration of Javascript Remix web application with FusionAuth
+navcategory: getting-started
+prerequisites: Node.js version 18
+section: web
+technology: Remix
+language: Javascript
+icon: /img/icons/remix.svg
+faIcon: fa-node-js
+color: green
+cta: EmailListCTA
+---
+
+import Aside from '/src/components/Aside.astro';
+import LoginAfter from '../../diagrams/quickstarts/login-after.astro';
+import LoginBefore from '../../diagrams/quickstarts/login-before.astro';
+import RemoteCode from '/src/components/RemoteCode.astro';
+
+In this quickstart, you will build an application with Remix and integrate it with FusionAuth. The application is for [ChangeBank](https://www.youtube.com/watch?v=pkH-kD73QUM), a global leader in converting dollars into coins. It will have areas reserved for logged in users and public-facing sections.
+
+Find the Docker Compose file and source code for the complete application at https://github.com/FusionAuth/fusionauth-quickstart-javascript-remix-web.
+
+## Prerequisites
+
+For this Quickstart, you'll need:
+
+* [Node 18](https://nodejs.org/en/download) or later.
+* [Docker](https://www.docker.com), which is the quickest way to start FusionAuth. (There are [other ways](/docs/v1/tech/installation-guide/)).
+
+## General Architecture
+
+While this sample application doesn't have login functionality without FusionAuth, a more typical integration will replace an existing login system with FusionAuth.
+
+In that case, the system might look like this before FusionAuth is introduced.
+
+
+
+The login flow will look like this after FusionAuth is introduced.
+
+
+
+In general, you would introduce FusionAuth to normalize and consolidate user data, making it consistent and up-to-date and offloading your login security and functionality to FusionAuth.
+
+## Getting Started
+
+Start with getting FusionAuth up and running and creating a new Remix application.
+
+### Clone The Code
+
+First, grab the code from the repository and change into that folder.
+
+```
+git clone https://github.com/FusionAuth/fusionauth-quickstart-javascript-remix-web.git
+cd fusionauth-quickstart-javascript-remix-web
+```
+
+All shell commands in this guide can be entered in a terminal in this folder. On Windows, you need to replace forward slashes with backslashes in paths.
+
+All the files you'll create in this guide already exist in the `complete-application` subfolder, if you prefer to copy them.
+
+### Run FusionAuth Via Docker
+
+You'll find a Docker Compose file `docker-compose.yml` and an environment variables configuration file `.env` in the root folder of the repository.
+
+Assuming you have Docker installed on your machine, you can start FusionAuth on your machine with the following.
+
+```
+docker compose up -d
+```
+
+This will start three containers, one each for FusionAuth, Postgres, and Elasticsearch.
+
+Here you are using a bootstrapping feature of FusionAuth, called [Kickstart](/docs/v1/tech/installation-guide/kickstart). When FusionAuth starts for the first time, it will look at the `kickstart/kickstart.json` file and configure FusionAuth to your specified state.
+
+
+
+FusionAuth will be configured with these settings:
+
+* Your client Id is `e9fdb985-9173-4e01-9d73-ac2d60d1dc8e`.
+* Your client secret is `super-secret-secret-that-should-be-regenerated-for-production`.
+* Your example username is `richard@example.com` and the password is `password`.
+* Your admin username is `admin@example.com` and the password is `password`.
+* The base URL of FusionAuth is `http://localhost:9011/`.
+
+You can log in to the [FusionAuth admin UI](http://localhost:9011/admin) and look around if you want to, but with Docker and Kickstart, everything will already be configured correctly.
+
+
+
+### Create A Basic Remix Application
+
+Next, you'll set up a basic Remix app. While this guide builds a new Remix project, you can use the same method to integrate your existing project with FusionAuth.
+
+Create the default Remix starter project.
+
+```shell
+npx create-remix@latest mysite
+```
+
+If `create-remix` isn't on your machine, npx will prompt you to install it. Confirm the installation with a `y` input.
+
+Choose the following options:
+- Just the basics
+- Remix App Server
+- TypeScript
+- Yes (to running `npm install`)
+
+Add additional npm packages the site will use using the commands below.
+
+```shell
+cd mysite
+npm install dotenv remix-auth remix-auth-oauth2 jwt-decode
+```
+
+The two Remix authentication packages allow you to use FusionAuth without needing to know how OAuth works. The JWT package will provide your app with the user details returned from FusionAuth. The `dotenv` package allows the app to read configuration details from a `.env` environment file.
+
+Now create the `.env` file in your `mysite` folder and add the following to it (note that this is a different environment file to the one in the root folder used by Docker for FusionAuth).
+
+
+
+### Preliminary Setup
+
+Before you configure authentication, you need to change the default files created by Remix.
+
+Replace the contents of the file `mysite/app/root.tsx` with the following code.
+
+
+
+This is what these changes do:
+- Add some styling with `import css from "~/css/changebank.css";` at the top.
+- Specify the `` content for the page (title and CSS link) in the two functions at the bottom.
+
+At the top of the file `mysite/app/entry.server.tsx`, add the following line.
+
+```tsx
+import 'dotenv/config';
+```
+
+This allows any other file run on the server to use settings from `.env`.
+
+## Authentication
+
+Authentication in Remix requires two parts:
+
+- An Authenticator service to handle communication with FusionAuth.
+- Routes (login, logout, callback) that talk to the Authenticator.
+
+### Services
+
+The `app` folder in the `mysite` project holds all your code. The `routes` folder is a reserved word in Remix, and contains your application's pages. Let's make a `services` folder to keep your authentication code separate.
+
+```shell
+mkdir app/services
+```
+
+In this `services` folder, add a file called `session.server.ts` and copy in the following code (this guide follows the example from the [Remix Auth README](https://github.com/sergiodxa/remix-auth)).
+
+
+
+This code provides a way for Remix to store cookies that maintain the user's session. (If you'd prefer to use file-based sessions instead of cookie-based, you can read about it in an earlier [blog post about using Remix](/blog/remix-demo).)
+
+Next, create an authentication file in the `services` folder, `auth.server.ts`, that uses the session provider you just created.
+
+
+
+In the line `new Authenticator`, you can specify which user details you want to keep in the session. This example uses a single string containing the user's email, but you could define an object with more details or just a user Id.
+
+Note that the `User` must have a value. If the Authenticator returns nothing to store in the session, then a user will not stay logged in.
+
+In `authOptions`, you specify the FusionAuth URLs stored in the `.env` file, which match those created by Kickstart when you ran the Docker command to start FusionAuth.
+
+Finally, `authStrategy` returns the user's email, decoded from the JWT returned by FusionAuth.
+
+### Routes
+
+First replace the homepage of your app in `mysite/app/routes/_index.tsx` with the following code.
+
+
+
+Remix extends React with a few more custom elements that automatically hide the difference between client and server from the programmer. For example, the line `Login` allows Remix to load the linked page in the background without a separate page refresh.
+
+If you have not worked with React before, there are a few differences from normal HTML to note:
+
+- The `class` attribute is replaced by `className`, as `class` is a reserved word in JavaScript.
+- To add JavaScript values into your HTML, you wrap the value in `{ }`.
+- The `style` values are not strings but object literals in braces, wrapped in more braces.
+
+The `_index.tsx` file imports the Authenticator service you created in the previous section, checks if the user has a session, and redirects the user to their profile if they do. This `isAuthenticated` function does not call FusionAuth but checks the user's cookie instead.
+
+
+
+The link you created looks for a login route, so let's code it. Create the file `mysite/app/routes/login.tsx` and add the following code to it.
+
+
+
+This route is purely server-side, as it exports no default function. Instead, the GET loader function redirects the user to FusionAuth. (The user will automatically be logged in without FusionAuth if they already have a session cookie in their browser).
+
+Now create the file `mysite/app/routes/logout.tsx` and add the following code to it.
+
+
+
+When a user browses to this route, they will be logged out by the Authenticator clearing their session, and redirected to the home page.
+
+The final route to create is `mysite/app/routes/auth.callback.tsx`.
+
+
+
+This is where FusionAuth is configured to direct the user after authentication. It may look like this code is doing yet another authentication with `authenticator.authenticate`, but the Authenticator will already have created a session for the user, so no call to FusionAuth will be made here. It is just a way to direct the user to the appropriate page after login.
+
+
+
+## Customization
+
+Now that authentication is done, the last task is to create two example pages that a user can access only when logged in.
+
+Copy over some CSS and an image from the example app.
+
+```shell
+mkdir app/css
+cp ../complete-application/app/css/changebank.css ./app/css/changebank.css
+cp ../complete-application/public/money.jpg ./public/money.jpg
+```
+
+Add the account page `mysite/app/routes/account.tsx` with the following code.
+
+
+
+The `loader` function at the top of the page prohibits the user from viewing this page if they are not authenticated. Any page you create that needs the user to be authenticated requires this function.
+
+The line `const email: string = useLoaderData();` provides whatever data the loader function returns for use in the HTML. It's used in the line `
{email}
`.
+
+The final page you need is `mysite/app/routes/change.tsx`, with the following code.
+
+
+
+This page has identical Remix and authentication functionality to the Account page and some pure React code that updates the DOM whenever the state changes.
+
+## Run The Application
+
+Start the Remix server from the root `mysite` directory.
+
+```shell
+npm run dev
+```
+
+You can now browse to [the app](http://localhost:3000).
+
+Log in using `richard@example.com` and `password`. The change page will allow you to enter a number. Log out and verify that you can't browse to the [account page](http://localhost:3000/account).
+
+## Next Steps
+
+This quickstart is a great way to get a proof of concept up and running quickly, but to run your application in production, there are some things you're going to want to do.
+
+### FusionAuth Customization
+
+FusionAuth gives you the ability to customize just about everything to do with the user's experience and the integration of your application. This includes:
+* [Hosted pages](/docs/v1/tech/themes/) such as login, registration, email verification, and many more.
+* [Email templates](/docs/v1/tech/email-templates/email-templates).
+* [User data and custom claims in access token JWTs](/articles/tokens/jwt-components-explained).
+
+### Security
+
+* You may want to customize the [token expiration times and policies](/docs/v1/tech/oauth/#configure-application-oauth-settings) in FusionAuth.
+* Choose [password rules](/docs/v1/tech/core-concepts/tenants#password) and a [hashing algorithm](/docs/v1/tech/reference/password-hashes) that meet your security needs.
+
+### Tenant And Application Management
+
+* Model your application topology using [Applications](/docs/v1/tech/core-concepts/applications), [Roles](/docs/v1/tech/core-concepts/roles), [Groups](/docs/v1/tech/core-concepts/groups), [Entities](/docs/v1/tech/core-concepts/groups), and more.
+* Set up [MFA](/docs/v1/tech/guides/multi-factor-authentication), [Social login](/docs/v1/tech/identity-providers/), or [SAML](/docs/v1/tech/identity-providers/samlv2/) integrations.
+* Integrate with external systems using [Webhooks](/docs/v1/tech/events-webhooks/), [SCIM](/docs/v1/tech/core-concepts/scim), and [Lambdas](/docs/v1/tech/lambdas/).
+
+### Remix Authentication
+
+- [Remix Docs](https://remix.run/docs)
+- [Passport.js authentication concepts](https://www.passportjs.org/concepts/authentication/downloads/html/)
+- [Remix Auth](https://github.com/sergiodxa/remix-auth)
+- [Remix-Auth-Oauth2 Docs](https://github.com/sergiodxa/remix-auth-oauth2)
+
+
+## Troubleshooting
+
+* I get "This site can’t be reached localhost refused to connect" when I click the login button.
+
+Ensure FusionAuth is running in the Docker container. You should be able to log in as the admin user `admin@example.com` with a password of `password` at [http://localhost:9011/admin](http://localhost:9011/admin).
+
+* It still doesn't work.
+
+You can always pull down a complete running application and compare what's different.
+
+```
+git clone https://github.com/FusionAuth/fusionauth-quickstart-javascript-remix-web.git
+cd fusionauth-quickstart-javascript-remix-web
+docker compose up -d
+cd complete-application
+npm install
+npm run dev
+```
diff --git a/astro/src/content/quickstarts/quickstart-react-native.mdx b/astro/src/content/quickstarts/quickstart-react-native.mdx
new file mode 100644
index 0000000000..d9da73eda2
--- /dev/null
+++ b/astro/src/content/quickstarts/quickstart-react-native.mdx
@@ -0,0 +1,229 @@
+---
+title: React Native
+description: Quickstart integration of React Native application with FusionAuth
+navcategory: getting-started
+prerequisites: Node, npx, Android Studio and/or Xcode
+section: native
+technology: React Native
+language: JavaScript
+icon: /img/icons/react.svg
+faIcon: fa-r
+color: indigo
+cta: EmailListCTA
+---
+import Aside from '../../components/Aside.astro';
+import IconButton from '../../components/IconButton.astro';
+import LoginAfter from '../../diagrams/quickstarts/login-after.astro';
+import LoginBefore from '../../diagrams/quickstarts/login-before.astro';
+import RemoteCode from '../../components/RemoteCode.astro';
+import RemoteValue from '../../components/RemoteValue/RemoteValue.astro';
+export const GITHUB_URL = 'https://raw.githubusercontent.com/FusionAuth/fusionauth-quickstart-react-native/main/';
+
+In this quickstart you are going to build an application with React Native and integrate it with FusionAuth.
+You'll be building it for [ChangeBank](https://www.youtube.com/watch?v=CXDxNCzUspM), a global leader in converting dollars into coins.
+It'll have areas reserved for users who have logged in as well as public facing sections.
+
+The docker compose file and source code for a complete application are available at
+https://github.com/FusionAuth/fusionauth-quickstart-react-native
+
+## Prerequisites
+
+- [Node](https://nodejs.org): This will be used to set up your project.
+- [Docker](https://www.docker.com): The quickest way to stand up FusionAuth. (There are [other ways](/docs/v1/tech/installation-guide/)).
+- To test on Android devices, you can either connect a physical device or [Android Studio](https://developer.android.com/studio) to set up an emulator.
+- To test on iOS devices, you'll need a Mac and install [Xcode](https://developer.apple.com/xcode/) to set up an emulator.
+
+This app has been tested with React Native 0.72.4 and Node 20. This example should work with other compatible versions of React Native.
+
+## General Architecture
+
+While this sample application doesn't have login functionality without FusionAuth, a more typical integration will replace an existing login system with FusionAuth.
+
+In that case, the system might look like this before FusionAuth is introduced.
+
+
+
+The login flow will look like this after FusionAuth is introduced.
+
+
+
+In general, you are introducing FusionAuth in order to normalize and consolidate user data. This helps make sure it is consistent and up-to-date as well as offloading your login security and functionality to FusionAuth.
+
+## Getting Started
+
+In this section, you'll get FusionAuth up and running and use `npx` to create a new application.
+
+### Clone the Code
+
+First off, grab the code from the repository and change into that directory.
+
+```
+git clone https://github.com/FusionAuth/fusionauth-quickstart-react-native.git
+cd fusionauth-quickstart-react-native
+```
+
+### Run FusionAuth via Docker
+
+In the root directory of the repo you'll find a Docker compose file (`docker-compose.yml`) and an environment variables configuration file (`.env`). Assuming you have Docker installed on your machine, you can stand up FusionAuth up on your machine with:
+
+```
+docker compose up -d
+```
+
+Here you are using a bootstrapping feature of FusionAuth, called [Kickstart](/docs/v1/tech/installation-guide/kickstart). When FusionAuth comes up for the first time, it will look at the `kickstart/kickstart.json` file and configure FusionAuth to a certain initial state.
+
+
+
+FusionAuth will be initially configured with these settings:
+
+* Your client Id is
+* Your client secret is .
+* Your example username is and the password is .
+* Your admin username is and the password is .
+* The base URL of FusionAuth `http://localhost:9011/`.
+
+You can log into the [FusionAuth admin UI](http://localhost:9011/admin) and look around if you want, but with Docker/Kickstart you don't need to.
+
+### Expose your Instance
+
+To make the FusionAuth instance running on your machine accessible to the app, you need to [expose it to the Internet following these instructions](/docs/v1/tech/developer-guide/exposing-instance). Then, copy the address `ngrok` gave you as you'll need it shortly. It looks something like `https://SOME-RANDOM-STRINGS.ngrok-free.app`.
+
+### Create your React Native Application
+
+Now you're going to create a React Native application. While this section builds a simple React Native application, you can use the same configuration to integrate your existing React Native application with FusionAuth.
+To make things easier, you're going to use `create-expo-app`, a library that sets up the environment using [Expo](https://docs.expo.dev/), a platform that runs natively on all your users' devices
+
+```shell
+npx create-expo-app my-react-native-app && cd my-react-native-app
+```
+
+You'll have to create all files in the root directory for your application.
+
+
+
+## Authentication
+
+We'll use the [Expo AuthSession library](https://docs.expo.dev/versions/latest/sdk/auth-session/), which simplifies integrating with FusionAuth and creating a secure web application.
+
+### Configure Expo AuthSession
+
+Install `expo-auth-session`, its dependency `expo-crypto` to handle cryptographic operations and `expo-web-browser` to interact with the device Browser in order to log the user in or out.
+
+```shell
+npx expo install expo-auth-session expo-crypto expo-web-browser
+```
+
+Create a `.env` file to hold information about your FusionAuth instance and application, replacing the value in `EXPO_PUBLIC_FUSIONAUTH_URL` with the address you copied from `ngrok` when [exposing your instance](#expose-your-instance).
+
+
+
+Replace `app.json` with the contents below to add some details about your app:
+- A `scheme` that will be used when redirecting back to your application after logging in and out of FusionAuth.
+- The package name for both Android (`expo.android.package`) and iOS (`expo.ios.bundleIdentifier`) builds.
+
+
+
+## App Customization
+
+In this section, you'll turn your application into a trivial banking application with some styling.
+
+### Add Styling
+
+First, run the command below to install some libraries needed for theming.
+
+```shell
+npm install expo-image expo-constants react-native-currency-input
+```
+
+Instead of using CSS, React Native has its own concept of [stylesheets](https://reactnative.dev/docs/stylesheet). Create a file named `changebank.style.js` with the contents below to style your ChangeBank app.
+
+
+
+Run the command below to download the ChangeBank logo into the `assets` folder.
+
+```shell
+wget -O assets/changebank.svg https://raw.githubusercontent.com/FusionAuth/fusionauth-quickstart-react-native/main/complete-application/assets/changebank.svg
+```
+
+## Finish Setting up the App
+
+Replace the existing `App.js` to integrate `expo-auth-session`, add the ChangeBank template, and stitch everything up.
+
+
+
+## Run the App
+
+Depending on where you want to test your app, follow these instructions.
+- For Android devices: you can either [connect a physical device](https://developer.android.com/studio/run/device) or install [Android Studio](https://developer.android.com/studio) to [set up an emulator](https://developer.android.com/studio/run/emulator).
+- For iOS devices: if you are running a Mac, you can install [Xcode](https://developer.apple.com/xcode/) to [set up an emulator or run on a physical device](https://developer.apple.com/documentation/xcode/running-your-app-in-simulator-or-on-a-device/).
+
+Now that you have a device connected or an emulator running, start up the React Native application from the root `my-react-native-app` directory using the command below.
+
+```shell
+npx expo start
+```
+
+After waiting a few moments, you should see a QR Code and a menu with some actions. Right below the QR Code, you'll see a message like this one _(the real address may vary)_.
+
+```
+› Metro waiting on exp://192.168.1.2:8081
+```
+
+To use [Expo Go](https://docs.expo.dev/get-started/expo-go/), a client for testing your apps on Android and iOS devices without building anything locally, you need to:
+
+* Copy that listening address (`exp://192.168.1.2:8081`).
+* Navigate to your FusionAuth instance on [localhost:9011](http://localhost:9011).
+* Log in with the email `admin@example.com` and password `password`.
+* Browse to **Applications**.
+* Click on in your `ExampleReactNativeApp` to edit it.
+* Go to the **OAuth** tab.
+* Add that address to **Authorized redirect URLs** and append `/--/redirect` to it
+ * Example: for `exp://192.168.1.2:8081`, you'd need to add `exp://192.168.1.2:8081/--/redirect` as a redirect URL
+* Click on to save your changes.
+
+Go back to the terminal with the Expo menu. To test on the connected or emulated Android device, press `a`. Otherwise, press `i` to run on the iOS device.
+
+Wait a few seconds and Expo will build and install the app in your device. You should then see the ChangeBank welcome page. Click the `Log in` button in the top right corner of that screen.
+
+
+
+You'll finally arrive at the FusionAuth login screen. Fill in and and click on `Submit` to be redirected back to the logged-in ChangeBank page.
+
+## Next Steps
+This quickstart is a great way to get a proof of concept up and running quickly, but to run your application in production, there are some things you're going to want to do.
+
+### FusionAuth Customization
+FusionAuth gives you the ability to customize just about everything with the user's experience and your application's integration. This includes
+* [Hosted pages](/docs/v1/tech/themes/) such as login, registration, email verification, and many more
+* [Email templates](/docs/v1/tech/email-templates/email-templates)
+* [User data and custom claims in access token JWTs](/articles/tokens/jwt-components-explained)
+
+### Security
+* [Expo AuthSession](https://docs.expo.dev/versions/latest/sdk/auth-session/) handles token validation and refresh
+* You may want to customize the [token expiration times and policies](/docs/v1/tech/oauth/#configure-application-oauth-settings) in FusionAuth
+* Choose [password rules](/docs/v1/tech/core-concepts/tenants#password) and a [hashing algorithm](/docs/v1/tech/reference/password-hashes) that meet your security needs
+
+### Tenant and Application Management
+* Model your application topology using [Applications](/docs/v1/tech/core-concepts/applications), [Roles](/docs/v1/tech/core-concepts/roles), [Groups](/docs/v1/tech/core-concepts/groups), [Entities](/docs/v1/tech/core-concepts/groups), and more
+* Set up [MFA](/docs/v1/tech/guides/multi-factor-authentication), [Social login](/docs/v1/tech/identity-providers/), and/or [SAML](/docs/v1/tech/identity-providers/samlv2/) integrations
+* Integrate with external systems using [Webhooks](/docs/v1/tech/events-webhooks/), [SCIM](/docs/v1/tech/core-concepts/scim), and [Lambdas](/docs/v1/tech/lambdas/)
+
+### Build your App for Distribution
+
+Follow [Expo's "Create your first build" tutorial](https://docs.expo.dev/build/setup/) to learn how to create a build for your app.
+
+## Troubleshooting
+
+* I keep receiving an `invalid_redirect_uri` when running the app with Expo Go
+
+Make sure you have updated the **Authorized redirect URLs** in your [FusionAuth instance](http://localhost:9011) like shown on the [Run the App](#run-the-app) step.
diff --git a/astro/src/css/style.css b/astro/src/css/style.css
index a431f9a92e..45780dd6a8 100644
--- a/astro/src/css/style.css
+++ b/astro/src/css/style.css
@@ -4,4 +4,9 @@
.font-mono{
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+}
+
+lite-youtube{
+ @apply aspect-video;
+ max-width: none;
}
\ No newline at end of file
diff --git a/astro/src/heroes/DocLanding.astro b/astro/src/heroes/DocLanding.astro
index 9966f2387e..36ed12dd08 100644
--- a/astro/src/heroes/DocLanding.astro
+++ b/astro/src/heroes/DocLanding.astro
@@ -11,8 +11,8 @@ const appTypes = [
},
{
"title": "Single-page App",
- "description": "Javascript web app that runs in the browser",
- "footer": "e.g. Angular, React, Remix",
+ "description": "JavaScript web app that runs in the browser",
+ "footer": "e.g. Angular, React, Vue",
"icon": "/img/icons/dl-single-page-app.svg",
"href": "/docs/quickstarts/#spa"
},
diff --git a/astro/src/pages/docs/quickstarts/quickstart-sections.ts b/astro/src/pages/docs/quickstarts/quickstart-sections.ts
index 901b81a2ca..731b19dd94 100644
--- a/astro/src/pages/docs/quickstarts/quickstart-sections.ts
+++ b/astro/src/pages/docs/quickstarts/quickstart-sections.ts
@@ -62,13 +62,6 @@ const qsSections: QuickStartSection[] = [
anchorTag: 'spa',
desc: 'JavaScript app that runs in the browser',
articles: [
- {
- href: '/blog/2022/07/15/remix-demo',
- title: 'Remix',
- icon: '/img/icons/javascript.svg',
- faIcon: 'fa-j',
- navColor: 'yellow'
- },
],
},
{
@@ -87,13 +80,6 @@ const qsSections: QuickStartSection[] = [
faIcon: 'fa-snake',
navColor: 'indigo'
},
- {
- href: '/blog/2020/08/19/securing-react-native-with-oauth',
- title: 'React Native',
- icon: '/img/icons/react.svg',
- faIcon: 'fa-r',
- navColor: 'indigo'
- },
],
},
{
diff --git a/site/_data/exampleapps.yaml b/site/_data/exampleapps.yaml
index e4f8f7d398..7ff7741817 100644
--- a/site/_data/exampleapps.yaml
+++ b/site/_data/exampleapps.yaml
@@ -231,10 +231,6 @@
name: Webhook Lambda Function
description: Stores FusionAuth webhook events to S3 using the CDK to manage infra
language: java
-- url: https://github.com/FusionAuth/fusionauth-example-remix
- name: Remix auth
- description: Example using FusionAuth to provide auth for a Remix application
- language: javascript
- url: https://github.com/FusionAuth/fusionauth-example-gaming-device-grant
name: Gaming and device grant
description: Example using the Device Authorization grant to provide authentication to a game.
diff --git a/site/docs/v1/tech/admin-guide/upgrade.adoc b/site/docs/v1/tech/admin-guide/upgrade.adoc
index 4ef963a480..c9748dd0cc 100644
--- a/site/docs/v1/tech/admin-guide/upgrade.adoc
+++ b/site/docs/v1/tech/admin-guide/upgrade.adoc
@@ -69,7 +69,7 @@ Before upgrading FusionAuth, there are a number of things to consider. Upgrading
=== Version Changes and Notes
-Read the link:/docs/v1/tech/release-notes[release notes]. Release notes help you understand how a version update affects your systems.
+Read the link:/docs/v1/tech/release-notes[release notes]. Release notes help you understand how a version update affects your systems.
The FusionAuth team strives to provide detailed information for every change in every version, including tying the change back to a GitHub issue. The release notes include details on new features, improvements, workarounds, bug fixes, and potential breaking changes.
@@ -81,9 +81,9 @@ Before starting the upgrade process on production, test the upgrade in a staging
Plan for any downtime or maintenance windows required for the upgrade. If changes to the database schema are required, required data migrations could lead to downtime that affects end users. Such changes are always noted in the release notes. (Read the release notes carefully.) An upgrade without a schema change, on the other hand, may not require any downtime from an end-user perspective.
-FusionAuth can perform database migrations automatically and silently using a process called link:/docs/v1/tech/guides/silent-mode[Silent Mode].
+FusionAuth can perform database migrations automatically and silently using a process called link:/docs/v1/tech/guides/silent-mode[Silent Mode].
-If you want to run the database migrations interactively or with other tooling, you can run any needed scripts out of band (meaning directly on the database yourself). The general process would be to:
+If you want to run the database migrations interactively or with other tooling, you can run any needed scripts out of band (meaning directly on the database yourself). The general process would be to:
- Remove all server nodes from a load balancer/proxy.
- Run the database migration scripts.
@@ -108,7 +108,7 @@ If you are using an OIDC compatible library in your application to log your user
include::docs/v1/tech/client-libraries/_client-library-versioning.adoc[]
-=== Skipping Versions
+=== Skipping Versions
Sometimes, you will want to upgrade to a FusionAuth version that is multiple minor versions ahead of your current version. For example, you might want to upgrade from version 1.43.0 to 1.45.0. This is called a "version jump." FusionAuth can run all the necessary database migrations to get you to the latest version, or you can apply the database migrations yourself.
@@ -118,7 +118,7 @@ The alternative to a version jump is to migrate and test at each version of Fusi
Whichever approach you take, you should always test the upgrade in a staging environment to identify potential issues. This is particularly important on more complex upgrades where you are moving between distant minor versions (from 1.22.0 to 1.43.0, for example) or if you have made customizations to FusionAuth. We recommend that the staging environment be as close as possible to your production environment. This includes using the same data, or at least the same data volume, as production. This enables you to test both functionality changes and data update performance times before committing to the upgrade on production.
-=== Updating Configuration
+=== Updating Configuration
Review the release notes to verify if the new version has any new configuration options with defaults that affect your installation.
@@ -155,7 +155,7 @@ This is a good option for development instances or non-production systems such a
This is also a good option for systems that can tolerate longer periods of downtime. For instance, if you know you have near-zero user activity at midnight, you can upgrade then. If you have scheduled downtime for other components of your system, that is a good time to upgrade FusionAuth in this manner.
-If minimizing downtime is a goal, then rolling upgrades or a blue-green deployment might be more suitable.
+If minimizing downtime is a goal, then rolling upgrades or a blue-green deployment might be more suitable.
=== Rolling Upgrade
@@ -217,7 +217,7 @@ To perform a blue-green deployment with a three node cluster, follow these steps
* The FusionAuth instance on the upgraded node will lock the database and own it while the database upgrade is completed. Note that there will be a schema mismatch between the first node and the other nodes, so the other nodes may give errors while the first node is being upgraded. The nature of these errors depends on the code paths being updated as well as how users interact with the system. *Errors should be minimal for core login functionality.*
-Downtime for this upgrade method is limited to the time it takes the first node to run the database migration, and the system will be back online at full capacity with the upgraded version of FusionAuth on the new nodes immediately following the migration.
+Downtime for this upgrade method is limited to the time it takes the first node to run the database migration, and the system will be back online at full capacity with the upgraded version of FusionAuth on the new nodes immediately following the migration.
++++
@@ -249,7 +249,7 @@ graph TB
FusionAuth can handle database migrations automatically using link:/docs/v1/tech/guides/silent-mode[Silent Mode]. FusionAuth can also handle updates interactively on development environments using link:/docs/v1/tech/installation-guide/fusionauth-app#maintenance-mode[Maintenance Mode].
-In production you may want to perform the database migration yourself rather than allow FusionAuth to do so. This is also known as an out-of-band upgrade. This is useful if you want to perform the database migration in a way that minimizes downtime or as part of a larger automated or coordinated upgrade process. Performing the database migration involves running SQL scripts to update the database schema.
+In production you may want to perform the database migration yourself rather than allow FusionAuth to do so. This is also known as an out-of-band upgrade. This is useful if you want to perform the database migration in a way that minimizes downtime or as part of a larger automated or coordinated upgrade process. Performing the database migration involves running SQL scripts to update the database schema.
Depending on your current version and the new version you will be updating to, you might need to execute one or more SQL scripts to update your database. These scripts are located in the migrations folder in the Database Schema ZIP file, which you can download from the link:/direct-download[Direct Downloads] page.
@@ -320,25 +320,26 @@ fusionauth-database-schema/
|-- 1.45.2.sql
|-- 1.46.0.sql
|-- 1.47.0.sql
+ |-- 1.48.0.sql
----
== Rolling Back an Upgrade
-If your upgrade is unsuccessful or causes unexpected issues, you may need to roll back your FusionAuth instance to a previous version.
+If your upgrade is unsuccessful or causes unexpected issues, you may need to roll back your FusionAuth instance to a previous version.
Here are the steps for initiating a rollback:
-1. Stop your FusionAuth instances.
+1. Stop your FusionAuth instances.
2. Initiate the process to restore from the database backup taken prior to starting the upgrade.
-3. Redeploy FusionAuth using your previous version. How you do this will depend on your deployment method.
+3. Redeploy FusionAuth using your previous version. How you do this will depend on your deployment method.
If you are running a FusionAuth Cloud deployment, you can find instructions for rolling back an upgrade here: link:/docs/v1/tech/installation-guide/cloud#rolling-back-from-a-problematic-upgrade[Rolling Back From a Problematic Upgrade].
It's important to consider the timing implications of a rollback or any disaster recovery process. RTO, or Recovery Time Objective, is the targeted period time within which a service should be restored after an outage to avoid unacceptable consequences. Simply put, it is how long you can afford to be without the service or system before it severely impacts your business. It represents the goal for the time taken to recover from failure.
-RPO, or Recovery Point Objective, on the other hand, refers to the maximum tolerable amount of data loss measured in time. Determine RPO by looking at the time of the last backup you need to restore from and the restore time.
+RPO, or Recovery Point Objective, on the other hand, refers to the maximum tolerable amount of data loss measured in time. Determine RPO by looking at the time of the last backup you need to restore from and the restore time.
-In the context of a FusionAuth upgrade rollback, the RPO would be the time since the last backup before the upgrade, and the RTO would be the time it takes to stand up the older version of the system and restore the database.
+In the context of a FusionAuth upgrade rollback, the RPO would be the time since the last backup before the upgrade, and the RTO would be the time it takes to stand up the older version of the system and restore the database.
The RPO effectively measures the maximum tolerable data loss in the event of a rollback, and the RTO measures the time it takes to recover from the failure.
@@ -366,7 +367,7 @@ include::docs/v1/tech/installation-guide/_modes.adoc[]
This section will guide you with detailed technical instructions on how to upgrade FusionAuth nodes on different platforms.
-=== Cloud
+=== Cloud
To upgrade your FusionAuth Cloud instance, see the link:/docs/v1/tech/installation-guide/cloud#upgrading-a-deployment[Cloud Installation Guide].
diff --git a/site/docs/v1/tech/release-notes.adoc b/site/docs/v1/tech/release-notes.adoc
index 84b216d273..8c530ac662 100644
--- a/site/docs/v1/tech/release-notes.adoc
+++ b/site/docs/v1/tech/release-notes.adoc
@@ -60,6 +60,118 @@ Looking for release notes older than 1.23.0? Look in the link:/docs/v1/tech/arch
[role=release-note]
+== Version 1.48.0-EAP.20231021
+_October 21st, 2023_
+
+[WARNING.general-warning]
+====
+*Early Access*
+
+This is an early access build. Please review the link:/docs/v1/tech/admin-guide/releases#early-access-program[EAP rules] to understand the limitations of this release before upgrading.
+====
+
+include::docs/v1/tech/__database-migration-warning.adoc[]
+
+=== Changed
+* We are officially announcing the end of life for the Nashorn JavaScript engine used by FusionAuth Lambda functions. All new functions have defaulted to the GraalJS since version `1.35.0`. The engine is not being removed in the release, but this is an official notice that we plan to remove this engine in early 2024. Please review your lambda functions and ensure the `engineType` is set to `GraalJS`.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/1828[GitHub Issue #1828]
+* We are officially announcing the end of life for the `fusionauth-search` package. This is currently available in a `.deb`, `.rpm` and `.zip` bundle for various platforms. This package is still available, but the plan is to stop building this at the end of 2023. Please make plans to discontinue use of the `fusionauth-search` package if you are currently using it.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2532[GitHub Issue #2532]
+* When the OpenID Connect or External JWT Identity Provider is configured to Link by Email and the IdP returns a claim named `email_verified` and the value is `false`, the link request will be rejected. This change is intended to reduce the risk of linking on an un-verified email address.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2423[GitHub Issue #2423]
+
+=== Security
+* When an IdP is configured to Link by Email or Link by Username and a user already exists with this email or username respectively, perform additional validation to ensure the user does not already have an existing link to the current Identity Provider. This only affects IdP that allow for one to many tenants to be accessed through a single IdP configuration. In practice this means that the IdP cannot guarantee that an email address is considered globally unique and only assigned to a single user.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2512[GitHub Issue #2512]
+
+=== Fixed
+* Enhance the widget used in multi-value select controls to accept a value when pasting. For example, you may now paste a value from the clipboard directly into the `Authorized redirect URLs` field. While previously the paste operation worked, the user would have to click the value to confirm. If you clicked off of the field, the value would not be saved.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/1784[GitHub Issue #1784]
+* Correct the error message when a user has enabled MFA and a webhook returns a non-200 status code for the `user.login.success` event. The message will now correctly indicate the webhook has failed instead of the previously incorrect error indicating an invalid token was used.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/1955[GitHub Issue #1955]
+* When viewing an Email Template in the FusionAuth admin UI, two dialogs open instead of one. This was the result of two event handlers being bound instead of one.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2304[GitHub Issue #2304]
+* When using the asynchronous tenant delete, it is possible for the delete job to fail if the system is under heavy load. When this occurs the delete job status may not be correctly updated and you are stuck in a `Deleting` state. The asynchronous job processor has been enhanced to account for this potential failure condition so the the job can be correctly restarted if necessary.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2307[GitHub Issue #2307]
+* Correct a potential race condition that could cause a request to the `/.well-known/jwks.json` endpoint to exception and return a `500` status code when under heavy load.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2390[GitHub Issue #2390]
+* The Lambda metrics introduced in version `1.47.0` may not always correctly increment the failed count when a lambda invocation failed. This affects the `lambda.[*].failures` and `lambda.[{webhookId}].failures` metric names.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2408[GitHub Issue #2408]
+* When using the `PATCH` method on the Tenant API, if you previously had any explicit webhooks configured for this tenant, the association between the tenant and the webhook was lost. If you are not using webhooks, or all of your webhooks are configured for `All tenants` (`webhook.global`), this bug would not affect you.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2411[GitHub Issue #2411]
+* Improve the validation for the Entity API to correctly validate the `type.id` value. Because this value was not being correctly validated, it means the API caller may receive a `500` status code instead of a `400` with a developer friendly JSON response body to indicate how the input can be corrected.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2412[GitHub Issue #2412]
+* A critical bug was identified that caused FusionAuth to incorrectly identify users eligible for deletion based upon the tenant policy to delete users with an unverified email address. Until you have upgraded to version `1.48.0` please disable `Delete unverified users` if you currently have enabled `Email verification`, `Verify email when changed` and `Delete unverified users`.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2441[GitHub Issue #2441]
+* A bug was identified that affected several APIs when using the `PATCH` method with fields that require custom deserializers in FusionAuth. Affected APIs included Application, Connector, Message Template and Identity Provider. The symptom you will observe is a failed request with a `500` status code.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2454[GitHub Issue #2454]
+* When using PostgreSQL, under heavy load, a potential deadlock conditions exists when attempting to write login metrics to the database. MySQL database was not affected by this bug. If you were to encounter this bug you may observe some exceptions in the log related to the LoginQueue.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2465[GitHub Issue #2465]
+* Fix a JavaScript error that was preventing Audit Log searches by user from returning results.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2470[GitHub Issue #2470]
+* Resolve an issue where users could not enable two-factor authentication during authentication when they were not registered for the application. Thanks to https://github.com/wproffitt-elder[@wproffitt-elder] for reporting!
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2474[GitHub Issue #2474]
+* When using the Refresh Token API, un-expired SSO sessions may be incorrectly omitted from the API response. The result of this bug is that an active SSO session may not be displayed in the FusionAuth admin UI. This has now been corrected, and the FusionAuth admin UI and the Refresh Token API will correctly return all valid SSO sessions.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2489[GitHub Issue #2489]
+* If the `search.servers` configuration value was not added to the `fusionauth.properties` configuration file, and you omit the `SEARCH_SERVERS` environment value, FusionAuth would fail to start. The correct behavior is for FusionAuth to default to `http://localhost:9021`.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2507[GitHub Issue #2507]
+
+=== Enhancements
+* Enhance the User and Entity Search APIs to paginate beyond 10,000 results. The Search API response will now include a `nextResults` value that can be used to ask for the next set of search results which enables the API to paginate through the entire available result set.
+ ** See the link:/docs/v1/tech/apis/entity-management/entities#search-for-entities[Entity Search APIs] and link:/docs/v1/tech/apis/users#search-for-users[User Search APIs] for API details.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/494[GitHub Issue #494]
+* When using the Webhook test action in the FusionAuth admin UI, additional information will now be returned if the webhook returns a non-200 status code. This should make it simpler to debug your webhook integration. Prior to this change, the response would only indicate if the response was successful or not.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/793[GitHub Issue #793]
+* When using the Webhook test action in the UI, changes to the example request body were not preserved. Changes will now be preserved across send requests for the browser session. This means a test can be run repeatedly without having to perform the same edits to the default event request body.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/797[GitHub Issue #797]
+* Support specifying webhook SSL certificates from Key Master. Prior to this enhancement, if you needed to specify an SSL certificate, it had to be added to the webhook in PEM format. You may now store this certificate in Key Master and then use this same certificate between webhooks.
++
+This change is backwards compatible, but the ability to manually specify X.509 certificates in PEM format on the webhook configuration has been deprecated and may be removed in the future. See the link:/docs/v1/tech/apis/webhooks[Webhook] API `sslCertificateKeyId` field for for additional details.
++
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/883[GitHub Issue #883]
+* Modal dialogs in the FusionAuth admin UI can now be closed by using the escape key or by clicking outside of the modal.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/903[GitHub Issue #903]
+* Add support for signing webhook events with a SHA-256 hash function. This feature will allow consumers of FusionAuth events to verify the message body has not been modified. The signature is contained in a JWT and will be sent using an HTTP request header named `X-FusionAuth-Signature-JWT`. You may use existing JWT verification strategies including consuming the public key from the JWKS endpoint.
+** See the link:/docs/v1/tech/events-webhooks/signing[Signing Webhooks] and link:/docs/v1/tech/apis/webhooks[Webhooks APIs] for signing and verification details.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/1859[GitHub Issue #1859]
+* Expose the `id_token` returned by the Identity Provider to the Reconcile Lambda function when available. If the `id_token` is returned by the IdP and the signature can be verified it will be now be passed to the lambda function in the `tokens` argument. Example: `tokens.id_token`.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2189[GitHub Issue #2189]
+* Add the `curl` command to the FusionAuth Docker image. This allows you to use the `curl` command for use in health checks or anytime you need to use `curl`!
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2272[GitHub Issue #2272]
+* Support for optional expansion of the `user.registrations` and `user.memberships` properties on the User Search API.
++
+This change is backwards compatible, but you may optionally request the Search API omit these properties on the response which may improve performance. See the link:/docs/v1/tech/apis/users#search-for-users[User Search] API for additional details on using the `expand` request parameter, and the `expandable` response value.
++
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2319[GitHub Issue #2319]
+* Enhance the error messaging returned to the end user when using the Test SMTP button in the FusionAuth admin UI. This enhancement will make it easier to test your SMTP configuration.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2373[GitHub Issue #2373]
+* Reduce un-necessary logging when fuzzers send parameter names containing `class`.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2393[GitHub Issue #2393]
+* When updating a theme, a validation error will be returned if you are missing messages. Currently the error response does include the missing message keys. This error response is now enhanced to return the keys and the default values from the default theme. This allows you to optionally parse the response for the missing keys and values.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2427[GitHub Issue #2427]
+* Expose the `access_token` returned by the Identity Provider to the Reconcile Lambda function. The `access_token` will now be passed to the lambda function in the `tokens` argument. Example: `tokens.access_token`.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2494[GitHub Issue #2494]
+* When the `id_token` is returned from the IdP and the signature can be verified it will now be used to optionally resolve the `uniqueIdClaim` in addition to the `emailClaim` and `usernameClaim`. This means you can configure the `uniqueIdClaim` to a claim that is only available in the `id_token`. Prior to this change, the `id_token` could only be verified if it was signed using the an HMAC algorithm using the `client_secret`. With this change, if the IdP publishes public keys using the JWKS endpoint that is resolved from the `.well-known/openid-configuration` FusionAuth will attempt to validate the signature.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2501[GitHub Issue #2501]
+
+=== Internal
+* Update 3rd party dependencies to remove CVE scan warnings. No known exploits are vulnerabilities exist in FusionAuth as the result of using these 3rd party clients. These upgrades are simply a precautionary measure to stay current.
+ ** Upgrade `google-guice` `5.1.0` to `6.0.0`
+ ** Upgrade `google-guava` `30.1.0` to `32.1.2`
+ ** Upgrade `java-http` `0.2.0` to `0.2.9`
+ ** Upgrade `kafka-clients` `2.8.2` to `3.6.0`
+ ** Upgrade `prime-mvc` `4.11.0` to `4.17.1`
+ ** Upgrade `snappy-java` `1.1.8.1` to `1.1.10.4`
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2385[GitHub Issue #2385]
+* Upgrade to the latest Java 17 LTS. Upgraded from `17.0.3+7` to `17.0.8+1`.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2386[GitHub Issue #2386]
+* Update the logging configuration when using the `fusionauth-search` distribution (`.deb`, `.rpm`, or `.zip`) to be more consistent with the `fusionauth-app` logging configuration. If you are using Elasticsearch or OpenSearch in Docker or other off the shelf installation of Elasticsearch or OpenSearch this change will not affect you.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2391[GitHub Issue #2391]
+* Update the FusionAuth static file resolution configuration to further limit class path resolution. While no known security risks exist with the current behavior, it is not necessary.
+** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/2462[GitHub Issue #2462]
+
+[role=release-note]
+
== Version 1.47.1
_July 27th, 2023_
diff --git a/site/landing/php-apis/cookie-example.png b/site/landing/php-apis/cookie-example.png
new file mode 100644
index 0000000000..a99ce91c17
Binary files /dev/null and b/site/landing/php-apis/cookie-example.png differ
diff --git a/site/landing/php-apis/login.html b/site/landing/php-apis/login.html
new file mode 100644
index 0000000000..7b54885a38
--- /dev/null
+++ b/site/landing/php-apis/login.html
@@ -0,0 +1,21 @@
+---
+layout: developer-container
+title: PHP APIs Cookie App Login
+description: PHP APIs Cookie App Login
+sitemap:
+ exclude: 'yes'
+---
+
+
+
+
+
+ Login with walker@example.com or trivette@example.com
+
+ Thanks for logging in. Here are the cookies that JavaScript on this page can see.
+
+
+
+
+
+
+
+
diff --git a/site/legal/data-processing-addendum-v1.4.pdf b/site/legal/data-processing-addendum-v1.4.pdf
new file mode 100644
index 0000000000..2aad8a2a31
Binary files /dev/null and b/site/legal/data-processing-addendum-v1.4.pdf differ
diff --git a/src/generate-release-notes-stub.sh b/src/generate-release-notes-stub.sh
index 086b9415a1..596e161883 100755
--- a/src/generate-release-notes-stub.sh
+++ b/src/generate-release-notes-stub.sh
@@ -5,9 +5,13 @@ if [[ $# < 1 ]]; then
exit 1
fi
-# If we can get good at tagging things correctly "bug", "enhancement", "feature" we should be able to make this produce the stub
-# for each section in the release notes - or get close.
+# Issues should be labeled with exactly one of: "bug", "enhancement", "feature", "security", or "internals"
+# Without one of these labels, they won't be included
+# If an issue has multiple labels, it will be repeated
#
+# An Issue's body should end with a '### Release Notes' section and list items to be included
+# Otherwise, they default to the issue title
+
milestone=$1
date=$(date +"%B %-d, %Y" | sed 's/1,/1st,/;s/2,/2nd,/;s/3,/3rd,/;s/\([0-9]\),/\1th,/')
@@ -16,22 +20,35 @@ echo ""
echo "== Version ${milestone}"
echo "_${date}_"
echo ""
+echo "include::docs/v1/tech/__database-migration-warning.adoc[]"
+echo ""
echo "=== Known Issues"
-echo "=== Security"
-echo "=== Changed"
-echo "=== Fixed"
-echo "=== Enhancements"
-echo "=== New"
-echo "=== Internal"
echo ""
+gh_issue_list() {
+ label=$1
+ header=$2
+ echo "=== $header"
+ set -o noglob # don't be globbing files in my backticks
-gh issue list --repo FusionAuth/fusionauth-issues -m $milestone -L 250 --search "sort:created-asc" --json number,body,title --jq ".[]|[.number,.body,.title] | @tsv" |
-while IFS=$'\t' read -r number body title; do
- generated_title=`echo $body | awk -F'--release-notes--' '{print $2, $3}'`
- if [[ "${generated_title}" == " " ]]; then
- generated_title=${title}
- fi
- echo "* $generated_title"
- echo "** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/$number[GitHub Issue #$number]"
-done
+ gh issue list --repo FusionAuth/fusionauth-issues -m $milestone -L 250 --label $label --search "sort:created-asc" --json number,body,title --jq ".[]|[.number,.body,.title] | @tsv" |
+ while IFS=$'\t' read -r number body title; do
+ generated_copy=`echo $body | awk -F'### Release Notes' '{print $2}'`
+ if [[ "${generated_copy}" == "" ]]; then
+ generated_copy=${title}
+ else
+ generated_copy=`echo $generated_copy | sed 's#\\\\r\\\\n#\n#g'`
+ fi
+ echo "* ${generated_copy#[$'\r\t\n ']}"
+ echo "** Resolves https://github.com/FusionAuth/fusionauth-issues/issues/$number[GitHub Issue #$number]"
+ done
+ echo ""
+}
+gh_issue_list "changed" "Changed"
+gh_issue_list "feature" "New"
+gh_issue_list "security" "Security"
+gh_issue_list "bug" "Fixed"
+gh_issue_list "enhancement" "Enhancements"
+gh_issue_list "internals" "Internal"
+
+echo ""