Package cimddraft
Overview
Package cimddraft implements OAuth Client ID Metadata Documents for an authorization server: checking a client identifier that's a URL, and the metadata document fetched from it.
A Client ID Metadata Document lets a client use a URL it controls as its client_id, with no registration step. The authorization server fetches the URL and reads the client's name and redirect URIs from it. The Model Context Protocol uses it as the main way MCP clients identify themselves.
id, err := cimddraft.ParseClientID(form.Get("client_id"))
// Fetch id.String(), refusing redirects and special-purpose addresses,
// and reading at most cimddraft.MaxDocumentSize bytes.
doc, err := cimddraft.ParseDocument(body, id)The package doesn't fetch. Fetching safely needs network policy, such as refusing the addresses rfc6890 lists (Section 8.6), that belongs to the server.
Client ID Metadata Documents are an IETF draft, draft-ietf-oauth-client-id-metadata-document. This package implements revision -02, whose text is in draft-ietf-oauth-client-id-metadata-document-02.txt in this directory, and the doc comments cite its sections. It tracks the draft's latest revision, and moving to a new one is a single change reviewed against the difference between the texts. When the draft is published as an RFC, a package named after that RFC replaces this one.
Index
Constants
const MaxDocumentSize = 5 * 1024MaxDocumentSize is the most an authorization server should read of a Client ID Metadata Document: 5 kilobytes (Section 8.7). A document that doesn't end within it is an error, not a truncated document.
const MetadataSupported = "client_id_metadata_document_supported"MetadataSupported is the authorization server metadata member that says the server accepts Client ID Metadata Documents (Section 6). Set it with rfc8414's Metadata.WithExtension.
Variables
var (
// ErrInvalidClientID is returned by [ParseClientID] for a URL that
// breaks the rules of Section 3.
ErrInvalidClientID = errors.New("invalid client identifier URL")
// ErrInvalidDocument is returned by [ParseDocument] for a document
// that isn't JSON, or breaks the rules of Section 4 or 4.1.
ErrInvalidDocument = errors.New("invalid client ID metadata document")
)Types
ClientID source
type ClientID struct {
// contains filtered or unexported fields
}ClientID is a Client Identifier URL. Use ParseClientID to check a string. Two ClientIDs are the same client only if their strings are identical (Section 3).
ParseClientID source
func ParseClientID(s string) (ClientID, error)ParseClientID returns s as a ClientID, or ErrInvalidClientID unless, following Section 3, it uses https, has a host and a path, and has no userinfo, fragment, or "." or ".." path segment. A query is allowed, since Section 3 only says it SHOULD NOT be there.
(ClientID) Host source
func (c ClientID) Host() stringHost returns the URL's host name, without the port. Show it to the user when asking them to authorize the client, since anyone can choose the client name in the document, but not the host it's served from.
(ClientID) String source
func (c ClientID) String() stringString returns the URL.
Document source
type Document struct {
ClientID string `json:"client_id"`
ClientName string `json:"client_name,omitempty"`
ClientURI string `json:"client_uri,omitempty"`
LogoURI string `json:"logo_uri,omitempty"`
RedirectURIs []string `json:"redirect_uris,omitempty"`
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`
GrantTypes []string `json:"grant_types,omitempty"`
ResponseTypes []string `json:"response_types,omitempty"`
Scope string `json:"scope,omitempty"`
JWKSURI string `json:"jwks_uri,omitempty"`
}Document is the client metadata in a Client ID Metadata Document: the RFC 7591 members an authorization server needs to show and redirect to the client. Read one with ParseDocument.
See Section 4.
ParseDocument source
func ParseDocument(data []byte, id ClientID) (Document, error)ParseDocument reads the Client ID Metadata Document fetched from the client ID, and returns ErrInvalidDocument if it isn't a JSON object or:
- its client_id isn't identical to the URL it was fetched from (Section 4);
- its token_endpoint_auth_method is one based on a shared secret, or it has client_secret or client_secret_expires_at (Section 4.1);
- its jwks has private key material (Section 4.1);
- a redirect URI isn't an absolute URI without a fragment.
It doesn't limit the size of data. Read at most MaxDocumentSize bytes first.