Overview
Credentials are authentication definitions that allow your plugin to securely access external services on behalf of users. The SDK provides a type-safe way to define credential schemas and implement authentication logic.
Defining Credentials
Use the addCredential method to register a credential definition:
plugin . addCredential ({
name: "github_api_key" ,
display_name: {
en_US: "GitHub API Key"
},
description: {
en_US: "Your GitHub personal access token"
},
schema: {
type: "object" ,
properties: {
api_key: {
type: "string" ,
title: "API Key" ,
description: "Your GitHub personal access token"
}
},
required: [ "api_key" ]
},
authenticate : async ({ args }) => {
const { credential } = args
// Validate the credential by making a test API call
const response = await fetch ( "https://api.github.com/user" , {
headers: {
Authorization: `token ${ credential . api_key } `
}
})
if ( ! response . ok ) {
throw new Error ( "Invalid GitHub API key" )
}
const user = await response . json ()
return {
valid: true ,
username: user . login
}
}
})
Credential Schema
Unique identifier for the credential. Used when referencing the credential in tools.
Localized display names shown to users in the UI.
Localized descriptions explaining what the credential is for.
JSON Schema defining the structure of the credential. Must be a valid JSON Schema object.
Optional function to validate the credential. Called when users add or update credentials.
Authentication Function
The authenticate function is optional but highly recommended. It validates credentials when users first add them:
Function Signature
authenticate : async ({ args }: {
args: {
credential: Record < string , any>
extra: Record < string , any>
}
}) => Promise < any >
Parameters
The credential data provided by the user, matching your schema definition.
Additional metadata or context passed from the Hub Server.
Return Value
You can return any data from the authenticate function. Common patterns include:
// Simple validation
return { valid: true }
// Validation with user info
return {
valid: true ,
username: "john_doe" ,
email: "[email protected] "
}
// Store additional metadata
return {
valid: true ,
account_id: "12345" ,
permissions: [ "read" , "write" ]
}
The authentication function should throw an error if validation fails. The error message will be shown to the user.
Credential Types
The SDK supports various credential types through JSON Schema:
API Key Credentials
{
name : "api_key" ,
display_name : { en_US : "API Key" },
schema : {
type : "object" ,
properties : {
key : {
type : "string" ,
format : "password" // Hides input in UI
}
},
required : [ "key" ]
}
}
OAuth-style Credentials
{
name : "oauth_token" ,
display_name : { en_US : "OAuth Token" },
schema : {
type : "object" ,
properties : {
access_token : { type : "string" },
refresh_token : { type : "string" },
expires_at : { type : "number" }
},
required : [ "access_token" ]
},
authenticate : async ({ args }) => {
// Verify token and optionally refresh
const { credential } = args
if ( credential . expires_at < Date . now ()) {
// Token expired - could refresh here
throw new Error ( "Token has expired" )
}
return { valid: true }
}
}
Username/Password Credentials
{
name : "basic_auth" ,
display_name : { en_US : "Username and Password" },
schema : {
type : "object" ,
properties : {
username : { type : "string" },
password : {
type : "string" ,
format : "password"
}
},
required : [ "username" , "password" ]
},
authenticate : async ({ args }) => {
const { credential } = args
// Verify credentials with the service
const isValid = await verifyCredentials (
credential . username ,
credential . password
)
if ( ! isValid ) {
throw new Error ( "Invalid username or password" )
}
return { valid: true , username: credential . username }
}
}
Complex Credentials
{
name : "aws_credentials" ,
display_name : { en_US : "AWS Credentials" },
schema : {
type : "object" ,
properties : {
access_key_id : { type : "string" },
secret_access_key : {
type : "string" ,
format : "password"
},
region : {
type : "string" ,
enum : [ "us-east-1" , "us-west-2" , "eu-west-1" ],
default : "us-east-1"
},
session_token : {
type : "string" ,
description : "Optional session token for temporary credentials"
}
},
required : [ "access_key_id" , "secret_access_key" , "region" ]
}
}
When a tool requires credentials, they are automatically passed by the Hub Server:
plugin . addTool ({
name: "list_repositories" ,
display_name: { en_US: "List Repositories" },
credentials: [ "github_api_key" ], // Reference credential by name
invoke : async ({ args }) => {
const { credentials , parameters } = args
// Access the credential data
const apiKey = credentials . github_api_key . api_key
const response = await fetch ( "https://api.github.com/user/repos" , {
headers: {
Authorization: `token ${ apiKey } `
}
})
return await response . json ()
}
})
Authentication Flow
When a user adds a credential:
User fills in the credential form based on your schema
Hub Server sends credential_auth_spec message to your plugin
Plugin resolves the credential definition from the registry
Plugin calls the authenticate function with the credential data
Plugin sends response back to Hub Server:
credential_auth_spec_response on success
credential_auth_spec_error on failure
// Internal SDK implementation (for reference)
channel . on ( "credential_auth_spec" , async ( message ) => {
const { request_id , credential_name , credential , extra } = message
try {
const definition = registry . resolve ( "credential" , credential_name )
if ( ! definition . authenticate ) {
throw new Error ( "Credential authenticate method is not implemented" )
}
const result = await definition . authenticate ({
args: { credential , extra }
})
channel . push ( "credential_auth_spec_response" , {
request_id ,
data: result
})
} catch ( error ) {
channel . push ( "credential_auth_spec_error" , {
request_id ,
message: error . message
})
}
})
Schema Validation
Credential definitions are validated using the CredentialDefinitionSchema from @choiceopen/atomemo-plugin-schema:
import { CredentialDefinitionSchema } from "@choiceopen/atomemo-plugin-schema/schemas"
const definition = CredentialDefinitionSchema . parse ( credential )
registry . register ( "credential" , definition )
If validation fails, a Zod error will be thrown with details about what’s invalid.
Best Practices
Always implement authentication
While optional, the authenticate function provides crucial validation and improves user experience by catching invalid credentials early.
Use appropriate field types
Use format: "password" for sensitive fields to ensure they’re hidden in the UI.
Provide clear error messages
When authentication fails, throw errors with clear, actionable messages that help users fix the issue.
For OAuth-style credentials, implement token refresh logic or clear error messages about expired tokens.
Test with invalid credentials
Always test your authentication function with invalid credentials to ensure proper error handling.
Security Considerations
Never log or expose credential data. Credentials should only be used for authentication and API calls, never stored in logs or error messages.
Credentials are stored securely by the Hub Server
Your plugin only receives credentials when executing tools that require them
Use HTTPS/WSS for all credential transmission
Implement proper error handling to avoid leaking credential information
Next Steps
Tools Learn how to use credentials in your tool implementations
Registry Understand how credentials are registered and resolved