npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

bento-auth-js

v6.0.2

Published

Authentication library for web applications of Bento-Platform

Downloads

635

Readme

Bento Auth JS

The Bento authentication/authorization web client library, written in TypeScript for React Redux applications.

The authentication portion of this library works with OIDC providers, such as KeyCloak.

The authorization portion of this library works with applications protected by the Bento Authorization Service.

Installation

Add bento-auth-js as a dependency to another project:

npm install bento-auth-js

Usage

Redux store setup.

Import the bento-auth-js reducers and add them to your application's Redux store.

import {AuthReducer as auth, OIDCReducer as openIdConfiguration} from "bento-auth-js";

const rootReducer = combineReducers({
    auth,
    openIdConfiguration,
    // rest of reducers
})

You may use the AuthReducer alone if the application doesn't require authorization. If you do need authorization, both reducers must be used by the store.

Authenticating a user

Usually this is done in the top App component. The following example uses a pop-up window with PKCE flow.

import {
    useHandleCallback,
    checkIsInAuthPopup,
    useIsAuthenticated,
    useOpenSignInWindowCallback,
    usePopupOpenerAuthCallback,
    useSignInPopupTokenHandoff,
    useSessionWorkerTokenRefresh,
    useOpenIdConfig,
    BentoAuthContextProvider,
} from "bento-auth-js";

import YourSessionWorker as SessionWorker from "../session.worker";
import { AUTH_CALLBACK_URL, BENTO_URL_NO_TRAILING_SLASH, CLIENT_ID, OPENID_CONFIG_URL } from "../config";
import { BentoAuthContext } from "./contexts";

// Session worker creator function must be in a constant for useSessionWorkerTokenRefresh
const createSessionWorker = () => new SessionWorker();

// Assuming fetchUserDependentData is a thunk creator:
// Using a thunk creator as a hook argument may lead to unwanted triggers on re-renders.
// So we store the thunk inner function of the fetchUserDependentData thunk creator in a constant, 
// outside of the component function.
const onAuthSuccess = fetchUserDependentData(nop);

const App = () => {
    const dispatch = useDispatch();

    // Popup sign-in window and its message handler refs
    const signInWindow = useRef(null);
    const windowMessageHandler = useRef(null);

    // Get the OIDC config
    const openIdConfig = useOpenIdConfig();
    
    // Opens sign-in window
    const userSignIn = useOpenSignInWindowCallback(signInWindow, SIGN_IN_WINDOW_FEATURES);

    // Create the auth callback for the application's URL
    const popupOpenerAuthCallback = usePopupOpenerAuthCallback();

    const isInAuthPopup = checkIsInAuthPopup(BENTO_URL_NO_TRAILING_SLASH);

    // Auth code callback handling 
    useHandleCallback(
        CALLBACK_PATH,
        onAuthSuccess,
        isInAuthPopup ? popupOpenerAuthCallback : undefined,
    );
    
    // Token handoff with Proof Key for Code Exchange (PKCE) from the sing-in popup
    useSignInPopupTokenHandoff(windowMessageHandler);

    // Session worker tokens refresh
    useSessionWorkerTokenRefresh(
        sessionWorker,
        createSessionWorker,
        onAuthSuccess,
    );

    // Get user auth status
    const isAuthenticated = useIsAuthenticated();

    return (
        <>
            {
                isAuthenticated ? "User is signed in!" : <a onClick={userSignIn}>
                    Sign in to Bento
                </a>
            }
        </>
    );
}

const AppWithContext = () => (
    <BentoAuthContextProvider value={{
        applicationUrl: "(...)",
        openIdConfigUrl: "(...)",
        clientId: "(...)",
        scope: "openid email",
        postSignOutUrl: "/",
        authCallbackUrl: "(...)/callback",
    }}>
        <App />
    </BentoAuthContext>
);

Authorization for a signed-in user

Client applications can evaluate user permissions with bento-auth-js. These permissions can then be used to hide or show information, or to disable/enable features.

To evaluate a user's permissions on a resource:

import { 
    useHasResourcePermission,
    useResourcePermissions,
    RESOURCE_EVERYTHING,
    viewDropBox,
    deleteDropBox,
} from "bento-auth-js";

// Get the authz url, here we assume it is somewhere in the store.
const authzUrl = useSelector((state) => state.services.itemsByKind?.authorization.url)

// Evaluates a single permission
const {isFetching, hasPermission} = useHasResourcePermission(RESOURCE_EVERYTHING, authzUrl, viewDropBox);

if (hasPermission) {
    // user can viewDropBox
}

// Returns the user's permissions on the resource
const {
    permissions,
    isFetching: isFetchingPermissions,
    hasAttempted: hasAttemptedPermissions,
} = useResourcePermissions(RESOURCE_EVERYTHING, authzUrl)

if (permissions.includes(deleteDropBox)) {
    // user can delete drop-box elements
}

Note on authorization:

With authorization in client/server applications, it is the server's duty to determine if the client's requests should be allowed or rejected.

Therefore, client side permissions should only be used with services that implement authorization on the server side.

For example, simply disabling a delete button that performs a DELETE request to a Bento service (e.g. Drop Box) is not secure if the service doesn't check if the user has the correct permissions with the authorization service.

You may use client side permissions to:

  • Disable information displays that get their data from protected GET endpoints.
    • No need to show an empty display resulting from a 403 response to an unauthorized user
  • Disable actions that use protected endpoints (POST, PUT, DELETE, ...)
    • No need for a button to be clickable if the user lacks the permissions for the resource.

Release procedure

A commit on the main branch will trigger a build and release of the package to the npm Registry, no need to manually create tags thanks to semantic-release.

Please follow the instructions bellow when writing your commits.

Semantic release

Bento Auth JS adheres to the semver versioning convention (Semantic Versioning). This repository uses the semantic-release library to automate the release of semver compliant packages to the npm Registry.

Semantic-release parses the commit messages in the release branch in order to determine the versioning changes. It does not rely on magic to work, but rather on specific commit message formats, which are described bellow.

Commit message guidelines

Semantic-release uses the Conventional Commits specification in order to parse relevant information.

<type>(<scope>): <short summary>
  │       │             │
  │       │             └─⫸ Summary in present tense. Not capitalized. No period at the end.
  │       │
  │       └─⫸ Commit Scope: Optional, what was changed.
  │
  └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|test

Both <type> and <short summary> are mandatory, while <scope> is optional, but recommended for pretty release notes.

Example commit messages

After fixing a dependency issue:

fix(dependencies): resolve peer dependencies issues caused by React version

After adding a new resource:

feat(resource): add support for katsu data-types

Commit with commitlint

Commitlint is a safeguard for commit message formats, which you can use to help write semver-compliant commits. Husky is a git hooks tool that binds commitlint to the git commit command.

Installation

Run these steps once to setup commitlint + husky.

# Install dev dependencies (commitlint & husky)
npm install
# Install husky git hook
npx husky install
# Add commitlint as a hook to husky
npx husky add .husky/commit-msg  'npx --no -- commitlint --edit ${1}'

Usage

Use the git cli as you normally would to make your commits, commitlint will intercept your commit if it is malformed.

Example:

git commit -m "ci(semantic-release): add commitlint and husky as dev tools to write valid commits"

Local development

For local development in a React/Redux app that uses bento-auth-js, you can follow these steps for your setup:

  1. build and pack bento-auth-js

    # Builds package and creates a pack file in the "./packs" dir
    npm run buildpack
  2. In the project using bento-auth-js, modify the bento-auth-js dependency in package.json so that the version number is now the absolute path to the pack file.

    - "bento-auth-js": "1.0.0",
    + "bento-auth-js": "file:~/bento-auth-js/packs/bento-auth-js-2.0.0.tgz",
  3. Install the dependencies in the project

    npm install

Note: you will need to repeat steps 1 and 3 everytime you want the changes to be applied to the app using bento-auth-js