Coder Social home page Coder Social logo

fusionauth / fusionauth-react-sdk Goto Github PK

View Code? Open in Web Editor NEW
9.0 15.0 5.0 521 KB

An SDK for using FusionAuth with React

Home Page: https://fusionauth.io/docs/quickstarts/#single-page-app

License: Apache License 2.0

JavaScript 9.89% TypeScript 88.90% Shell 0.14% SCSS 1.06%
authorization-code-grant fusionauth oauth2 oidc react sdk

fusionauth-react-sdk's Introduction

This repo is out of date and is archived. @fusionauth/react-sdk is currently maintained at https://github.com/FusionAuth/fusionauth-javascript-sdk/tree/main/packages/sdk-react.

An SDK for using FusionAuth in React applications.

Table of Contents

Overview

This SDK allows you to add login, logout, and registration buttons to your React application. You can do this via pre-built buttons, hooks, or higher-order components.

Your users will be sent to FusionAuth’s themeable hosted login pages and then log in. After that, they are sent back to your React application.

Once authentication succeeds, the following secure, HTTP-only cookies will be set:

  • app.at - an OAuth Access Token

  • app.rt - a Refresh Token used to obtain a new app.at. This cookie will only be set if refresh tokens are enabled on your FusionAuth instance.

The access token can be presented to APIs to authorize the request and the refresh token can be used to get a new access token.

There are 2 ways to interact with this SDK:

  1. By hosting your own server that performs the OAuth token exchange and meets the server code requirements for FusionAuth Web SDKs.
  2. By using the server hosted on your FusionAuth instance, i.e., not writing your own server code.

If you are hosting your own server, see server code requirements.

You can use this library against any version of FusionAuth or any OIDC compliant identity server.

Getting Started

Installation

NPM:

npm install @fusionauth/react-sdk

Yarn:

yarn add @fusionauth/react-sdk

Configuring Provider

To configure the SDK, wrap your app with FusionAuthProvider:

import React from 'react';
import { createRoot } from 'react-dom/client';
import { FusionAuthProvider } from '@fusionauth/react-sdk';
import App from './App';

const container = document.getElementById('root');
const root = createRoot(container!);

    root.render(
        <FusionAuthProvider
            clientID=""     // Your FusionAuth client ID
            serverUrl=""    // The URL of the server that performs the token exchange
            redirectUri=""  // The URI that the user is directed to after the login/register/logout action
        >
            <App />
        </FusionAuthProvider>
    );

Usage

Pre-built buttons

There are three pre-styled buttons that are configured to perform login/logout/registration. They can be placed anywhere in your app as is.

import {
  FusionAuthLoginButton,
  FusionAuthLogoutButton,
  FusionAuthRegisterButton
} from '@fusionauth/react-sdk';

export const LoginPage = () => (
  <>
    <h1>Welcome, please log in or register</h1>
    <FusionAuthLoginButton />
    <FusionAuthRegisterButton />
  </>
);

export const AccountPage = () => (
  <>
    <h1>Hello, user!</h1>
    <FusionAuthLogoutButton />
  </>
);

Programmatic usage

Alternatively, you may interact with the SDK programmatically using the useFusionAuth hook or withFusionAuth HOC.

useFusionAuth

Use the useFusionAuth hook with your functional components to get access to the properties exposed by FusionAuthContext:

import React from 'react';
import { useFusionAuth } from '@fusionauth/react-sdk';

const App = () => {
  const { login, logout, register, isAuthenticated } = useFusionAuth();

  return isAuthenticated ? (
    <div>
      <span>Hello, user!</span>
      <button onClick={() => logout()}>Logout</button>
    </div>
  ) : (
    <div>
      <button onClick={() => login()}>Log in</button>
      <button onClick={() => register()}>Register</button>
    </div>
  );
};

See useFusionAuth for more details.

withFusionAuth

The withFusionAuth higher-order component can be used to wrap your components and give them access to a fusionAuth prop which contains all the properties exposed by the FusionAuthContext. This works with both functional and class components:

Functional Component
import React from 'react';
import { withFusionAuth, WithFusionAuthProps } from '@fusionauth/react-sdk';

const LogoutButton: React.FC<WithFusionAuthProps> = props => {
  const { logout } = props.fusionAuth;

  return <button onClick={() => logout()}>Logout</button>;
}

export default withFusionAuth(LogoutButton);
Class Component
import React, { Component } from 'react';
import { withFusionAuth, WithFusionAuthProps } from '@fusionauth/react-sdk';

class LogoutButton extends Component<WithFusionAuthProps> {
  render() {
    const { logout } = this.props.fusionAuth;
    return <button onClick={() => logout()}>Logout</button>;
  }
}

export default withFusionAuth(LogoutButton);

See withFusionAuth for more details.

State parameter

The login and register functions both accept an optional string parameter called state. The state that is passed in to the function call will be passed back to the onRedirectSuccess handler on your FusionAuthProvider. Though you may pass any value you would like for the state parameter, it is often used to indicate which page the user was on before redirecting to login or registration, so that the user can be returned to that location after a successful authentication.

Protecting Content

The RequireAuth component can be used to protect information from unauthorized users. It takes an optional prop withRole that can be used to ensure the user has a specific role. If an array of roles is passed, the user must have at least one of the roles to be authorized.

import { RequireAuth, useFusionAuth } from '@fusionauth/react-sdk';

const UserNameDisplay = () => {
  const { user } = useFusionAuth();

  return (
    <RequireAuth>
      <p>User: {user.name}</p> // Only displays if user is authenticated
    </RequireAuth>
  );
};

const AdminPanel = () => (
  <RequireAuth withRole="admin">
    <button>Delete User</button> // Only displays if user is authenticated and has 'admin' role
  </RequireAuth>
);

Known Issues

Token exchange endpoint being called repeatedly

If you see the token exchange endpoint being called multiple times, this is due to a dev time setting in React 18. When running using StrictMode in development mode, React 18 will mount, unmount, and remount all components in this mode, which results in the network call running twice.

This will not happen in a production build or if StrictMode is disabled.

If you remove the React.StrictMode tags in index.tsx of the example app, the call is only made once.

Quickstart

See the FusionAuth React Quickstart for a full tutorial on using FusionAuth and React.

Documentation

Full library documentation

Use backticks for code in this readme. This readme is included on the FusionAuth website, and backticks show the code in the best light there.

Formatting

There are several linting packages run when you push to a branch. One is prettier. If this fails, you can fix the files from the command line:

  • npm run install
  • npm run prettier -- -w /path/to/file

Doing this will overwrite your file, but fix prettier's objections.

Releases

To perform a release to NPM, create a release on GitHub. That will automatically publish a release to GitHub.

Upgrade Policy

This library may periodically receive updates with bug fixes, security patches, tests, code samples, or documentation changes.

These releases may also update dependencies, language engines, and operating systems, as we'll follow the deprecation and sunsetting policies of the underlying technologies that the libraries use.

This means that after a dependency (e.g. language, framework, or operating system) is deprecated by its maintainer, this library will also be deprecated by us, and may eventually be updated to use a newer version.

fusionauth-react-sdk's People

Contributors

bhalsey avatar colinfrick avatar david-chalk avatar davidprae avatar dmackinn avatar jakelo123 avatar jpdeblock avatar michaelyons avatar mooreds avatar osbornm avatar sam-woodridge avatar todda00 avatar vcampitelli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fusionauth-react-sdk's Issues

[RFC] Refactor FusionAuthProvider

NOTE: this issue tracks the discussion around the decision to even do this. This is not the implementation issue.

Situation

The FusionAuth React SDK has a FusionAuthProvider component that is responsible for much of the functionality. It's basically the valuable intellectual property of the SDK.

Challenge

The FusionAuthProvider source code is a bit unwieldy and difficult to digest for developers. This is turn can make it difficult to debug or just generally understand what "state" the running code is in. Extending or adding new functionality can also be a precarious operation.

Question

Should we refactor the FusionAuthProvider to improve the readability and maintainability of the code?

Answer

Yes. And let's use XState to model the business logic and state of the FusionAuthProvider.

What is XState?

XState is a state management and orchestration solution for JavaScript and TypeScript apps. It lets us create state machines which offer predictability via guarantees about state and functionality.

Sounds cool but what benefits will this offer us?

Here's an example we can look at.

The example demonstrates a few nifty features:

1. Discrete, exclusive states

In in the world of state machines, the term "state" refers to a "state of being" (as opposed to "data" – this is a common conflation of terms). State machines can only be in one state at a time. In the case of lampMachine, the defined states are TurnedOn and TurnedOff. So the lampMachine can either be TurnedOn or TurnedOff. There's no way to be in both or neither. This is great because it exactly models the binary state lamps actually have.

How is this applicable to the FusionAuth React SDK?

There are two super important states to consider within the FusionAuth ReactSDK: 1) "user is authenticated" and 2) "user is not authenticated". If a user is authenticated they cannot also be unauthenticated (and vice versa). Boolean values can represent this simple idea easy enough. But things get hazy once we introduce related states.

Take this code from the React SDK for example:

const [isLoading, setIsLoading] = useState(false);
const isAuthenticated = useMemo(() => Object.keys(user).length > 0, [user]);

So it turns out there's some more "states" we can be in. How do they interact? What's the relationship? Do they affect one another? Does isLoading have something to do with isAuthenticated?

Further, it's possible for isLoading and isAuthenticated to both be true. Is that ok? It's really hard to tell, we need a lot more context which requires digging into the code.

This demonstrates one of the big benefits of state machines: I don't need any more context than reading the defined states to understand what's even possible. Intention is clearly encoded when using state machines.

2. Scoped events

State machines have the ability to scope events to particular states. In the lampMachine, if it's in the TurnedOn state, sending an ON event won't do anything because we didn't define that event for that state. This matches our mental model of how lamps work: if a lamp is turned on, I can't turn it on again. I could try but I couldn't actually do anything since there is nothing to do.

How is this applicable to the FusionAuth React SDK?

When a user is a particular state like Authenticated, we can make sure events that don't contextually mean anything (like AUTHENTICATE) actually do anything at all. We'll be guaranteed to not try and authenticate again.

3. Portable business logic

While there is a small integration API to deal with when consuming state machines, the actual business logic is framework agnostic so can be used in arbitrary JavaScript projects.

How is this applicable to the FusionAuth React SDK?

This means we can build out this robust model of business logic and immediately bring it over to the other SDKs and it'll work exactly the same. This helps maintainability and coherence among the SDKs – a fix for one fixes the others, extending functionality for one, extends that functionality for the others.

What's the lift? 💪

The current business logic isn't very explicit so we will need to be extra careful about interpreting the business logic, extracting it, and translating it into a state machine. We already have built up a good mental model about what's going on but refactors like this have the potential to uncover ambiguity in the current implementation. We'll need to eliminate these ambiguities by making decisions/uncovering what the actual product requirments are. This could involve some back-and-forth or even a meeting.

Estimate: 1 developer 2-3 days

Provider needs error handling

Provider needs error handling

Description

The main provider component -- FusionAuthProvider -- doesn't check if the response from /me is good. If someone had a server implementation that returned an object representing an error, the SDK would set it as the user.

Probably just need to check for an ok http status from call to /me, and take the correct action from there.

Affects versions

All versions.

Steps to reproduce

Using the example-react-sdk:

  1. Go to the /me route handler and make it do something like:
res.status(500).send({
    error: 'something went wrong'
})

Then save and boot up the server and client.
2. Go to the browser and log in. If the browser doesn't make the network call to (/me), then clear the user cookie with dev tools and refresh.
3. Observe that the SDK is showing you the /account page, but there is no user info to display because your user is set to { error: 'something went wrong' })

Expected behavior

The SDK should know that it is in a non-authenticated state and set the user to {}

Platform

Any web browser.

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

Remove `async` from non-async function definitions

Remove async from non-async function definitions

Description

The login, logout, and register methods provided by IFusionAuthContext are incorrectly typed as asynchronous. They are defined with async, even though they do not contain any asynchronous code. It would be helpful if tests calling these functions with await and waitFor(() =>... assertion) were also be updated.

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

Update README to mention hosted endpoint support

Update README to mention core hosted endpoint support

Description

The SDK comes with out-of-the-box support for FusionAuth hosted endpoints, however, the README currently says “…requires you to set up a server that will be used to perform the OAuth token exchange. This server must have the following endpoints…”

We should keep the documentation up to date by mentioning (alongside the example server code) that the SDK supports the core endpoints by default, and that hosting your own server is not a requirement. Link to the quickstart example app

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

Add peerDependencies

Add peerDependencies

Description

From a feedback request:

You will want to include “react” and “react-dom” as peerDependencies, if that is the package that is being released.

Expected behavior

Include these in the package.json so that if you try to install the react sdk without react, npm complains.

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

Additional context

https://flaviocopes.com/npm-peer-dependencies/

Token exchange endpoint getting called multiple times

I am trying to recreate the example using a Vite/React app with a Serverless/Lambda REST API. I have the POST /token-exchange endpoint doing exactly as it does in the example server, and every time I try to login without an access_token cookie, it is calling the token-exchange endpoint twice. This causes it to error out since it's a race to whoever gets to claim the code first. Sometimes one call will succeed and the other will fail, other times both will fail. But never will both succeed (as they shouldn't). Not sure how much it helps as it's a very local setup, but here are the logs from my Docker container (note the first call succeeds and gives me a token and gets the user info, but the second call fails with an auth_code_not_found error):

fusionauth                     | 2022-12-16 08:43:27.606 PM WARN  org.elasticsearch.client.RestClient - request [PUT http://search:9200/fusionauth_user/_doc/cf82193b-56b6-4740-a75b-0bc1d8ee38fd] returned 1 warnings: [299 Elasticsearch-7.17.0-bee86328705acaa9a6daede7140defd4d9ec56bd "Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security."]
forms-services                 |
forms-services                 |
forms-services                 | POST /token-exchange (λ: tokenExchange)
forms-services                 |
forms-services                 |
forms-services                 | POST /token-exchange (λ: tokenExchange)
forms-localstack               | 2022-12-16T20:43:32.845  INFO --- [   asgi_gw_0] localstack.request.aws     : AWS secretsmanager.GetSecretValue => 200
forms-services                 | user info ClientResponse {
forms-services                 |   statusCode: 200,
forms-services                 |   response: {
forms-services                 |     applicationId: <redacted>,
forms-services                 |     email: <redacted>,
forms-services                 |     email_verified: true,
forms-services                 |     family_name: 'Dura',
forms-services                 |     given_name: 'Josh',
forms-services                 |     roles: [],
forms-services                 |     scope: 'openid offline_access',
forms-services                 |     sid: <redacted>,
forms-services                 |     sub: <redacted>,
forms-services                 |     tid: <redacted>
forms-services                 |   }
forms-services                 | }
forms-services                 | (λ: tokenExchange) RequestId: 6f693574-2c1c-4879-b922-a1d1cf658d73  Duration: 5184.44 ms  Billed Duration: 5185 ms
forms-localstack               | 2022-12-16T20:43:33.032  INFO --- [   asgi_gw_2] localstack.request.aws     : AWS secretsmanager.GetSecretValue => 200
forms-services                 | error with oauth2/token endpoint call {"statusCode":400,"exception":{"error":"invalid_request","error_description":"Invalid Authorization Code","error_reason":"auth_code_not_found"}}
forms-services                 | (λ: tokenExchange) RequestId: 00c5005e-59f9-4a1e-a758-7a8c6b71945b  Duration: 5250.92 ms  Billed Duration: 5251 ms
forms-services                 | error Error: [object Object]
forms-services                 |     at /source/.build/utils/fusionauth.js:87:27
forms-services                 |     at step (/source/.build/utils/fusionauth.js:33:23)
forms-services                 |     at Object.throw (/source/.build/utils/fusionauth.js:14:53)
forms-services                 |     at rejected (/source/.build/utils/fusionauth.js:6:65)
forms-services                 |     at processTicksAndRejections (node:internal/process/task_queues:96:5)

User object from the SDK is not set

The issue I am seeing is that the user object from the sdk is just an empty object. The “isAuthenticated” property is being correctly populated though.

    const { user, isAuthenticated,  } = useFusionAuth();

This results in user being set to an empty object: {} and isAuthenticated being true.

I am able to get the user by just reading the cookie myself, but it seems like user should be set.

It looks like setUser is configured here: https://github.com/FusionAuth/fusionauth-react-sdk/blob/main/src/providers/FusionAuthProvider.tsx#L56

and it seems like useEffect should be setting the user object here: https://github.com/FusionAuth/fusionauth-react-sdk/blob/main/src/providers/FusionAuthProvider.tsx#L127 but the useFusionAuth method doesn't return a valid user.

Send down id token to the react SDK

Send down id token to the react SDK

Problem

We may want to display user information in the react app. The proper way to do that is to use an id_token.

Solution

We should send the id token down to the react app as a non http only cookie.

Alternatives/workarounds

The user object may have that data. See #22 as well.

Additional context

Add any other context or screenshots about the feature request here.

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

How to vote

Please give us a thumbs up or thumbs down as a reaction to help us prioritize this feature. Feel free to comment if you have a particular need or comment on how this feature should work.

Support localstorage

Feedback from a community user:

I won’t be able to use it yet, because my auth flow is traditional i.e. Saving the tokens to localstorage

Add 'Unauthenticated' component

Add 'Unauthenticated' component

We have an AuthRequired component, but it is common to want to display things (the login button) only to unauthenticated users.

Solution

Add an inverse component that only executes when a user is not authenticated.

Alternatives/workarounds

use the isAuthenticated function.

Additional context

Add any other context or screenshots about the feature request here.

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

How to vote

Please give us a thumbs up or thumbs down as a reaction to help us prioritize this feature. Feel free to comment if you have a particular need or comment on how this feature should work.

v1.0.5 doesn't contain any code

v1.0.5 doesn't contain any code

Description

Cannot import anything, as there's no code listed under node_modeles/@fusionauth/react-sdk

Affects versions

List the version you are running, and any other versions you have attempted a recreated.

Steps to reproduce

  1. install @fusionauth/react-sdk
  2. try to import something from the package

Expected behavior

Package should contain code

Screenshots

image

Platform

(Please complete the following information)

  • Device: Desktop
  • OS: NixOs
  • All browsers
  • PostgreSQL

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

Additional context

Workaround is to install v1.0.0

Work with FusionAuth core hosted endpoints

Work with FusionAuth core hosted endpoints

Problem

Using the React SDK requires hosting server endpoints. The only compatible solution right now is in https://github.com/FusionAuth/fusionauth-example-react-sdk

Solution

When FusionAuth adds functionality to host these endpoints, the react sdk should work with this out of the box.

Alternatives/workarounds

Use the example-react-sdk / server

Additional context

FusionAuth/fusionauth-issues#1943

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

How to vote

Please give us a thumbs up or thumbs down as a reaction to help us prioritize this feature. Feel free to comment if you have a particular need or comment on how this feature should work.

Add 'change password' button and function

Changing a password is part of the login flow. We should add a button/function to do this. It will redirect the user over to FusionAuth and then, on successful change, send them back to the app.

allow withRole to take an array of values

allow withRole to take an array of values

Problem

A developer might want to make a page available to multiple roles. RequireAuth.withRole only takes a single value.

Solution

Allow withRole to take a single value or array of values. It should be typed, anyways. So something like withRole: String | String[]

Alternatives/workarounds

FusionAuth role configuration can be set to add hybrid roles that are the combined set of the multiple roles. But this is cumbersome and might not be possible for all users.

Additional context

Requested by Sonderformat.

No error message when the wrong client id is provided

No error message when the wrong client id is provided

Description

There is no error message to the developer if they configure this SDK with the wrong client id, just a blank screen.

Affects versions

0.25.0
using fusionauth 1.45.1 hosted backend.

Steps to reproduce

Steps to reproduce the behavior:

  1. Configure a new react app with this library.
  2. Create an Application in FusionAuth
  3. Put the wrong client id in the react app createRoot call.
  4. Add a login button to the app
  5. Try to login using an incognito browser.

Expected behavior

I don't know, but at least a message in the JS console.

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

Additional context

You can grab this sample app if you want a super simple testbed: https://github.com/FusionAuth/fusionauth-example-react-guide

Inline documentation for SDK

Inline documentation for SDK

Problem

There is no inline documentation for components and methods provided by the SDK

Solution

Use JSDoc to include inline docs so that developers get useful descriptions in tooltips, like the screenshot below (pulled in from our Angular SDK).

image

Additional context

We can align requirements/documentation across the react/angular/vue SDKs using our tech spec -- cc: @david-chalk

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

How to vote

Please give us a thumbs up or thumbs down as a reaction to help us prioritize this feature. Feel free to comment if you have a particular need or comment on how this feature should work.

Why is `Content-Type` set for empty requests?

Currently when making a POST to the /jwt-refresh endpoint the request gets a content-type set to application/json (see: https://github.com/FusionAuth/fusionauth-react-sdk/blob/main/src/providers/FusionAuthProvider.tsx#L141-L149). This seems odd since there is no BODY on the request. This can cause problems in some backends as they might choose to valid a body based on the the content-type. For example the default JSON parser in fastify (a node backend) throws if there is no body (see: https://github.com/fastify/fastify/blob/a4b21f0a2e7e753e9a8772dbac6b255b7dcbdc6b/test/helper.js#L316-L335).

I see to possible solutions to this.

  1. Don't set the content-type
  2. If the idea was to set this to eventually pass something in the body but that was never implemented you could just set the body as an empty object for now.

Please let me know your thoughts.

Source Maps Missing

Issue

The source code published to NPM is compressed and no source maps are shipped. This makes it really difficult to debug.

FWIW; A lot of libraries these days don't even do compression since it will be handled by the users setup ( webpack ) already.

/me fetch failure causing infinite loop

/me fetch failure causing infinite loop

Description

After login when no user cookie is present then the user info endpoint is being invoked via a fetch request and if that fetch fails for a reason (CORS, or anything else), and a re-render is triggered, then it will cause an infinite loop (can be tested with the example app, comment out the alert dialog to see it).

Affects versions

Latest

Steps to reproduce

Steps to reproduce the behavior:

  1. Configure a failing userinfo endpoint in the example app
  2. Login to the app

Expected behavior

Have some backoff strategy to stop making the fetch calls and getting information about userinfo failure specifically (because it is a backchannel invocation failure, not a redirect failure) or the ability to pass in a function which can do the userinfo invocation, so the consumers of the SDK has a better control over what to do.

Screenshots

N/A

[RFC] Utilize Storybook for UI development

NOTE: this issue tracks the discussion around the decision to even do this. This is not the implementation issue.

Situation

The FusionAuth React SDK is a React npm package that offers both UI components with preconfigured functionality and non-UI components that offer non-visible functionality. There is currently no way to view the visible UI components.

Challenge

It is difficult to work on the visual styles of the UI components because there is no way to view them.

Question

How can we view the UI components in order to get visual feedback on style changes?

Answer

Let's use Storybook. It is the industry standard for viewing UI components in isolation and as such is well-supported with lots of documentation and resources.

Rendering components in isolation is particularly necessary for UI libraries like the FusionAuth React SDK because we don't have a host app to run them in. Components being isolated also forces developers to make sure they don't have any hidden dependencies to work correctly.

Aside from giving developers a place to develop UI components, Storybook also acts as interactive documentation for these components. Developers (and others) can interactively change props and components update to reflect their changes.

FusionAuth could choose to host the Storybook publicly so developers can view the components without even pulling down and running the project themselves. Services like Chromatic make hosting Storbook instances extremely easy and quick.

We can also "compose" Storybooks enabling us to have one place to view the components for every FusionAuth SDK. This would be a future enhancement past this one however.

Example Storybooks

What's the lift? 💪

Integrating Storybook is fairly simple. And because we don't have a ton of components, it shouldn't take very long to make a "Story" for each component.

Estimate: 1 developer 1 day

Specify node/npm version

package.json should specify a node and npm version

This is important for compatibility because mismatched versions can create unexpected issues.

refreshToken() does not work without implicitly setting tokenRefreshPath

refreshToken() does not work without implicitly setting tokenRefreshPath

Description

When using the Hosted Backend, the endpoint URL for token refresh is /app/refresh/{clientId} but the React SDK is sending the refresh attempt to /app/refresh.

When the provider is set with a tokenRefreshPath which includes the clientId, the refresh works as expected.

Not working:

<FusionAuthProvider
  clientID="4dff639c-d360-427a-b742-d108a2229002"
  serverUrl="http://localhost:9011"
  redirectUri="http://localhost:4000"
>

Working:

<FusionAuthProvider
  clientID="4dff639c-d360-427a-b742-d108a2229002"
  serverUrl="http://localhost:9011"
  redirectUri="http://localhost:4000"
  tokenRefreshPath="/app/refresh/4dff639c-d360-427a-b742-d108a2229002"
>

Affects versions

"@fusionauth/react-sdk": "^0.25.0"
Fusion Auth w/ Hosted Backend API @ 1.47.1

Expected behavior

I expect the clientId to be included in the refresh URL without having to set the tokenRefreshPath

customize the name of the `isAuthenticated` cookie

Option to customize the cookie name used to check isAuthenticated.

Problem

We're using a different backend implementation, our cookie content and name is different, so isAuthenticated will never work for us.

Solution

Have an option to change the cookie name from app.at_exp to something else, so the SDK could still be used as is.

Alternatives/workarounds

Don't use the SDK and implement our own SDK which is also OK.

Tests causing 'not wrapped in act(...)' warning

Running the tests will output several 'not wrapped in act(...)' warnings.

Description

The warning is being triggered by some tests calling testing-library's render method with await as well as some instances from within act. This is an indication that react state of components being tested may be out of sync with assertions made in tests, which could cause unexpected behavior.

Relevant documentation

image

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

Add support for automatic, transparent refresh of access tokens

Add support for automatic, transparent refresh of access tokens

Problem

Currently, if I am making requests of an external API who is using the access token retrieved from the OAuth server as a credential, I have to catch a failure/access denied request, and then manually call the refresh token endpoint, then repeat my call.

Solution

It would be great if the SDK automatically renewed the access token without any work on my part.

One option would be to have the server side SDK code send down a cookie that expired just before the access token did. This cookie could contain no secrets, so it could be readable by JS. We could set a timer to check for this cookie regularly. When the cookie is gone/expired, the SDK js could call out to the refresh token endpoint and get a new access token.

There may be other approaches that would work.

Alternatives/workarounds

n/a

Additional context

FusionAuth/fusionauth-issues#1674 outlines this functionality as well.

Community guidelines

All issues filed in this repository must abide by the FusionAuth community guidelines.

How to vote

Please give us a thumbs up or thumbs down as a reaction to help us prioritize this feature. Feel free to comment if you have a particular need or comment on how this feature should work.

Do not use multiple package managers

We've noticed that some repos contain both yarn.lock and package-lock.json files -- a result of using both yarn and npm package managers. This item is to make sure repositories have just one lock file. Document this information in any relevant README files, so that future contributors will know which package manager to use.

Access token not removed after logout

Related: #22

The access and refresh token cookies are set by the example server side code. Since it is set by a server side component, it is not accessible to the react SDK to delete on logout.

When you click logout, you are sent to FusionAuth's logout link: https://github.com/FusionAuth/fusionauth-react-sdk/blob/main/src/providers/FusionAuthProvider.tsx#L100

This kills the FusionAuth managed cookies. We also need to remove any server side non FusionAuth set cookies, such as the access_token.

After the FusionAuth logout URL is processed, it calls the logout url. (Set here by default; https://github.com/FusionAuth/fusionauth-example-react-sdk/blob/main/kickstart/kickstart.json#L60 ). That'd the proper place to nuke the access token and refresh token cookies.

So I think the best path is to create another server side route which receives the logout request, nukes the cookies, and then redirect to the first, unauthenticated page of the react app.

[RFC] Utilize Mock Server Worker for tests

NOTE: this issue tracks the discussion around the decision to even do this. This is not the implementation issue.

Situation

The FusionAuth React SDK currently extensively uses function mocking in order to test functions that access the network.

Challenge

While this ensures that a function by a particular name is called, it isn't a very robust way to check that a function does what it's supposed to do.

Question

How can we test functions that access the network in a more robust way that gives us more confidence in the results of our tests?

Answer

Let's use Mock Service Worker (MSW). MSW is the industry standard API mocking library that allows you to write client-agnostic mocks and reuse them across any frameworks, tools, and environments. It's well supported and has plenty of resources and documention.

Basically, we can utilize it to setup Service Workers that intercept network requests and respond with what we want to test. I.e. a function that accesses GET /some-endpoint won't need to be mocked. It will make it's request normally and the Service Workers will intercept the call and respond accordingly.

We're able to easily test multiple response types as well, so we can make sure any network failures are handled in an appropriate way as well.

This will let the code run that should run and the surface area of our tests will be increased and so will the accuracy of our tests.

MSW is also framework agnostic which means we could reuse the work we do for the other FusionAuth SDKs, increasing our confidence in those tests as well.

What's the lift? 💪

The FusionAuth React SDK doesn't hit very many endpoints (about 6), so even accounting for variations, we're not looking at too much setup time.

After setup, we just need to update the tests to remove the mocked calls. This also won't be very time consuming as there aren't many functions to worry about.

Estimate: 1 developer 1 day

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.