# delfi-pkce-auth

Simple PKCE authentication helper for Node.js apps integrating with DELFI / CSI OAuth 2.0.

## Installation

Install the package by itself:

```bash
npm install delfi-pkce-auth
```

If you are starting from the Express example in this README, install all required dependencies with:

```bash
npm install express express-session delfi-pkce-auth
```

## Features

- Generate a PKCE code verifier
- Generate an `S256` PKCE code challenge
- Build the DELFI authorization URL
- Exchange an authorization code for a token
- Read a stored access token from an Express session

## Quick Start

```js
const express = require("express");
const session = require("express-session");
const pkceAuth = require("delfi-pkce-auth");

const app = express();

app.use(session({
  secret: "replace-me",
  resave: false,
  saveUninitialized: true
}));

pkceAuth.initialize({
  clientId: process.env.DELFI_CLIENT_ID,
  redirectUri: "http://localhost:3000/callback",
  audience: process.env.DELFI_AUDIENCE // this is optional
});

app.get("/login", (req, res) => {
  const codeVerifier = pkceAuth.generateCodeVerifier();
  const codeChallenge = pkceAuth.generateCodeChallenge(codeVerifier);

  req.session.codeVerifier = codeVerifier;
  res.redirect(pkceAuth.getAuthUrl(codeChallenge));
});

app.get("/callback", async (req, res) => {
  try {
    const tokenData = await pkceAuth.exchangeCodeForToken(
      req.query.code,
      req.session.codeVerifier
    );

    req.session.token = tokenData.access_token;
    console.log(req.session.token);
    res.send("Authentication successful");
  } catch (error) {
    res.status(500).send(error.message);
  }
});

app.listen(3000);
```

## Configuration

Call `initialize()` once before calling any other package functions.

```js
pkceAuth.initialize({
  clientId: "your-client-id",
  redirectUri: "http://localhost:3000/callback",
  audience: "fwk-drillplan.slbservice.com" // correct audience for calling Drillplan
});
```

### Options

| Option | Required | Description |
| --- | --- | --- |
| `clientId` | Yes | OAuth client ID |
| `redirectUri` | Yes | Redirect URI registered for the client |
| `audience` | No | Added to the authorization request scope after `openid` |

## API

### `initialize(config)`

Stores package configuration for later calls.

### `generateCodeVerifier()`

Returns a random PKCE code verifier string.

### `generateCodeChallenge(codeVerifier)`

Returns an `S256` PKCE code challenge for the supplied verifier.

### `getAuthUrl(codeChallenge)`

Builds the authorization URL using:

- `response_type=code`
- `client_id`
- `redirect_uri`
- `code_challenge`
- `code_challenge_method=S256`
- `scope=openid` plus `audience` if provided

### `exchangeCodeForToken(code, codeVerifier)`

Exchanges the authorization code for token data from `https://csi.slb.com/v2/token`.

The token request includes:

- `grant_type=authorization_code`
- `client_id`
- `code`
- `redirect_uri`
- `code_verifier`

Returns the parsed JSON token response.

### `getAccessToken(req)`

Returns `req.session.token` if present, otherwise `null`.

## Notes

- `audience` is optional
- authorization and token endpoints are currently fixed to:
  - `https://csi.slb.com/v2/auth`
  - `https://csi.slb.com/v2/token`
- this package uses `node-fetch@2`

## License

MIT
