New:Socket for Asana Is Now Available.Learn more
Get Started

@grantex/express

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@grantex/express

Express.js middleware for Grantex grant token verification and scope-based authorization

latest
Source
npmnpm
Version
0.1.5
Version published
Weekly downloads
21
250%
Maintainers
1
Weekly downloads
 
Created
Source

@grantex/express

Express.js middleware for Grantex grant token verification and scope-based authorization.

Verify Grantex JWTs and enforce scopes on any Express route with two lines of middleware.

Install

npm install @grantex/express @grantex/sdk express

Quick Start

import express from 'express';
import { requireGrantToken, requireScopes } from '@grantex/express';

const app = express();

const JWKS_URI = 'https://grantex-auth-dd4mtrt2gq-uc.a.run.app/.well-known/jwks.json';

// Verify the grant token on every /api request
app.use('/api', requireGrantToken({ jwksUri: JWKS_URI }));

// Enforce specific scopes per route
app.get('/api/calendar', requireScopes('calendar:read'), (req, res) => {
  // req.grant is fully typed — contains principalId, scopes, agentDid, etc.
  res.json({ principalId: req.grant.principalId, scopes: req.grant.scopes });
});

app.post('/api/email/send', requireScopes('email:send'), (req, res) => {
  res.json({ sent: true });
});

app.listen(3000);

Factory Pattern

Use createGrantex() to share configuration across routes:

import { createGrantex } from '@grantex/express';

const grantex = createGrantex({
  jwksUri: JWKS_URI,
  clockTolerance: 5,
});

app.get('/api/calendar', grantex.requireToken(), grantex.requireScopes('calendar:read'), handler);
app.get('/api/email',    grantex.requireToken(), grantex.requireScopes('email:read'),    handler);

API

requireGrantToken(options)

Express middleware that extracts and verifies a Grantex grant token from the request.

On success, populates req.grant with a VerifiedGrant object and calls next(). On failure, returns a JSON error response.

OptionTypeDefaultDescription
jwksUristringrequiredJWKS endpoint URL for token verification
tokenExtractor(req) => string | undefinedBearer headerCustom function to extract the token
clockTolerancenumber0Seconds of clock skew tolerance
audiencestringExpected JWT aud claim
onError(err, req, res, next) => voidJSON responseCustom error handler

requireScopes(...scopes)

Express middleware that checks the verified grant for required scopes. Must be used after requireGrantToken().

Returns 403 if any scope is missing.

createGrantex(options)

Factory that creates a middleware instance with shared options.

Returns { requireToken(overrides?), requireScopes(...scopes) }.

req.grant

After requireGrantToken() succeeds, req.grant contains:

FieldTypeDescription
tokenIdstringJWT jti claim
grantIdstringGrant record ID
principalIdstringEnd-user who authorized the agent
agentDidstringAgent's DID
developerIdstringDeveloper org ID
scopesstring[]Granted scopes
issuedAtnumberToken issued-at (epoch seconds)
expiresAtnumberToken expiry (epoch seconds)

Error Codes

CodeStatusMeaning
TOKEN_MISSING401No token found in request
TOKEN_INVALID401Token signature or format is invalid
TOKEN_EXPIRED401Token has expired
SCOPE_INSUFFICIENT403Token lacks required scopes

Custom Error Handling

app.use('/api', requireGrantToken({
  jwksUri: JWKS_URI,
  onError: (err, req, res, next) => {
    if (err.code === 'TOKEN_EXPIRED') {
      res.status(401).json({ error: 'Session expired', refreshUrl: '/auth/refresh' });
    } else {
      res.status(err.statusCode).json({ error: err.message });
    }
  },
}));

Custom Token Extraction

// Read from a cookie instead of the Authorization header
app.use('/api', requireGrantToken({
  jwksUri: JWKS_URI,
  tokenExtractor: (req) => req.cookies?.grantToken,
}));

// Read from a custom header
app.use('/api', requireGrantToken({
  jwksUri: JWKS_URI,
  tokenExtractor: (req) => req.headers['x-grant-token'] as string,
}));

// Read from a query parameter (useful for WebSocket upgrades)
app.use('/ws', requireGrantToken({
  jwksUri: JWKS_URI,
  tokenExtractor: (req) => req.query.token as string,
}));

TypeScript

The package exports all types for full TypeScript support:

import type { GrantexRequest, GrantexMiddlewareOptions, VerifiedGrant } from '@grantex/express';

Use GrantexRequest to type your route handlers:

import type { GrantexRequest } from '@grantex/express';
import type { Response } from 'express';

app.get('/api/me', requireGrantToken({ jwksUri }), (req: GrantexRequest, res: Response) => {
  // req.grant is typed without casting
  res.json({ user: req.grant.principalId });
});

Requirements

  • Node.js 18+
  • Express 4.18+
  • @grantex/sdk >= 0.1.0

License

Apache-2.0

Keywords

grantex

FAQs

Package last updated on 25 Jun 2026

Related posts