Files
NixMsg/internal/auth/auth.go

96 lines
3.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package auth 定义密码哈希池、会话令牌、API 令牌与登录锁定计数的接口。
// 本包在 T0.4 只提供契约与测试假实现;真正的 argon2 池与令牌逻辑由平台 P 实现。
package auth
import (
"context"
"errors"
"time"
)
// ErrNotImplemented 表示假实现尚未提供业务能力。
var ErrNotImplemented = errors.New("auth: not implemented")
// PasswordKind 区分哈希用途(便于日志与限流,不影响算法)。
type PasswordKind string
const (
PasswordLogin PasswordKind = "login"
PasswordTalk PasswordKind = "talk"
PasswordAdmin PasswordKind = "admin"
)
// HashPool 是 argon2id 并发池(DEVELOPMENT 第 12 节)。
type HashPool interface {
// Hash 计算 PHC 格式哈希。
Hash(ctx context.Context, kind PasswordKind, password string) (phc string, err error)
// Verify 常量时间比较;ok 为 false 时 err 仍可为 nil(密码不匹配)。
Verify(ctx context.Context, kind PasswordKind, password, phc string) (ok bool, err error)
// QueueLen 返回等待哈希的任务数(指标用)。
QueueLen() int
}
// SessionTokens 管理端会话令牌(nst_ 前缀,库中存 SHA-256)。
type SessionTokens interface {
// Issue 生成新令牌明文,返回明文与 SHA-256 十六进制(或原始哈希字节由实现约定)。
Issue(ctx context.Context) (token string, hash []byte, err error)
// HashToken 对已有令牌做 SHA-256(校验用,不走 argon2)。
HashToken(token string) []byte
// LooksLikeSessionToken 判断密码字段是否以 nst_ 开头。
LooksLikeSessionToken(credential string) bool
}
// APITokenInfo 是列表项(不含令牌明文)。
type APITokenInfo struct {
ID int64
Name string
Enabled bool
CreatedAt time.Time
LastUsedAt *time.Time
}
// APITokens 管理后台 API 令牌(nxm_ 前缀)。
type APITokens interface {
Issue(ctx context.Context) (token string, hash []byte, err error)
HashToken(token string) []byte
LooksLikeAPIToken(credential string) bool
}
// LockKind 区分锁定计数器类型。
type LockKind string
const (
// LockLoginEndpointIP:编号 + IP,5 分钟内 10 次错 → 锁该组合 5 分钟。
LockLoginEndpointIP LockKind = "login_endpoint_ip"
// LockLoginEndpoint:编号总数,1 小时内 50 次错 → 暂停该编号密码登录 1 小时。
LockLoginEndpoint LockKind = "login_endpoint"
// LockTalkPair:发送方 + 对方对话密码。
LockTalkPair LockKind = "talk_pair"
// LockTalkTarget:对方对话密码总数。
LockTalkTarget LockKind = "talk_target"
// LockAdminIP:管理员登录 / 错误 API 令牌。
LockAdminIP LockKind = "admin_ip"
// LockRegisterIP:注册安全码错误。
LockRegisterIP LockKind = "register_ip"
)
// LockKey 是一次锁定查询/计数的键。
type LockKey struct {
Kind LockKind
EndpointID string // 端编号;管理员/注册场景可空
PeerID string // 对话密码对方;可空
IP string // 来源 IP;按编号总数等场景可空
}
// LoginLocks 是内存锁定计数器(重启清零)。
type LoginLocks interface {
// Check 若当前已锁定返回 locked=true 与剩余时间。
Check(key LockKey) (locked bool, retryAfter time.Duration)
// Fail 记录一次失败;若因此触发锁定,返回 locked=true。
Fail(key LockKey) (locked bool, retryAfter time.Duration)
// ClearEndpoint 清除某端编号相关的登录锁定(两种都清),对应管理 unlock。
ClearEndpoint(endpointID string)
// Clear 清除精确键。
Clear(key LockKey)
}