Authorization in Geode provides comprehensive control over who can access your graph data and what operations they can perform. Building on authentication (verifying identity), authorization determines what authenticated users are permitted to do within the database. Geode implements a multi-layered authorization system combining role-based access control (RBAC), object-level permissions, and row-level security (RLS) to deliver enterprise-grade access management.
Authorization Architecture
Geode’s authorization system operates at multiple levels to provide defense-in-depth:
- System Level: Controls server administration, user management, and global operations
- Graph Level: Controls access to entire graphs (create, read, write, delete)
- Label Level: Controls access to specific node and relationship types
- Property Level: Controls access to individual properties within nodes and relationships
- Row Level: Controls access to specific data rows based on runtime conditions
Authorization decisions are evaluated in order, with more specific rules taking precedence over general rules.
Permission Types
Geode supports the following permission types:
Data Permissions
-- SELECT: Read data from nodes, relationships, and properties
GRANT SELECT ON GRAPH social_network TO analyst;
-- INSERT: Create new nodes and relationships
GRANT INSERT ON :User TO application_service;
-- UPDATE: Modify existing properties
GRANT UPDATE ON :User TO user_management;
-- DELETE: Remove nodes, relationships, or properties
GRANT DELETE ON :TempData TO cleanup_service;
-- MERGE: Create or update data (combines INSERT and UPDATE)
GRANT MERGE ON :Session TO session_manager;
Schema Permissions
-- CREATE: Create new graphs, labels, or constraints
GRANT CREATE GRAPH TO schema_admin;
GRANT CREATE CONSTRAINT TO developer;
-- ALTER: Modify schema definitions
GRANT ALTER ON GRAPH analytics TO data_architect;
-- DROP: Remove schema elements
GRANT DROP CONSTRAINT TO schema_admin;
Administrative Permissions
-- ADMIN: Full administrative access
GRANT ADMIN ON DATABASE TO dba_team;
-- EXECUTE: Execute stored procedures and functions
GRANT EXECUTE ON PROCEDURE export_data TO analyst;
-- BACKUP: Create and restore backups
GRANT BACKUP ON DATABASE TO backup_service;
Granting Permissions
Permissions are granted using the GRANT statement. Permissions can be granted to users directly or to roles (recommended).
Basic Grant Syntax
-- Grant to a user
GRANT SELECT ON GRAPH customers TO alice;
-- Grant to a role
GRANT SELECT, INSERT ON GRAPH customers TO data_entry;
-- Grant multiple permissions at once
GRANT SELECT, INSERT, UPDATE, DELETE ON GRAPH inventory TO warehouse_manager;
Granting with Grant Option
Allow recipients to further grant the permission to others:
-- Alice can grant SELECT to other users
GRANT SELECT ON GRAPH customers TO alice WITH GRANT OPTION;
-- Team lead can delegate permissions
GRANT INSERT ON :Order TO team_lead WITH GRANT OPTION;
Granting All Permissions
-- Grant all data permissions on a graph
GRANT ALL ON GRAPH analytics TO data_scientist;
-- Grant all permissions on specific labels
GRANT ALL ON :Product, :Category TO product_manager;
Denying Permissions
The DENY statement explicitly prevents access, overriding any granted permissions:
-- Prevent access to sensitive data
DENY SELECT ON :Salary TO general_employee;
-- Block modification of historical records
DENY UPDATE, DELETE ON :AuditLog TO ROLE application;
-- Deny specific property access
DENY SELECT(ssn, credit_score) ON :Customer TO marketing;
Deny Precedence
Deny rules take precedence over grant rules at the same specificity level:
-- User has analyst role with broad SELECT
GRANT ROLE analyst TO bob;
GRANT SELECT ON GRAPH company TO analyst;
-- But Bob specifically cannot see salary data
DENY SELECT(salary) ON :Employee TO bob;
-- Bob can read employees but not their salaries
Revoking Permissions
Remove previously granted permissions:
-- Revoke specific permission
REVOKE SELECT ON GRAPH customers FROM alice;
-- Revoke multiple permissions
REVOKE INSERT, UPDATE ON :Order FROM data_entry;
-- Revoke grant option only (keeps the permission)
REVOKE GRANT OPTION FOR SELECT ON GRAPH customers FROM alice;
-- Revoke all permissions from user/role
REVOKE ALL ON GRAPH analytics FROM consultant;
Label-Level Authorization
Control access to specific node and relationship types:
-- Different teams access different node types
GRANT SELECT ON :Customer TO sales_team;
GRANT SELECT ON :Product TO inventory_team;
GRANT SELECT ON :Employee TO hr_team;
-- Relationship type permissions
GRANT SELECT ON :PURCHASED TO analytics;
GRANT INSERT ON :FOLLOWS TO social_features;
-- Restrict access to sensitive labels
DENY SELECT ON :InternalMemo TO external_contractor;
Pattern-Based Label Permissions
Use wildcards for managing permissions across multiple labels:
-- Grant access to all Public* labels
GRANT SELECT ON :Public* TO public_api;
-- Grant access to all labels in a namespace
GRANT SELECT ON :hr_* TO hr_department;
-- Deny access to all Internal* labels
DENY SELECT ON :Internal* TO external_user;
Property-Level Authorization
Fine-grained control over individual properties:
-- Grant access to specific properties only
GRANT SELECT(name, email, department) ON :Employee TO directory_service;
-- Hide sensitive properties
DENY SELECT(salary, performance_rating, ssn) ON :Employee TO general_user;
-- Allow updating specific properties
GRANT UPDATE(email, phone, address) ON :Employee TO self_service;
-- Block modification of system properties
DENY UPDATE(created_at, created_by, internal_id) ON :* TO application;
Column Masking
Automatically mask sensitive data for unauthorized users:
-- Create masking policy for credit cards
CREATE MASK credit_card_mask ON :Payment.card_number
AS CASE
WHEN current_user_has_role('pci_admin') THEN card_number
ELSE '****-****-****-' || right(card_number, 4)
END;
-- Apply masking to SSN
CREATE MASK ssn_mask ON :Person.ssn
AS CASE
WHEN current_user_has_role('hr_admin') THEN ssn
ELSE '***-**-' || right(ssn, 4)
END;
Graph-Level Authorization
Control access to entire graphs:
-- Grant read access to a graph
GRANT SELECT ON GRAPH production TO reporting;
-- Grant full access to development graph
GRANT ALL ON GRAPH development TO developers;
-- Prevent access to sensitive graph
DENY ALL ON GRAPH executive_compensation TO general_employee;
-- Control graph management
GRANT CREATE GRAPH TO data_architect;
GRANT DROP GRAPH TO dba;
Multi-Graph Authorization
When working with multiple graphs:
-- Grant access to multiple graphs
GRANT SELECT ON GRAPH customers, orders, inventory TO fulfillment;
-- Different permission levels per graph
GRANT SELECT ON GRAPH production TO analyst;
GRANT ALL ON GRAPH analytics TO analyst;
-- Cross-graph query permissions
GRANT SELECT ON GRAPH * TO global_reporting;
Authorization with Stored Procedures
Control execution of stored procedures and functions:
-- Grant execute permission
GRANT EXECUTE ON PROCEDURE calculate_recommendations TO recommendation_engine;
-- Grant with elevated privileges
CREATE PROCEDURE admin_task()
SECURITY DEFINER -- Runs with creator's privileges
AS $$
MATCH (u:User) WHERE u.inactive FOR '365 days'
DETACH DELETE u
$$;
-- Grant to run procedures with caller's privileges
CREATE PROCEDURE user_report(user_id: STRING)
SECURITY INVOKER -- Runs with caller's privileges
AS $$
MATCH (u:User {id: $user_id}) RETURN u
$$;
Dynamic Authorization
Authorization decisions that depend on runtime context:
-- Time-based access control
CREATE POLICY business_hours_only ON :Transaction
FOR ALL
TO standard_user
USING (EXTRACT(HOUR FROM current_timestamp()) BETWEEN 9 AND 17);
-- Location-based access
CREATE POLICY regional_access ON :Customer
FOR SELECT
TO regional_manager
USING (c.region = current_user_property('assigned_region'));
-- Data classification-based access
CREATE POLICY classification_access ON :Document
FOR SELECT
TO analyst
USING (d.classification_level <= current_user_property('clearance_level'));
Authorization Inheritance
Role Hierarchy
Roles can inherit from other roles:
-- Create base role
CREATE ROLE employee;
GRANT SELECT ON :PublicInfo TO employee;
-- Create role that inherits from employee
CREATE ROLE manager INHERITS employee;
GRANT SELECT ON :TeamPerformance TO manager;
-- Managers automatically have employee permissions plus their own
Permission Inheritance Chain
-- Build inheritance chain
CREATE ROLE viewer;
CREATE ROLE editor INHERITS viewer;
CREATE ROLE admin INHERITS editor;
-- Assign permissions at appropriate levels
GRANT SELECT ON GRAPH main TO viewer;
GRANT INSERT, UPDATE ON GRAPH main TO editor;
GRANT DELETE, ADMIN ON GRAPH main TO admin;
-- Admin has all permissions: SELECT, INSERT, UPDATE, DELETE, ADMIN
Viewing Authorization
Check Current Permissions
-- Show permissions for current user
SHOW GRANTS FOR CURRENT USER;
-- Show permissions for specific user
SHOW GRANTS FOR alice;
-- Show permissions for a role
SHOW GRANTS FOR ROLE analyst;
-- Show effective permissions (including inherited)
SHOW EFFECTIVE GRANTS FOR bob;
System Views
-- View all permission grants
SELECT * FROM system.privileges
WHERE grantee = 'analyst';
-- View role memberships
SELECT * FROM system.role_members
WHERE member = 'alice';
-- View all deny rules
SELECT * FROM system.privileges
WHERE is_deny = true;
Authorization Best Practices
1. Use Role-Based Access Control
-- DO: Grant to roles, assign roles to users
CREATE ROLE report_viewer;
GRANT SELECT ON GRAPH reports TO report_viewer;
GRANT ROLE report_viewer TO alice, bob, charlie;
-- DON'T: Grant directly to users
-- GRANT SELECT ON GRAPH reports TO alice;
-- GRANT SELECT ON GRAPH reports TO bob;
-- GRANT SELECT ON GRAPH reports TO charlie;
2. Implement Least Privilege
-- Start with no permissions
CREATE USER new_analyst;
-- Grant only what's needed
GRANT SELECT ON GRAPH analytics TO new_analyst;
GRANT SELECT(name, email, department) ON :Employee TO new_analyst;
-- Review and adjust as needed
SHOW GRANTS FOR new_analyst;
3. Use Deny for Explicit Restrictions
-- Broad grant with specific deny
GRANT SELECT ON GRAPH company TO analyst;
DENY SELECT ON :Salary TO analyst;
DENY SELECT ON :ExecutiveCompensation TO analyst;
4. Regular Permission Audits
-- Find users with admin privileges
SELECT grantee FROM system.privileges
WHERE privilege = 'ADMIN';
-- Find unused permissions
SELECT p.grantee, p.privilege, p.object_name
FROM system.privileges p
LEFT JOIN system.access_log a
ON p.grantee = a.username AND p.object_name = a.object_name
WHERE a.last_access IS NULL
OR a.last_access < current_timestamp() - INTERVAL '90 days';
5. Separate Development and Production
-- Production: Minimal permissions
GRANT SELECT ON GRAPH production TO application;
-- Development: Broader permissions
GRANT ALL ON GRAPH development TO developer;
-- Prevent production modification from dev accounts
DENY INSERT, UPDATE, DELETE ON GRAPH production TO developer;
Authorization Configuration
Server-Level Settings
# Enable authorization enforcement
geode serve --authorization-enabled=true
# Set default deny (no implicit permissions)
geode serve --default-deny=true
# Enable permission caching for performance
geode serve --permission-cache-size=10000 \
--permission-cache-ttl=300s
# Log all authorization decisions
geode serve --log-authorization=true
Configuration File
# geode.yaml
authorization:
enabled: true
default_deny: true
permission_cache:
enabled: true
size: 10000
ttl_seconds: 300
audit:
log_grants: true
log_denies: true
log_checks: false # Can be verbose
Troubleshooting Authorization
Permission Denied Errors
-- Check user's current permissions
SHOW GRANTS FOR current_user();
-- Check effective permissions including inheritance
SHOW EFFECTIVE GRANTS FOR alice;
-- Check for deny rules
SELECT * FROM system.privileges
WHERE grantee IN (SELECT role FROM system.role_members WHERE member = 'alice')
AND is_deny = true;
Debugging Authorization
# Enable verbose authorization logging
geode serve --authorization-debug=true
# Log shows:
# [AUTH] User alice checking SELECT on :Customer
# [AUTH] Found grant via role analyst
# [AUTH] No deny rules match
# [AUTH] Authorization: ALLOW
Common Issues
- Inherited deny blocking access: Check parent roles for deny rules
- Missing role assignment: Verify user has required roles
- Property-level deny: Check for property restrictions
- Graph-level restriction: Verify graph access before label access
Authorization Patterns
Multi-Tenant Authorization
-- Isolate tenant data
CREATE POLICY tenant_isolation ON :*
FOR ALL
TO application
USING (tenant_id = current_user_property('tenant_id'));
-- Tenant admins see their own tenant only
CREATE POLICY tenant_admin_access ON :User
FOR ALL
TO tenant_admin
USING (tenant_id = current_user_property('tenant_id'));
Hierarchical Data Access
-- Manager sees direct reports
CREATE POLICY manager_sees_reports ON :Employee
FOR SELECT
TO manager
USING (manager_id = current_user_property('employee_id')
OR employee_id = current_user_property('employee_id'));
-- Executive sees entire organization
GRANT SELECT ON :Employee TO executive;
Time-Limited Access
-- Temporary elevated access
GRANT SELECT ON :AuditData TO auditor
VALID UNTIL '2026-03-31';
-- Audit-period access
CREATE POLICY audit_window ON :FinancialRecord
FOR SELECT
TO auditor
USING (record_date BETWEEN '2025-01-01' AND '2025-12-31');
Related Topics
- Role-Based Access Control - RBAC implementation details
- Row-Level Security - Fine-grained row-level access policies
- Authentication - User identity verification
- Audit Logging - Tracking authorization decisions
- Compliance - Regulatory compliance requirements
- Security - Security overview and best practices
Further Reading
- Security Architecture - Deep dive into security design
- Authorization Best Practices - Production deployment guide
- Session Management - Session and context security
- Enterprise Security Whitepaper - Comprehensive security documentation