npm package: @lantern-packages/auth-core-utility
Description: Shared Auth0 utilities for React and Express applications
Latest version: 1.0.0

# Auth Core Utility

A shared authentication package that provides Auth0 integration utilities for both React and Express applications.

## Features

- 🔐 Auth0 integration with minimal setup
- ⚛️ React components and hooks
- 🚀 Express middleware for API protection
- 🔑 Role-based access control
- 📦 TypeScript support

## Installation

Install the package in your project:

```bash
npm install @lantern/auth-core-utility
# or
yarn add @lantern/auth-core-utility
```

## Usage

### React Setup

Wrap your app with `AuthProvider`:

```tsx
import { AuthProvider } from '@lantern/auth-core-utility';

function App() {
  return (
    <AuthProvider 
      config={{
        domain: 'your-auth0-domain',
        clientId: 'your-auth0-client-id',
        audience: 'your-auth0-audience'
      }}
    >
      <YourApp />
    </AuthProvider>
  );
}
```

Use authentication in components:

```tsx
import { useAuth, LoginButton, LogoutButton } from '@lantern/auth-core-utility';

function Profile() {
  const { user, isAuthenticated, isLoading } = useAuth();

  if (isLoading) return <div>Loading...</div>;
  if (!isAuthenticated) return <LoginButton />;

  return (
    <div>
      <h2>Welcome {user?.name}</h2>
      <LogoutButton />
    </div>
  );
}
```

### Express Setup

Protect your API routes:

```typescript
import { createAuthMiddleware, requireAuth, requireRole } from '@lantern/auth-core-utility';

const app = express();

// Setup auth middleware
const auth = createAuthMiddleware({
  auth0Domain: 'your-auth0-domain',
  audience: 'your-api-identifier'
});

// Protect routes
app.get('/api/protected', auth, requireAuth, (req, res) => {
  res.json({ message: 'Protected data' });
});

// Role-based protection
app.get('/api/admin', auth, requireRole('admin'), (req, res) => {
  res.json({ message: 'Admin only data' });
});
```

## API Reference

### React Components & Hooks

- `AuthProvider` - Main provider component
- `useAuth` - Hook for authentication state
- `LoginButton` - Pre-built login button
- `LogoutButton` - Pre-built logout button
- `ProtectedRoute` - Route guard component

### Express Middleware

- `createAuthMiddleware` - Creates JWT validation middleware
- `requireAuth` - Ensures request is authenticated
- `requireRole` - Validates user has required role

## Configuration

### AuthProvider Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| config.domain | string | Yes | Auth0 domain |
| config.clientId | string | Yes | Auth0 client ID |
| config.audience | string | No | API identifier |
| config.redirectUri | string | No | Redirect URL after login |

## Development

```bash
# Install dependencies
yarn install

# Build package
yarn build

# Run tests
yarn test
```

## Publishing the Package

### 1. Update package.json

```json
{
  "name": "@lantern/auth-core-utility",
  "version": "1.0.0",
  "private": false,
  "main": "dist/index.js",
  "module": "dist/index.esm.js",
  "types": "dist/index.d.ts",
  "files": [
    "dist"
  ],
  "publishConfig": {
    "access": "public"
  }
}
```

### 2. Build the Package
```bash
# Install dependencies
yarn install

# Build the package
yarn build
```

### 3. Publish to NPM Registry
```bash
# Login to NPM
npm login

# Publish package
npm publish --access public
```

## Using the Package

### In a React Project

1. Install the package:
```bash
# Using npm
npm install @lantern/auth-core-utility @auth0/auth0-react react-router-dom

# Using yarn
yarn add @lantern/auth-core-utility @auth0/auth0-react react-router-dom
```

2. Wrap your app with AuthProvider:
```tsx
// src/App.tsx or similar
import { AuthProvider } from '@lantern/auth-core-utility';

function App() {
  return (
    <AuthProvider 
      config={{
        domain: 'your-auth0-domain',
        clientId: 'your-auth0-client-id',
      }}
    >
      <YourApp />
    </AuthProvider>
  );
}
```

3. Use authentication in components:
```tsx
// src/components/Profile.tsx
import { useAuth, LoginButton } from '@lantern/auth-core-utility';

function Profile() {
  const { user, isAuthenticated } = useAuth();
  
  if (!isAuthenticated) {
    return <LoginButton />;
  }
  
  return <div>Welcome, {user?.name}!</div>;
}
```

### In an Express Backend

1. Install the package:
```bash
# Using npm
npm install @lantern/auth-core-utility express-jwt jwks-rsa

# Using yarn
yarn add @lantern/auth-core-utility express-jwt jwks-rsa
```

2. Use middleware:
```typescript
// src/server.ts
import express from 'express';
import { createAuthMiddleware, requireAuth } from '@lantern/auth-core-utility';

const app = express();

const auth = createAuthMiddleware({
  auth0Domain: 'your-auth0-domain',
  audience: 'your-api-identifier'
});

app.get('/api/protected', 
  auth,              // Validate JWT
  requireAuth,       // Check authentication
  (req, res) => {
    res.json({ message: 'Protected route' });
  }
);
```

## Local Development

If you're developing this package locally in a monorepo:

1. Link the package:
```bash
# From the package directory
yarn link

# From your project directory
yarn link @lantern/auth-core-utility
```

2. Watch for changes:
```bash
# From the package directory
yarn watch
```

## Local Development with a Linked Package

When using this package in another project locally via `npm link` or `yarn link`, you might encounter issues, especially with applications created with Create React App. This is often due to two main problems:

1.  **Multiple instances of React:** The linked package might resolve its own copy of React, while your main application uses another. This leads to the "Invalid hook call" runtime error.
2.  **Transpilation:** The source code of the linked package needs to be transpiled by your main application's build process.

### Linking the Package

First, build and link the `@lantern/auth-core-utility` package:

```bash
# In the auth-core-utility directory
npm run build
npm link
```

Then, in your main project, link to the utility:

```bash
# In your main project's directory
npm link @lantern/auth-core-utility
```

### Configuration for Create React App (with Craco)

If your project uses [Craco](https://craco.js.org/) to override the Create React App configuration, you can solve the local linking issues by modifying your `craco.config.js`.

Add the following configuration to your `craco.config.js` file. This ensures that:
- Only one copy of `react` and `react-dom` is used.
- The build system can import files from outside the `src` directory.
- The `babel-loader` transpiles the linked utility's source code.

```javascript
// craco.config.js
const path = require('path');
const { getLoader, loaderByName } = require('@craco/craco');

module.exports = {
  webpack: {
    alias: {
      react: path.resolve(__dirname, 'node_modules/react'),
      'react-dom': path.resolve(__dirname, 'node_modules/react-dom'),
    },
    configure: (webpackConfig) => {
      // Allow importing from outside of src
      const scopePluginIndex = webpackConfig.resolve.plugins.findIndex(
        ({ constructor }) => constructor && constructor.name === 'ModuleScopePlugin'
      );
      if (scopePluginIndex > -1) {
        webpackConfig.resolve.plugins.splice(scopePluginIndex, 1);
      }

      // Find the babel-loader and add the linked package's src directory
      const { isFound, match } = getLoader(webpackConfig, loaderByName('babel-loader'));
      if (isFound) {
        const include = Array.isArray(match.loader.include)
          ? match.loader.include
          : [match.loader.include];
        
        // The path to the linked package, adjust if necessary
        const linkedPackagePath = path.resolve(__dirname, 'node_modules/@lantern/auth-core-utility');
        
        match.loader.include = include.concat([
          path.join(linkedPackagePath, 'src'),
        ]);
      }

      return webpackConfig;
    },
  },
};
```

After making these changes, restart your development server. Your application should now work correctly with the linked local package.

## Versioning

We use semantic versioning:
- MAJOR version for incompatible API changes
- MINOR version for new functionality in a backwards compatible manner
- PATCH version for backwards compatible bug fixes

```bash
# Bump version
npm version patch -m "Bump version to %s"
npm publish
```

## License

MIT