Token导航 LogoToken导航TokenDH.com
开发需要联网github未标认证来源可访问许可证需确认审计通过

bknd-public-vs-authbknd 公共与身份验证

Agent Skill

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。

总安装

303

周安装

13

GitHub Stars

3

下载量

106
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:bknd-public-vs-auth(bknd 公共与身份验证)
来源仓库:https://github.com/cameronapak/bknd-skills
仓库路径:skills/bknd-public-vs-auth
安装命令:
npx skills add https://github.com/cameronapak/bknd-skills --skill bknd-public-vs-auth
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/cameronapak/bknd-skills --skill bknd-public-vs-auth

简介

用于配置哪些数据或接口允许公开访问或需认证后使用。

  • 可设置匿名角色和实体级访问规则来控制信息暴露范围。
  • 通过代码定义默认角色权限,UI 仅用于查看现有配置。
  • 需结合 guard 系统和角色模型进行细粒度控制。
  • bknd-public-vs-auth 属于开发类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Public vs Authenticated Access

Configure which data and endpoints are publicly accessible vs require authentication.

Prerequisites

  • Bknd project with code-first configuration
  • Auth enabled (auth: {enabled: true})
  • Guard enabled (guard: {enabled: true})
  • Basic understanding of roles (see bknd-create-role)

When to Use UI Mode

  • Viewing current role configurations
  • Inspecting permission assignments

UI steps: Admin Panel > Auth > Roles

Note: Access configuration requires code mode.

When to Use Code Mode

  • Setting up anonymous/default role for public access
  • Configuring entity-specific access rules
  • Creating mixed public/private data patterns
  • Building closed (auth-required) systems

Core Concept: Default Role

Bknd uses the default role to determine what unauthenticated users can access:

User makes request → Has token? → Yes → Use user's role
                              → No  → Use default role (is_default: true)
                                    → No default? → ACCESS DENIED

Code Approach

Step 1: Fully Public (Read-Only)

Allow unauthenticated users to read all data:

import { serve } from "bknd/adapter/bun";
import { em, entity, text } from "bknd";

const schema = em({
  posts: entity("posts", { title: text().required() }),
});

serve({
  connection: { url: "file:data.db" },
  config: {
    data: schema.toJSON(),
    auth: {
      enabled: true,
      guard: { enabled: true },
      roles: {
        // Public role - anyone can read
        anonymous: {
          is_default: true,
          implicit_allow: false,
          permissions: ["data.entity.read"],
        },
        // Authenticated users can create/update
        user: {
          implicit_allow: false,
          permissions: [
            "data.entity.read",
            "data.entity.create",
            "data.entity.update",
          ],
        },
      },
    },
  },
});

Result:

  • GET /api/data/posts - Works without auth
  • POST /api/data/posts - Requires auth
  • PATCH /api/data/posts/1 - Requires auth

Step 2: Fully Private (Auth Required)

Require authentication for all access:

{
  auth: {
    enabled: true,
    guard: { enabled: true },
    allow_register: true,
    default_role_register: "user",
    roles: {
      admin: { implicit_allow: true },
      user: {
        implicit_allow: false,
        permissions: [
          "data.entity.read",
          "data.entity.create",
          "data.entity.update",
        ],
      },
      // NO default role - unauthenticated users get nothing
    },
  },
}

Result: All /api/data/* endpoints return 403 without authentication.

Step 3: Entity-Specific Public Access

Make some entities public, others private:

{
  auth: {
    enabled: true,
    guard: { enabled: true },
    roles: {
      anonymous: {
        is_default: true,
        implicit_allow: false,
        permissions: [
          // Only posts are public
          {
            permission: "data.entity.read",
            effect: "allow",
            policies: [{
              condition: { entity: "posts" },
              effect: "allow",
            }],
          },
        ],
      },
      user: {
        implicit_allow: false,
        permissions: [
          "data.entity.read",   // Read all entities
          "data.entity.create",
          "data.entity.update",
        ],
      },
    },
  },
}

Result:

  • GET /api/data/posts - Public
  • GET /api/data/users - Requires auth
  • GET /api/data/comments - Requires auth

Step 4: Multiple Public Entities

Expose several entities publicly:

{
  roles: {
    anonymous: {
      is_default: true,
      implicit_allow: false,
      permissions: [
        {
          permission: "data.entity.read",
          effect: "allow",
          policies: [{
            condition: { entity: { $in: ["posts", "categories", "tags"] } },
            effect: "allow",
          }],
        },
      ],
    },
  },
}

Step 5: Public Records with Filter

Make only published/public records accessible:

{
  roles: {
    anonymous: {
      is_default: true,
      implicit_allow: false,
      permissions: [
        {
          permission: "data.entity.read",
          effect: "allow",
          policies: [
            // Posts: only published
            {
              condition: { entity: "posts" },
              effect: "filter",
              filter: { status: "published" },
            },
            // Products: only visible
            {
              condition: { entity: "products" },
              effect: "filter",
              filter: { visible: true },
            },
          ],
        },
      ],
    },
  },
}

Result: Anonymous users only see filtered records; authenticated users see all.

Step 6: Mixed Public/Owner Access

Public can read published; owners can read their own drafts:

{
  roles: {
    anonymous: {
      is_default: true,
      implicit_allow: false,
      permissions: [
        {
          permission: "data.entity.read",
          effect: "allow",
          policies: [{
            condition: { entity: "posts" },
            effect: "filter",
            filter: { status: "published" },
          }],
        },
      ],
    },
    user: {
      implicit_allow: false,
      permissions: [
        // Read: published OR own posts
        {
          permission: "data.entity.read",
          effect: "allow",
          policies: [{
            condition: { entity: "posts" },
            effect: "filter",
            filter: {
              $or: [
                { status: "published" },
                { author_id: "@user.id" },
              ],
            },
          }],
        },
        // Create allowed
        "data.entity.create",
        // Update own only
        {
          permission: "data.entity.update",
          effect: "allow",
          policies: [{
            effect: "filter",
            filter: { author_id: "@user.id" },
          }],
        },
      ],
    },
  },
}

Step 7: Invite-Only System

No public access, no self-registration:

{
  auth: {
    enabled: true,
    guard: { enabled: true },
    allow_register: false,  // Disable self-registration
    roles: {
      admin: { implicit_allow: true },
      member: {
        implicit_allow: false,
        permissions: [
          "data.entity.read",
          "data.entity.create",
          "data.entity.update",
        ],
      },
      // No default role
    },
  },
  options: {
    seed: async (ctx) => {
      // Admin creates users manually
      await ctx.app.module.auth.createUser({
        email: "admin@company.com",
        password: "admin-password",
        role: "admin",
      });
    },
  },
}

Step 8: API with Public Read, Auth Write

Common REST API pattern:

{
  roles: {
    anonymous: {
      is_default: true,
      implicit_allow: false,
      permissions: ["data.entity.read"],  // Read anything
    },
    api_user: {
      implicit_allow: false,
      permissions: [
        "data.entity.read",
        "data.entity.create",
        "data.entity.update",
        "data.entity.delete",
      ],
    },
  },
}

Complete Configuration Examples

Blog Platform

import { serve } from "bknd/adapter/bun";
import { em, entity, text, boolean, relation } from "bknd";

const schema = em(
  {
    posts: entity("posts", {
      title: text().required(),
      content: text(),
      published: boolean().default(false),
    }),
    comments: entity("comments", {
      body: text().required(),
      approved: boolean().default(false),
    }),
    users: entity("users", {}),
  },
  ({ posts, comments, users }) => [
    relation(posts, "author").manyToOne(users),
    relation(comments, "post").manyToOne(posts),
    relation(comments, "user").manyToOne(users),
  ]
);

serve({
  connection: { url: "file:data.db" },
  config: {
    data: schema.toJSON(),
    auth: {
      enabled: true,
      guard: { enabled: true },
      allow_register: true,
      default_role_register: "commenter",
      roles: {
        // Public: read published posts + approved comments
        anonymous: {
          is_default: true,
          implicit_allow: false,
          permissions: [
            {
              permission: "data.entity.read",
              effect: "allow",
              policies: [
                {
                  condition: { entity: "posts" },
                  effect: "filter",
                  filter: { published: true },
                },
                {
                  condition: { entity: "comments" },
                  effect: "filter",
                  filter: { approved: true },
                },
              ],
            },
          ],
        },
        // Registered users: read all, create comments
        commenter: {
          implicit_allow: false,
          permissions: [
            "data.entity.read",
            {
              permission: "data.entity.create",
              effect: "allow",
              policies: [{
                condition: { entity: "comments" },
                effect: "allow",
              }],
            },
          ],
        },
        // Authors: full post access, manage own comments
        author: {
          implicit_allow: false,
          permissions: [
            "data.entity.read",
            {
              permission: "data.entity.create",
              effect: "allow",
              policies: [{
                condition: { entity: { $in: ["posts", "comments"] } },
                effect: "allow",
              }],
            },
            {
              permission: "data.entity.update",
              effect: "allow",
              policies: [{
                condition: { entity: "posts" },
                effect: "filter",
                filter: { author_id: "@user.id" },
              }],
            },
          ],
        },
        // Admin: everything
        admin: { implicit_allow: true },
      },
    },
  },
});

SaaS Application

{
  auth: {
    enabled: true,
    guard: { enabled: true },
    allow_register: true,
    default_role_register: "free_user",
    roles: {
      // Landing page data only
      anonymous: {
        is_default: true,
        implicit_allow: false,
        permissions: [
          {
            permission: "data.entity.read",
            effect: "allow",
            policies: [{
              condition: { entity: { $in: ["plans", "features"] } },
              effect: "allow",
            }],
          },
        ],
      },
      // Free tier: limited access
      free_user: {
        implicit_allow: false,
        permissions: [
          "data.entity.read",
          {
            permission: "data.entity.create",
            effect: "allow",
            policies: [{
              condition: { entity: "projects" },
              effect: "allow",
            }],
          },
        ],
      },
      // Paid tier: full access to own data
      pro_user: {
        implicit_allow: false,
        permissions: [
          "data.entity.read",
          "data.entity.create",
          {
            permission: "data.entity.update",
            effect: "allow",
            policies: [{
              effect: "filter",
              filter: { owner_id: "@user.id" },
            }],
          },
          {
            permission: "data.entity.delete",
            effect: "allow",
            policies: [{
              effect: "filter",
              filter: { owner_id: "@user.id" },
            }],
          },
        ],
      },
      admin: { implicit_allow: true },
    },
  },
}

Testing Access Levels

Test Public Access

# Should succeed (anonymous read)
curl http://localhost:7654/api/data/posts

# Should fail (anonymous create)
curl -X POST http://localhost:7654/api/data/posts \
  -H "Content-Type: application/json" \
  -d '{"title": "Test"}'
# Returns 403

Test Authenticated Access

# Login
TOKEN=$(curl -s -X POST http://localhost:7654/api/auth/password/login \
  -H "Content-Type: application/json" \
  -d '{"email": "user@test.com", "password": "pass123"}' | jq -r '.token')

# Should succeed (authenticated create)
curl -X POST http://localhost:7654/api/data/posts \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "Test"}'

Test Entity-Specific Access

# Public entity - should succeed
curl http://localhost:7654/api/data/posts

# Private entity - should fail
curl http://localhost:7654/api/data/users
# Returns 403

Test Filtered Access

# Anonymous: only sees published
curl http://localhost:7654/api/data/posts
# Returns: [{ status: "published" }, ...]

# Authenticated: sees all including drafts
curl http://localhost:7654/api/data/posts \
  -H "Authorization: Bearer $TOKEN"
# Returns: [{ status: "draft" }, { status: "published" }, ...]

Frontend Integration

React: Check Auth State

import { useApp, useAuth } from "bknd/react";

function DataDisplay() {
  const { api } = useApp();
  const { user } = useAuth();
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    // Works for both anonymous and authenticated
    api.data.readMany("posts").then((res) => {
      if (res.ok) setPosts(res.data);
    });
  }, []);

  return (
    <div>
      {posts.map((post) => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          {/* Show edit only for authenticated users */}
          {user && <button>Edit</button>}
        </article>
      ))}

      {/* Show create only for authenticated */}
      {user ? (
        <button>New Post</button>
      ) : (
        <a href="/login">Login to create posts</a>
      )}
    </div>
  );
}

Conditional Fetch

function useProtectedData(entity: string) {
  const { api } = useApp();
  const { user, isLoading } = useAuth();
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    if (isLoading) return;

    api.data.readMany(entity).then((res) => {
      if (res.ok) {
        setData(res.data);
      } else {
        setError(res.error);
      }
    });
  }, [entity, user, isLoading]);

  return { data, error, isAuthenticated: !!user };
}

// Usage
function ProtectedPage() {
  const { data, error, isAuthenticated } = useProtectedData("projects");

  if (error?.status === 403 && !isAuthenticated) {
    return <LoginPrompt />;
  }

  return <DataList items={data} />;
}

Common Pitfalls

No Default Role = No Public Access

Problem: Permission not granted for unauthenticated requests

Fix: Add a default role:

{
  roles: {
    anonymous: {
      is_default: true,  // Required for public access!
      permissions: ["data.entity.read"],
    },
  },
}

Guard Disabled

Problem: Everyone can access everything

Fix: Enable the guard:

{
  auth: {
    enabled: true,
    guard: { enabled: true },  // Required!
  },
}

Filter Not Applied

Problem: Anonymous users see all records, not just filtered

Fix: Use effect: "filter" not effect: "allow":

// WRONG - allows all
{
  condition: { entity: "posts" },
  effect: "allow",
  filter: { published: true },  // Ignored!
}

// CORRECT - applies filter
{
  condition: { entity: "posts" },
  effect: "filter",
  filter: { published: true },
}

Sensitive Entity Exposed

Problem: Users entity publicly readable

Fix: Use entity conditions:

{
  permissions: [
    {
      permission: "data.entity.read",
      effect: "allow",
      policies: [{
        // Only allow specific entities
        condition: { entity: { $in: ["posts", "comments"] } },
        effect: "allow",
      }],
    },
  ],
}

Auth Header Not Sent

Problem: User authenticated but still gets public data

Fix: Include credentials in fetch:

// Browser with cookies
fetch("/api/data/posts", { credentials: "include" });

// Token-based
fetch("/api/data/posts", {
  headers: { Authorization: `Bearer ${token}` },
});

Access Matrix Reference

ScenarioAnonymous RoleUser RoleResult
Public Readdata.entity.readAll CRUDAnon: read; User: CRUD
Private OnlyNone/No defaultAll CRUDAnon: 403; User: CRUD
Entity-SpecificRead posts onlyRead allAnon: posts; User: all
FilteredFilter publishedRead allAnon: published; User: all

DOs and DON'Ts

DO:

  • Set is_default: true on exactly one role for public access
  • Use entity conditions to limit which entities are public
  • Use filter policies to expose only appropriate records
  • Test access as both anonymous and authenticated users
  • Keep sensitive entities (users, settings) protected

DON'T:

  • Forget to enable guard (guard: {enabled: true})
  • Use implicit_allow: true on anonymous/default role
  • Expose user data publicly without filters
  • Assume auth header is always sent (check frontend code)
  • Mix up effect: "allow" and effect: "filter"

Related Skills

  • bknd-create-role - Define roles for authorization
  • bknd-assign-permissions - Configure detailed permissions
  • bknd-row-level-security - Data-level access control
  • bknd-protect-endpoint - Secure custom endpoints
  • bknd-setup-auth - Initialize authentication system

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

34.51%
按下载量换算37

Claude

27.81%
按下载量换算29

Cursor

18.42%
按下载量换算20

Gemini CLI

9.75%
按下载量换算10

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills