Documentation
¶
Overview ¶
Package client is what a project consuming iam remotely imports — a thin server-to-server HTTP client for POST /api/token. It carries none of iam's own ORM/auth machinery: a consumer's binary (including its WASM edge build) never pulls in tinywasm/orm or tinywasm/rbac just to ask "who is this user and what may they do in MY project".
This client is called from the CONSUMER'S OWN SERVER, never from the browser: client_secret must never reach a WASM/JS bundle a user can inspect (see ARCHITECTURE.md §6.4/§7). The consumer's server reads the SSO cookie off the incoming request and forwards its value here — it never verifies or decodes that cookie itself, only iam can.
Index ¶
Constants ¶
const ( EnvBaseURL = "IAM_BASE_URL" EnvClientSecret = "IAM_CLIENT_SECRET" )
Nombres convencionales de las variables de entorno. Están aquí para que todos los consumidores usen las mismas y nadie invente un tercer nombre.
const ( ErrMsgMissingBaseURL = "iam client: Config.BaseURL is required" ErrMsgMissingProjectID = "iam client: Config.ProjectID is required" ErrMsgMissingClientSecret = "iam client: Config.ClientSecret is required" )
const ( ErrMsgAssignRoleUserRequired = "iam client: AssignRole: userID is required" ErrMsgAssignRoleCodeRequired = "iam client: AssignRole: roleCode is required" )
const SSOCookieName = "iam_session"
SSOCookieName is the cookie iam sets after a successful login, shared across every *.velty.cl subdomain (Domain=".velty.cl", see ARCHITECTURE.md §7). A consumer reads it off its OWN incoming request (net/http-style cookie jar, or ctx.Cookie(SSOCookieName) in this ecosystem's router.Context) and passes its value to FetchAuthzToken.
Variables ¶
var ErrNoSSOSession = fmt.Err("iam", "sso", "session-required")
ErrNoSSOSession means either no SSO cookie was forwarded, or iam rejected it (expired/forged) — both collapse to "treat this caller as anonymous", never as an error worth alarming on: an expired or absent session is routine, not an attack (same principle as tinywasm/jwt's Outcome — see its docs).
Functions ¶
func ResolveUser ¶ added in v0.0.9
ResolveUser calls POST <iamBaseURL>/api/users/resolve server-to-server: finds (or creates) a user by email within iam's identity, and returns their Sub — the same id their token's Sub will carry once they log in. For a consumer that needs to grant a resource (e.g. site ownership) to someone who may never have logged in yet. Requires only clientSecret — there is no session involved (see ARCHITECTURE.md/PathUsersResolve doc in iam's routes package for why that's safe).
func SetIdentity ¶ added in v0.0.21
SetIdentity guarda en el contexto lo que iam resolvió para esta petición.
Types ¶
type Config ¶ added in v0.0.21
type Config struct {
BaseURL string // https://iam.velty.cl, o el servidor de desarrollo
ProjectID string // identifica al proyecto ante iam
ClientSecret string // NUNCA llega al navegador
}
Config es lo que un proyecto necesita para hablarle a iam.
func ConfigFromEnv ¶ added in v0.0.21
ConfigFromEnv arma una Config leyendo EnvBaseURL y EnvClientSecret. projectID es del proyecto, no del entorno: es una constante suya, no algo que se despliega distinto por ambiente.
type Consumer ¶ added in v0.0.21
type Consumer struct {
// contains filtered or unexported fields
}
Consumer es un proyecto que consume iam. Autentica peticiones contra iam y recuerda el scope que iam devolvió, para que el autorizador del proyecto lo lea sin un segundo viaje.
Un proyecto crea UNO al arrancar y lo comparte entre su servidor local y su Worker: son el mismo objeto con la misma configuración, y ahí está la razón de que exista — antes cada punto de entrada armaba el middleware por su cuenta, con cuatro argumentos que había que mantener sincronizados a mano.
func New ¶ added in v0.0.21
New valida la configuración y falla rápido si falta algo. Arrancar sin poder hablarle a iam es peor que no arrancar: cada ruta protegida respondería 403 para siempre y nadie sabría por qué.
func (*Consumer) AssignRole ¶ added in v0.0.21
AssignRole concede roleCode al usuario en ESTE proyecto. Idempotente: si ya lo tiene, no es un error.
Es la contraparte de Scope: un consumidor no solo lee los roles que iam le entrega, tambien necesita concederlos cuando su propio dominio decide que alguien pasa a tener acceso. Sin esto, el consumidor solo podria sembrar roles por lista de correos conocida de antemano.
func (*Consumer) Authn ¶ added in v0.0.21
func (c *Consumer) Authn() router.Middleware
Authn identifica al llamante. Reemplaza a authority.Authenticate() en un proyecto que delega su identidad en iam.
Una cookie SSO ausente o rechazada es lo NORMAL (sesión vencida, nadie ha entrado todavía): deja al llamante anónimo y sigue. Nunca es un 500 ni un error que se le muestre a la petición.
func (*Consumer) Scope ¶ added in v0.0.21
Scope devuelve los códigos de rol vigentes que iam entregó para userID. ok es false cuando no hay entrada vigente — y eso DENIEGA: la ausencia de una respuesta no es un permiso.
Devuelve códigos, no permisos. Qué autoriza cada código es política del proyecto, no de iam (ver docs/ARCHITECTURE.md §3.4).
type Identity ¶ added in v0.0.8
Identity is what FetchAuthzToken resolves for the caller's session: the authorization claims (Sub/Aud/Scope) plus the profile fields iam's /api/token response carries alongside them — a consumer showing "Hola, <Name>" needs no second call.
func FetchAuthzToken ¶
FetchAuthzToken calls POST <iamBaseURL>/api/token server-to-server, forwarding ssoCookieValue (the SSO cookie's value read off the caller's own incoming request) so iam can identify the user, and clientSecret so iam knows which project is asking. Returns the project-scoped authorization claims — Aud is projectID, Scope is the user's role codes in that project (see ARCHITECTURE.md §6.1/§6.2) — plus the user's basic profile.
The claims are decoded WITHOUT verifying the HMAC signature (tinyjwt.DecodeUnverified, not Verify): this response came directly from iam over THIS SAME HTTPS call, not from an untrusted third party presenting a token later — there is nothing to gain from re-checking a signature whose secret this consumer does not, and must never, have (ARCHITECTURE.md §6.2: the HS256 secret is internal to iam). Do not change this to Verify — it would require sharing iam's secret, which is exactly the acoplamiento this design avoids.