Skip to content

SharePointAuth

SharePointAuth handles authentication for Microsoft Graph API access. It integrates with the SharePointAccessValidator for authorization checks, supports On-Behalf-Of (OBO) token exchange for delegated permissions, and includes in-memory token caching with a configurable TTL.

Import

import {
  SharePointAuth,
  SharePointAuthConfig,
  MicrosoftTokenProvider,
} from "@modernpath/agent-framework";

Constructor

new SharePointAuth(
  config: SharePointAuthConfig,
  tokenProvider: MicrosoftTokenProvider,
  accessValidator: SharePointAccessValidator,
)
Parameter Type Description
config SharePointAuthConfig Authentication configuration (tenant, client credentials, OBO settings).
tokenProvider MicrosoftTokenProvider Provider that returns a Microsoft access token for a given user.
accessValidator SharePointAccessValidator Customer-owned access validation hook (called before every token request).

SharePointAuthConfig

interface SharePointAuthConfig {
  tenantId?: string;
  clientId?: string;
  clientSecret?: string;
  useOnBehalfOfExchange?: boolean;
  scopes?: string[];
  cacheTTLms?: number;
}
Property Type Default Description
tenantId string -- Azure AD tenant ID. Required for OBO exchange.
clientId string -- Azure AD application (client) ID. Required for OBO exchange.
clientSecret string -- Azure AD client secret. Required for OBO exchange.
useOnBehalfOfExchange boolean false When true, performs an OAuth2 OBO exchange to get a Graph token from the upstream token. When false, assumes the token provider already returns a Graph-usable token.
scopes string[] ["https://graph.microsoft.com/.default"] Graph API scopes for OBO exchange.
cacheTTLms number 3600000 (1 hour) Token cache TTL in milliseconds.

MicrosoftTokenProvider

interface MicrosoftTokenProvider {
  getMicrosoftAccessToken(userId: number): Promise<string>;
}

Methods

getAccessToken

async getAccessToken(
  userId: number,
  auditingId: number,
  opts?: { forceRefresh?: boolean },
): Promise<string>

Returns a Microsoft Graph API access token for the given user/auditing context. Validates access first, then checks the cache, and finally obtains or exchanges a token.

Parameter Type Description
userId number The user requesting access.
auditingId number The auditing context.
opts.forceRefresh boolean When true, bypasses the cache and obtains a fresh token.

Throws: Error if access validation fails or token cannot be obtained.

clearCache

clearCache(userId: number, auditingId: number): void

Clears the cached token for a specific user/auditing combination.

Authentication Flow

sequenceDiagram
    participant Agent
    participant Auth as SharePointAuth
    participant AV as AccessValidator
    participant Cache as Token Cache
    participant TP as TokenProvider
    participant AAD as Azure AD

    Agent->>Auth: getAccessToken(userId, auditingId)
    Auth->>AV: validateAccess(userId, auditingId)
    AV-->>Auth: { valid: true }

    alt Cache hit
        Auth->>Cache: lookup(userId, auditingId)
        Cache-->>Auth: cached token
    else Cache miss
        Auth->>TP: getMicrosoftAccessToken(userId)
        TP-->>Auth: upstream token

        alt OBO enabled
            Auth->>AAD: OBO exchange (assertion, client credentials)
            AAD-->>Auth: Graph access token
        end

        Auth->>Cache: store(token, TTL)
    end

    Auth-->>Agent: access token

Code Example

import { SharePointAuth, SharePointAccessValidator } from "@modernpath/agent-framework";

// Customer-owned access validator
const accessValidator: SharePointAccessValidator = {
  async validateAccess(userId, auditingId) {
    const hasAccess = await checkUserPermissions(userId, auditingId);
    return hasAccess
      ? { valid: true }
      : { valid: false, reason: "User does not have SharePoint access" };
  },
};

// Token provider (wraps your existing auth system)
const tokenProvider = {
  async getMicrosoftAccessToken(userId: number) {
    return await authService.getMicrosoftToken(userId);
  },
};

// Create auth instance
const auth = new SharePointAuth(
  {
    tenantId: process.env.AZURE_TENANT_ID!,
    clientId: process.env.AZURE_CLIENT_ID!,
    clientSecret: process.env.AZURE_CLIENT_SECRET!,
    useOnBehalfOfExchange: true,
    cacheTTLms: 1800000, // 30 minutes
  },
  tokenProvider,
  accessValidator,
);

// Get token
const token = await auth.getAccessToken(userId, auditingId);

// Force refresh (e.g. after permission change)
const freshToken = await auth.getAccessToken(userId, auditingId, { forceRefresh: true });