clienttokenhttp

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: AGPL-3.0 Imports: 12 Imported by: 0

Documentation

Overview

Package clienttokenhttp — токен-эндпоинт платформы (задача #898, приёмка F2 §9.1 п. 1).

Клиент предъявляет подписанное утверждение, мы сверяем подпись его открытым ключом из своей же таблицы и выдаём токен доступа по виду выдачи «учётные данные клиента». Форма запроса и форма ответа — стандартные (RFC 6749 §4.4, RFC 7523 §2.2): предъявитель — чужая библиотека, и ответ обязан быть тем, который она умеет прочитать, иначе отказ выглядит для неё сбоем сети.

Единый тон наружу и различимость внутрь

Всякий отказ, наступивший ПОСЛЕ того, как в запросе назван клиент — включая «такого клиента нет», — отдаёт побайтово ОДНО И ТО ЖЕ. Различимый отказ есть оракул: по нему устанавливают, существует ли клиент, жив ли он, какой у него алгоритм и какие идентификаторы однократности уже заняты. Каждый ответ сам по себе безобиден, а вместе они дают карту.

Различимыми остаются ровно ПЯТЬ отказов, и все пять решаются ДО того, как запрос назвал хоть какого-нибудь клиента: метод, потолок тела, неразбираемая форма, вид выдачи вне перечня и повторённый параметр утверждения. Они не сообщают о клиенте ничего, потому что клиента на этом шаге ещё нет, и стандартные коды у них обязаны быть свои — иначе чужая библиотека прочтёт «слишком большое тело» как «неверный клиент» и будет чинить не то.

Различимость для НАС живёт с другой стороны провода: у каждого исхода свой счётчик и своя запись в журнале. Без счётчика мёртвый контроль невидим — проверка, не отказавшая ни разу за всё время жизни, неотличима от проверки, которая работает и просто не встречала нарушителя.

Index

Constants

View Source
const TokenPath = "/iam/v1/token"

TokenPath — объявленный путь эндпоинта.

#nosec G101 -- это АДРЕС поверхности, а не учётные данные: строка попадает в маршрут и в документацию клиента, её знает всякий, кто обращается к сервису. Слово в адресе называет предмет выдачи, а не хранимый секрет.

Variables

This section is empty.

Functions

func DeclaredOutcomes added in v0.2.0

func DeclaredOutcomes() []string

DeclaredOutcomes — закрытый словарь исходов этой полосы строками.

Отдаётся наружу ради читателя величин: набор рядов витрины обязан совпадать с набором клеток переписи by construction. Выведен из того же clientassertion.Outcomes, которым засеяна перепись, поэтому второй копией словаря не является.

func NewMux

func NewMux(h http.Handler) *http.ServeMux

NewMux монтирует эндпоинт на объявленный путь и НИ НА КАКОЙ другой.

Перечень путей выводится из этой функции, а не выписывается: утверждение о единственном маршруте оставалось бы зелёным, уедь второй не туда.

Types

type Config

type Config struct {
	// BodyCeiling — потолок тела запроса в байтах. ОБЯЗАТЕЛЕН.
	//
	// Умолчания здесь нет намеренно. Величина, которую построение подставляет
	// молча, не может быть предметом стража старта: страж, требующий её
	// задания, зелен при любом входе, потому что незаданной она не бывает. Тело
	// этого запроса — форма с одним подписанным утверждением, и его потолок
	// объявляет тот, кто поднимает сервис.
	BodyCeiling int64
	Logger      *slog.Logger
}

Config — настройка эндпоинта.

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler — токен-эндпоинт.

func NewHandler

func NewHandler(cfg Config, verifier Verifier, issuer Issuer) (*Handler, error)

NewHandler строит эндпоинт. Неполная провязка — отказ построения: эндпоинт без проверяющего принимал бы кого угодно, без выдачи — не выдавал бы никому, и оба состояния обнаружились бы на первом запросе, а не на старте.

func (*Handler) Outcomes

func (h *Handler) Outcomes() map[clientassertion.Outcome]uint64

Outcomes — перепись исходов. Читается сборщиком метрик.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type Issuer

type Issuer interface {
	Issue(ctx context.Context, in client_token.Input) (client_token.Output, clientassertion.Outcome, error)
}

Issuer — порт выдачи.

type Verifier

type Verifier interface {
	// Verify — полоса аутентификации клиента (RFC 7523 §2.2): утверждение
	// доказывает личность клиента, ключ берётся из строки реестра.
	Verify(ctx context.Context, assertionType, raw string) (clientassertion.Result, error)
	// VerifyFederated — федеративная полоса (RFC 7523 §2.1): утверждение
	// подписал внешний издатель, ключ берётся из нашего перечня доверенных
	// издателей.
	VerifyFederated(ctx context.Context, raw string) (clientassertion.Result, error)
}

Verifier — порт проверяющего утверждение, ОБЕ полосы.

Один порт на две полосы, а не два: эндпоинт обязан выбирать полосу сам, по объявленному виду выдачи. Разнеси их по двум портам — и появилась бы посадка, где провязана одна, а вторая молча отвергает всё.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL