Function Integration
Access authenticated user context in your serverless functions.
Access authenticated user context in your serverless functions.
Receiving User Context
When a function is invoked with an auth user token, the user context is injected into the event:
exports.handler = async (event) => {
// Check if user is authenticated
if (!event.__volcano_auth) {
return {
statusCode: 401,
body: JSON.stringify({ error: 'Unauthorized' })
};
}
// Access user information
const { user_id, email, project_id, role } = event.__volcano_auth;
console.log('User ID:', user_id);
console.log('Email:', email);
console.log('Project:', project_id);
console.log('Role:', role); // "authenticated" or "anonymous"
};User Context Fields
event.__volcano_auth = {
user_id: 'uuid', // Auth user's unique ID
email: 'user@example.com', // User's email
project_id: 'uuid', // Project the user belongs to
role: 'authenticated' // "authenticated" or "anonymous"
}Role values:
"authenticated"- User signed up with email/password or OAuth"anonymous"- Guest user (created viasignUpAnonymous())
Note: Both user types have a user_id. When an anonymous user converts to authenticated, their user_id remains the same - preserving all their data.
With service key
If invoked with a service key (not auth user token), __volcano_auth is undefined:
if (!event.__volcano_auth) {
// Invoked with service key (service-to-service)
// Or no authentication
}Handling Different User Types
exports.handler = async (event) => {
const auth = event.__volcano_auth;
if (!auth) {
return { statusCode: 401, body: 'Unauthorized' };
}
// Handle based on user type
if (auth.role === 'anonymous') {
// Guest user - maybe limit features
return {
statusCode: 200,
body: JSON.stringify({
data: limitedData,
suggestion: 'Create an account to unlock all features'
})
};
}
// Full authenticated user
return {
statusCode: 200,
body: JSON.stringify({ data: fullData })
};
};Database Integration
Set PostgreSQL session variables for Row-Level Security:
const { Pool } = require('pg');
const pool = new Pool({
connectionString: process.env.DATABASE_URL
});
exports.handler = async (event) => {
if (!event.__volcano_auth) {
return { statusCode: 401, body: 'Unauthorized' };
}
const { user_id, email, role } = event.__volcano_auth;
const client = await pool.connect();
try {
// Set user context in PostgreSQL session
await client.query('SET request.jwt.claim.sub = $1', [user_id]);
await client.query('SET request.jwt.claim.email = $1', [email]);
await client.query('SET request.jwt.claim.role = $1', [role]);
// Now RLS policies work automatically
// Works for both authenticated and anonymous users
const result = await client.query('SELECT * FROM posts');
return {
statusCode: 200,
body: JSON.stringify(result.rows)
};
} finally {
client.release();
}
};Complete Example
const { Pool } = require('pg');
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
exports.handler = async (event) => {
// 1. Verify authentication
if (!event.__volcano_auth) {
return { statusCode: 401, body: 'Unauthorized' };
}
const { user_id, email, role } = event.__volcano_auth;
// 2. Get database connection
const client = await pool.connect();
try {
// 3. Set user context for RLS
await client.query('SET request.jwt.claim.sub = $1', [user_id]);
await client.query('SET request.jwt.claim.role = $1', [role]);
// 4. Handle different actions
const { action } = event;
switch (action) {
case 'create_post':
await client.query(
'INSERT INTO posts (title, content) VALUES ($1, $2)',
[event.title, event.content]
// user_id automatically set by trigger
);
return { statusCode: 201, body: 'Post created' };
case 'get_posts':
// RLS automatically filters to user's posts
// Works for both anonymous and authenticated users
const result = await client.query('SELECT * FROM posts');
return {
statusCode: 200,
body: JSON.stringify(result.rows)
};
default:
return { statusCode: 400, body: 'Unknown action' };
}
} finally {
client.release();
}
};Environment Variables
Volcano automatically injects these into your functions:
process.env.DATABASE_URL // Your database connection string
// Plus any variables you configureSee Also
- Row-Level Security - Secure data at database level
- Auth Helpers - Using auth.uid(), auth.email()
- Examples - Complete working examples