encore-go-auth — скилл для Claude Code: установка
Скилл помогает защищать Go-эндпоинты Encore и проверять, кто выполняет запрос. Пригодится для JWT, API-ключей и сессионных cookie.
npx skills add encoredev/skills --skill encore-go-auth -a claude-code
npx skills add encoredev/skills --skill go-auth -a claude-codeЧто делает encore-go-auth
Скилл описывает встроенную аутентификацию Encore Go: обработчик с аннотацией //encore:authhandler получает параметры запроса и возвращает auth.UID, данные пользователя и ошибку. Из Authorization можно извлечь bearer-токен, проверить JWT или API-ключ, а при ошибке вернуть errs.Unauthenticated для ответа 401.
Доступ к защищённому обработчику задаётся через //encore:api auth; публичный эндпоинт использует //encore:api public. Внутри обработчика доступны auth.UserID() и auth.Data(), где можно прочитать идентификатор, email и роль. Параметры также могут приходить из cookie и query string.
Сигнатура обработчика фиксирована: context.Context, указатель на структуру параметров и результат (auth.UID, *AuthData, error). Без аннотации //encore:authhandler Encore не распознает функцию как обработчик аутентификации.
Какие задачи решает
- защитить Go-эндпоинт Encore авторизацией
- проверить bearer-токен или JWT из
Authorization - прочитать ID, email и роль текущего пользователя
- вернуть 401 при неверных учётных данных
- подключить аутентификацию через cookie или API-ключ
Примеры запросов агенту
- Защити эндпоинт профиля через
//encore:api authи верни данные изauth.UserID()иauth.Data(). - Создай
//encore:authhandler, который проверяет bearer-токен из заголовкаAuthorizationи возвращаетerrs.Unauthenticatedпри ошибке. - Покажи, как принимать сессионную cookie и использовать её для аутентификации Encore Go.
Как установить encore-go-auth
1Через Skills CLI (Vercel)
npx skills add encoredev/skills --skill encore-go-auth -a claude-codenpx skills add encoredev/skills --skill go-auth -a claude-code2Вручную: положить файлы
~/.claude/skills/go-auth/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/go-auth/
1Через Skills CLI (Vercel)
npx skills add encoredev/skills --skill go-auth -a codex2Вручную: положить файлы
.agents/skills/go-auth/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add encoredev/skills --skill go-auth -a cursor2Вручную: положить файлы
.cursor/skills/go-auth/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install encoredev/skills go-auth2Вручную: положить файлы
.github/skills/go-auth/SKILL.md1Через Skills CLI (Vercel)
npx skills add encoredev/skills --skill go-auth -a gemini-cli2Командой платформы
gemini skills install https://github.com/encoredev/skills --path encore/go-authВручную: положить файлы
.devin/skills/go-auth/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add encoredev/skills --skill go-auth -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Вопросы о encore-go-auth
Как установить encore-go-auth в Claude Code?
Выполните npx skills add encoredev/skills --skill encore-go-auth -a claude-code, затем npx skills add encoredev/skills --skill go-auth -a claude-code. Файл скилла будет доступен по пути ~/.claude/skills/go-auth/SKILL.md.
Что делает encore-go-auth?
Скилл помогает настраивать аутентификацию Encore Go: создавать auth.AuthHandler, защищать эндпоинты через //encore:api auth и читать данные текущего пользователя.
Какая сигнатура нужна для auth handler?
Функция должна иметь аннотацию //encore:authhandler, принимать context.Context и указатель на структуру параметров, а возвращать (auth.UID, *AuthData, error). При неверных данных используется errs.Unauthenticated.
Исходный текст
SKILL.md · Apache-2.0
---
name: encore-go-auth
description: Protect Encore Go endpoints with authentication and authorize callers. Covers `auth.AuthHandler`, `auth.UserID`, the `Authorization` header, and `//encore:api auth`.
when_to_use: >-
User wants to require login on a Go endpoint, restrict an endpoint to authenticated/signed-in users, validate a bearer token / JWT / API key from an `Authorization` header, read the current user inside a handler (`auth.UserID()` / `auth.Data()`), define an `auth.AuthHandler`, return `errs.Unauthenticated` from a handler, or use `//encore:api auth` on a handler. Trigger phrases: "protect this endpoint", "only authenticated users", "require login", "Authorization header", "bearer token", "401", "403", "who is calling", "current user".
---
# Encore Go Authentication
## Instructions
Encore Go provides a built-in authentication system using the `//encore:authhandler` annotation.
### 1. Create an Auth Handler
```go
package auth
import (
"context"
"encore.dev/beta/auth"
"encore.dev/beta/errs"
)
// AuthParams defines what the auth handler receives
type AuthParams struct {
Authorization string `header:"Authorization"`
}
// AuthData defines what authenticated requests have access to
type AuthData struct {
UserID string
Email string
Role string
}
//encore:authhandler
func Authenticate(ctx context.Context, params *AuthParams) (auth.UID, *AuthData, error) {
token := strings.TrimPrefix(params.Authorization, "Bearer ")
payload, err := verifyToken(token)
if err != nil {
return "", nil, &errs.Error{
Code: errs.Unauthenticated,
Message: "invalid token",
}
}
return auth.UID(payload.UserID), &AuthData{
UserID: payload.UserID,
Email: payload.Email,
Role: payload.Role,
}, nil
}
```
### 2. Protect Endpoints
```go
package user
import "context"
// Protected endpoint - requires authentication
//encore:api auth method=GET path=/profile
func GetProfile(ctx context.Context) (*Profile, error) {
// Only authenticated users reach here
}
// Public endpoint - no authentication required
//encore:api public method=GET path=/health
func Health(ctx context.Context) (*HealthResponse, error) {
return &HealthResponse{Status: "ok"}, nil
}
```
### 3. Access Auth Data in Endpoints
```go
package user
import (
"context"
"encore.dev/beta/auth"
myauth "myapp/auth" // Import your auth package
)
//encore:api auth method=GET path=/profile
func GetProfile(ctx context.Context) (*Profile, error) {
// Get the user ID
userID, ok := auth.UserID()
if !ok {
// Should not happen with auth endpoint
}
// Get full auth data
data := auth.Data().(*myauth.AuthData)
return &Profile{
UserID: string(userID),
Email: data.Email,
Role: data.Role,
}, nil
}
```
## Auth Handler Signature
The auth handler must:
1. Have the `//encore:authhandler` annotation
2. Accept `context.Context` and a params struct pointer
3. Return `(auth.UID, *YourAuthData, error)`
```go
//encore:authhandler
func MyAuthHandler(ctx context.Context, params *Params) (auth.UID, *AuthData, error)
```
## Auth Handler Behavior
| Scenario | Returns | Result |
|----------|---------|--------|
| Valid credentials | `(uid, data, nil)` | Request authenticated |
| Invalid credentials | `("", nil, err)` with `errs.Unauthenticated` | 401 response |
| Other error | `("", nil, err)` | Request aborted |
## Common Auth Patterns
### JWT Token Validation
```go
import "github.com/golang-jwt/jwt/v5"
var secrets struct {
JWTSecret string
}
func verifyToken(tokenString string) (*Claims, error) {
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(t *jwt.Token) (interface{}, error) {
return []byte(secrets.JWTSecret), nil
})
if err != nil {
return nil, err
}
claims, ok := token.Claims.(*Claims)
if !ok || !token.Valid {
return nil, errors.New("invalid token")
}
return claims, nil
}
```
### API Key Authentication
```go
//encore:authhandler
func Authenticate(ctx context.Context, params *AuthParams) (auth.UID, *AuthData, error) {
apiKey := params.Authorization
user, err := db.QueryRow[User](ctx, `
SELECT id, email, role FROM users WHERE api_key = $1
`, apiKey)
if err != nil {
return "", nil, &errs.Error{
Code: errs.Unauthenticated,
Message: "invalid API key",
}
}
return auth.UID(user.ID), &AuthData{
UserID: user.ID,
Email: user.Email,
Role: user.Role,
}, nil
}
```
### Cookie-Based Auth
```go
type AuthParams struct {
Cookie string `header:"Cookie"`
}
//encore:authhandler
func Authenticate(ctx context.Context, params *AuthParams) (auth.UID, *AuthData, error) {
sessionID := parseCookie(params.Cookie, "session")
if sessionID == "" {
return "", nil, &errs.Error{
Code: errs.Unauthenticated,
Message: "no session",
}
}
session, err := getSession(ctx, sessionID)
if err != nil || session.ExpiresAt.Before(time.Now()) {
return "", nil, &errs.Error{
Code: errs.Unauthenticated,
Message: "session expired",
}
}
return auth.UID(session.UserID), &AuthData{
UserID: session.UserID,
Email: session.Email,
Role: session.Role,
}, nil
}
```
### Multi-Source Auth (Cookie + Header + Query)
Auth params can extract data from multiple sources:
```go
import "net/http"
type AuthParams struct {
SessionCookie *http.Cookie `cookie:"session"` // From cookie
Authorization string `header:"Authorization"` // From header
ClientID string `query:"client_id"` // From query string
}
//encore:authhandler
func Authenticate(ctx context.Context, params *AuthParams) (auth.UID, *AuthData, error) {
// Try session cookie first
if params.SessionCookie != nil {
return authenticateWithSession(ctx, params.SessionCookie.Value)
}
// Fall back to Authorization header
if params.Authorization != "" {
return authenticateWithToken(ctx, params.Authorization)
}
return "", nil, &errs.Error{
Code: errs.Unauthenticated,
Message: "no credentials provided",
}
}
```
## Service-to-Service Auth
Auth data automatically propagates in internal service calls:
```go
package order
import (
"context"
"myapp/user" // Import the user service
)
//encore:api auth method=GET path=/orders/:id
func GetOrderWithUser(ctx context.Context, params *GetOrderParams) (*OrderWithUser, error) {
order, err := getOrder(ctx, params.ID)
if err != nil {
return nil, err
}
// Auth is automatically propagated to this call
profile, err := user.GetProfile(ctx)
if err != nil {
return nil, err
}
return &OrderWithUser{Order: order, User: profile}, nil
}
```
## Testing with Auth
Override auth data in tests using `auth.WithContext`:
```go
package user_test
import (
"context"
"testing"
"encore.dev/beta/auth"
myauth "myapp/auth"
"myapp/user"
)
func TestGetProfile(t *testing.T) {
// Create a context with auth data
ctx := auth.WithContext(
context.Background(),
auth.UID("test-user-123"),
&myauth.AuthData{
UserID: "test-user-123",
Email: "[email protected]",
Role: "user",
},
)
// Call the endpoint with the authenticated context
profile, err := user.GetProfile(ctx)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if profile.Email != "[email protected]" {
t.Errorf("expected [email protected], got %s", profile.Email)
}
}
```
## Guidelines
- Only one `//encore:authhandler` per application
- Return `auth.UID` as the first return value (user identifier)
- Return your custom `AuthData` struct as second value
- Use `auth.UserID()` to get the authenticated user ID
- Use `auth.Data()` and type assert to get full auth data
- Auth propagates automatically in service-to-service calls
- Use `auth.WithContext()` to override auth in tests
- Keep auth handlers fast - they run on every authenticated request
© encoredev · Apache-2.0 · encoredev/skills