
Research
Malicious npm Packages Impersonate Flashbots SDKs, Targeting Ethereum Wallet Credentials
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
@optimizely-opal/opal-ocp-sdk
Advanced tools
Optimizely Connect Platform (OCP) SDK for OPAL
A TypeScript SDK for building Opal tools in Optimizely Connect Platform. This SDK provides decorators, abstractions, and utilities to simplify the development.
@tool
and @interaction
decorators to easily register functionsToolFunction
for standardized request processingnpm install @optimizely-opal/opal-ocp-sdk
or
yarn add @optimizely-opal/opal-ocp-sdk
import { ToolFunction, tool, interaction, ParameterType, InteractionResult, OptiIdAuthData } from '@optimizely-opal/opal-ocp-sdk';
export class MyToolFunction extends ToolFunction {
// Register a simple tool without authentication
@tool({
name: 'create_task',
description: 'Creates a new task in the system',
endpoint: '/create-task',
parameters: [
{
name: 'title',
type: ParameterType.String,
description: 'The task title',
required: true
},
{
name: 'priority',
type: ParameterType.String,
description: 'Task priority level',
required: false
}
]
})
async createTask(params: { title: string; priority?: string }, authData?: OptiIdAuthData, bearerToken?: string) {
return {
id: '123',
title: params.title,
priority: params.priority || 'medium'
};
}
// Register a tool with OptiID authentication
@tool({
name: 'secure_task',
description: 'Creates a secure task with OptiID authentication',
endpoint: '/secure-task',
parameters: [
{
name: 'title',
type: ParameterType.String,
description: 'The task title',
required: true
}
],
authRequirements: [
{
provider: 'OptiID',
scopeBundle: 'tasks',
required: true
}
]
})
async createSecureTask(params: { title: string }, authData?: OptiIdAuthData, bearerToken?: string) {
if (!authData) {
throw new Error('OptiID authentication required');
}
const { customerId, instanceId, accessToken } = authData.credentials;
return {
id: '456',
title: params.title,
customerId,
instanceId
};
}
// Register an interaction
@interaction({
name: 'task_webhook',
endpoint: '/webhook/task'
})
async handleTaskWebhook(data: any): Promise<InteractionResult> {
return new InteractionResult(
`Task ${data.taskId} was updated`,
`https://app.example.com/tasks/${data.taskId}`
);
}
}
The perform
method handles all requests automatically and routes them to your registered tools and interactions.
Tools are functions that can be discovered and executed through the OCP platform. They:
Interactions are event handlers that process incoming data (like webhooks):
Supported parameter types:
enum ParameterType {
String = 'string',
Integer = 'integer',
Number = 'number',
Boolean = 'boolean',
List = 'list',
Dictionary = 'object'
}
The SDK supports authentication and authorization mechanisms:
OptiID provides user authentication with type safety. This is the only user authentication provider currently supported in Opal:
interface AuthRequirementConfig {
provider: string; // 'OptiID'
scopeBundle: string; // e.g., 'calendar', 'tasks'
required?: boolean; // default: true
}
The SDK automatically extracts Bearer tokens from the Authorization
header for tool authorization. When users register tools in Opal, they can specify a Bearer token that Opal will include in requests to validate the tool's identity:
@tool({
name: 'secure_tool',
description: 'Tool that validates requests from Opal',
endpoint: '/secure-endpoint',
parameters: [
{ name: 'data', type: ParameterType.String, description: 'Data to process', required: true }
]
})
async secureToolHandler(
params: { data: string },
authData?: OptiIdAuthData,
bearerToken?: string
) {
// Validate that the request is from an authorized Opal instance
const expectedToken = process.env.OPAL_TOOL_TOKEN;
if (!bearerToken || bearerToken !== expectedToken) {
throw new Error('Unauthorized: Invalid or missing Bearer token');
}
// Process the request knowing it's from a trusted Opal instance
return {
status: 'success',
data: `Processed: ${params.data}`,
authorizedBy: 'Opal'
};
}
You can use both OptiID authentication (for user context) and Bearer tokens (for tool authorization) together:
@tool({
name: 'dual_auth_tool',
description: 'Tool with both user authentication and tool authorization',
endpoint: '/dual-auth',
parameters: [],
authRequirements: [
{ provider: 'OptiID', scopeBundle: 'calendar', required: true }
]
})
async dualAuthOperation(
params: unknown,
authData?: OptiIdAuthData,
bearerToken?: string
) {
// First, validate the tool authorization (request from Opal)
const expectedToken = process.env.OPAL_TOOL_TOKEN;
if (!bearerToken || bearerToken !== expectedToken) {
throw new Error('Unauthorized: Invalid tool authorization');
}
// Then, validate user authentication
if (!authData) {
throw new Error('OptiID authentication required');
}
const { customerId, accessToken } = authData.credentials;
// Process with both tool and user authorization
return {
message: 'Authorized request processed',
customerId,
toolAuthorized: true
};
}
Bearer Token Usage:
All tool and interaction handler methods follow this signature pattern:
async handlerMethod(
params: TParams, // Tool parameters or interaction data
authData?: OptiIdAuthData, // OptiID user authentication data (if authenticated)
bearerToken?: string // Bearer token for tool authorization (if provided)
): Promise<TResult>
@tool(config: ToolConfig)
Registers a method as a discoverable tool.
interface ToolConfig {
name: string;
description: string;
parameters: ParameterConfig[];
authRequirements?: AuthRequirementConfig[];
endpoint: string;
}
@interaction(config: InteractionConfig)
Registers a method as an interaction handler.
interface InteractionConfig {
name: string;
endpoint: string;
}
ToolFunction
Abstract base class for OCP functions:
export abstract class ToolFunction extends Function {
public async perform(): Promise<Response>;
}
Extend this class and implement your OCP function. The perform
method automatically routes requests to registered tools.
Key model classes with generic type support:
Tool<TAuthData>
- Represents a registered tool with typed auth dataInteraction<TAuthData>
- Represents an interaction handler with typed auth dataParameter
- Defines tool parametersAuthRequirement
- Defines authentication needsInteractionResult
- Response from interactionsOptiIdAuthData
- OptiID specific authentication dataThe SDK automatically provides a discovery endpoint at /discovery
that returns all registered tools in the proper OCP format:
{
"functions": [
{
"name": "create_task",
"description": "Creates a new task in the system",
"parameters": [
{
"name": "title",
"type": "string",
"description": "The task title",
"required": true
},
{
"name": "priority",
"type": "string",
"description": "Task priority level",
"required": false
}
],
"endpoint": "/create-task",
"http_method": "POST"
},
{
"name": "secure_task",
"description": "Creates a secure task with OptiID authentication",
"parameters": [
{
"name": "title",
"type": "string",
"description": "The task title",
"required": true
}
],
"endpoint": "/secure-task",
"http_method": "POST",
"auth_requirements": [
{
"provider": "OptiID",
"scope_bundle": "tasks",
"required": true
}
]
}
]
}
yarn build
# Run tests
yarn test
# Run tests in watch mode
yarn test:watch
# Run tests with coverage
yarn test:coverage
yarn lint
import { ToolFunction, tool, interaction, ParameterType, OptiIdAuthData, InteractionResult } from '@optimizely-opal/opal-ocp-sdk';
export class AuthenticatedFunction extends ToolFunction {
// OptiID authentication example
@tool({
name: 'secure_operation',
description: 'Performs a secure operation with OptiID',
endpoint: '/secure',
parameters: [],
authRequirements: [{ provider: 'OptiID', scopeBundle: 'tasks', required: true }]
})
async secureOperation(params: unknown, authData?: OptiIdAuthData, bearerToken?: string) {
if (!authData) throw new Error('OptiID authentication required');
const { customerId, accessToken } = authData.credentials;
// Use OptiID credentials for API calls
return { success: true, customerId };
}
// Interaction with authentication example
@interaction({
name: 'authenticated_webhook',
endpoint: '/secure-webhook'
})
async handleSecureWebhook(data: any, authData?: OptiIdAuthData, bearerToken?: string): Promise<InteractionResult> {
if (!authData) {
return new InteractionResult('Authentication required for webhook processing');
}
const { customerId } = authData.credentials;
// Process webhook data with authentication context
return new InteractionResult(
`Webhook processed for customer ${customerId}: ${data.eventType}`,
`https://app.example.com/events/${data.eventId}`
);
}
}
FAQs
OCP SDK for Opal
The npm package @optimizely-opal/opal-ocp-sdk receives a total of 95 weekly downloads. As such, @optimizely-opal/opal-ocp-sdk popularity was classified as not popular.
We found that @optimizely-opal/opal-ocp-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.