Permissions and Guest Access Configuration
Overview
This document explains how we configured Backstage permissions to allow guest users to access catalog entities and templates, and how to make authenticated API calls.
Permission Policy Implementation
Custom Permission Policy
We replaced the default "allow-all" policy with a custom policy that provides controlled access for guest users.
Location: packages/backend/src/permissions/index.ts
Key Features
- Guest Read Access: Unauthenticated users can view catalog entities and templates
- Authenticated Write Access: Only authenticated users can create new entities
- Flexible Extension: Easy to add more granular permissions as needed
Guest User Configuration
Frontend Configuration
Guest authentication is enabled in the sign-in page
Backend Configuration
Guest users are automatically handled by the permission policy without additional configuration.
API Authentication
Getting a Guest Token
Guest users receive a token automatically when accessing the frontend. To get a token programmatically:
# Get guest token
curl -X POST http://localhost:7007/api/auth/guest/refresh \
-H "Content-Type: application/json" \
-d '{}' | jq -r '.backstageIdentity.token'
Using the Token for API Calls
# Store the token
TOKEN=$(curl -X POST http://localhost:7007/api/auth/guest/refresh \
-H "Content-Type: application/json" \
-d '{}' | jq -r '.backstageIdentity.token')
# Use the token for authenticated requests
curl http://localhost:7007/api/catalog/entities \
-H "Authorization: Bearer $TOKEN" | jq
Common API Endpoints
Catalog API
# List all entities
curl http://localhost:7007/api/catalog/entities \
-H "Authorization: Bearer $TOKEN"
# Get a specific entity
curl http://localhost:7007/api/catalog/entities/by-name/template/default/template-dns-record-v2 \
-H "Authorization: Bearer $TOKEN"
# Query entities with filters
curl "http://localhost:7007/api/catalog/entities?filter=kind=Template" \
-H "Authorization: Bearer $TOKEN"
Scaffolder API
# List available templates
curl http://localhost:7007/api/scaffolder/v2/templates \
-H "Authorization: Bearer $TOKEN"
# Get scaffolder actions
curl http://localhost:7007/api/scaffolder/v2/actions \
-H "Authorization: Bearer $TOKEN"
# List tasks (requires authentication)
curl http://localhost:7007/api/scaffolder/v2/tasks \
-H "Authorization: Bearer $TOKEN"
Testing as Claude
When testing API endpoints as Claude (or any automated system), follow this pattern:
1. Get Authentication Token
# Get guest token for testing
export BACKSTAGE_TOKEN=$(curl -s -X POST http://localhost:7007/api/auth/guest/refresh \
-H "Content-Type: application/json" \
-d '{}' | jq -r '.backstageIdentity.token')
echo "Token acquired: ${BACKSTAGE_TOKEN:0:20}..."
2. Test Catalog Access
# Test reading templates
curl -s http://localhost:7007/api/catalog/entities \
-H "Authorization: Bearer $BACKSTAGE_TOKEN" \
-H "Content-Type: application/json" \
| jq '.items[] | select(.kind == "Template") | {name: .metadata.name, version: .metadata.labels["openportal.dev/version"]}'
3. Test Template Rendering
# Get template with version label
curl -s http://localhost:7007/api/catalog/entities/by-name/template/default/template-dns-record-v2 \
-H "Authorization: Bearer $BACKSTAGE_TOKEN" \
| jq '{
name: .metadata.name,
title: .metadata.title,
version: .metadata.labels["openportal.dev/version"],
type: .spec.type
}'
Security Considerations
Current Implementation
- Read-Only Guest Access: Guests can view but not modify
- Token Expiration: Guest tokens expire after 1 hour
- CORS Protection: API is protected against cross-origin requests
Production Recommendations
- Disable Guest Access: Remove 'guest' from sign-in providers
- Implement RBAC: Use role-based access control for fine-grained permissions
- Add Rate Limiting: Protect APIs from abuse
- Enable HTTPS: Use TLS for all API communications
- Audit Logging: Track all API access and modifications
Debugging Permission Issues
Check Current Permissions
# Test permission for reading catalog
curl -X POST http://localhost:7007/api/permission/authorize \
-H "Authorization: Bearer $BACKSTAGE_TOKEN" \
-H "Content-Type: application/json" \
-d '[{
"permission": {
"type": "catalog-entity",
"name": "catalog.entity.read"
}
}]'
Common Issues
-
403 Forbidden: Token expired or invalid
- Solution: Refresh the token
-
401 Unauthorized: No token provided
- Solution: Include Authorization header
-
Permission Denied: Policy blocks the action
- Solution: Check permission policy implementation
Summary
The permission system allows:
- Guest users to browse the catalog and view templates
- Authenticated users to create and modify entities
- API access via Bearer tokens
- Flexible permission policies for different user roles
This configuration balances accessibility for development with security controls that can be tightened for production deployments.