Documentation
¶
Overview ¶
Package dpop implements the DPoP protocol primitives used by OAuth token requests and Lark OpenAPI requests. Key contains only a public key and a stable signer handle.
Index ¶
- Constants
- Variables
- func IsClockRecoverySignal(code int, oauthError string) bool
- func NormalizeHTU(rawURL string) (string, error)
- func SynchronizeClock(ctx context.Context, httpClient *http.Client, brand core.LarkBrand, key *Key) error
- func WithBinding(ctx context.Context, binding *Binding) context.Context
- func WithTokenEndpointKey(ctx context.Context, key *Key) context.Context
- type AdjustableClock
- type Binding
- type Clock
- type ClockState
- type Key
- func (k *Key) Clock() *AdjustableClock
- func (k *Key) ID() string
- func (k *Key) Provider() string
- func (k *Key) PublicJWK() (keysigner.PublicJWK, error)
- func (k *Key) SecurityLevel() keysigner.SecurityLevel
- func (k *Key) SignProof(method, rawURL string) (string, error)
- func (k *Key) SignProofContext(ctx context.Context, method, rawURL string) (string, error)
- func (k *Key) Thumbprint() (string, error)
- type KeyStore
- func (s *KeyStore) Delete(id string) error
- func (s *KeyStore) DeleteContext(ctx context.Context, id string) error
- func (s *KeyStore) DeleteKeyContext(ctx context.Context, key *Key) error
- func (s *KeyStore) EnsureContext(ctx context.Context, id string) (*Key, error)
- func (s *KeyStore) Generate() (*Key, error)
- func (s *KeyStore) GenerateContext(ctx context.Context) (*Key, error)
- func (s *KeyStore) Load(id string) (*Key, error)
- func (s *KeyStore) LoadContext(ctx context.Context, id string) (*Key, error)
- func (s *KeyStore) PrepareReplaceableContext(ctx context.Context, id string) (*Key, bool, error)
- func (s *KeyStore) ProbeKeyWritableContext(ctx context.Context, key *Key) error
- func (s *KeyStore) ProbeWritableContext(ctx context.Context) error
- func (s *KeyStore) RequireKeyWritableContext(ctx context.Context, key *Key) error
- func (s *KeyStore) RequireWritableContext(ctx context.Context) error
- func (s *KeyStore) RequireWritableForReauthorizationContext(ctx context.Context) (bool, error)
- func (s *KeyStore) Save(key *Key) error
- func (s *KeyStore) SaveContext(ctx context.Context, key *Key) error
- type Transport
Constants ¶
const ( ProofHeader = "DPoP" Scheme = "DPoP" TokenType = "DPoP" ClockSkewErrorCode = 20153 InvalidProofOAuthError = "invalid_dpop_proof" )
const ( // exchange because it makes no claim about whether a request was sent. KeyStoreUnavailableHint = "" /* 253-byte string literal not displayed */ // only when key storage fails before the Token Endpoint request. KeyStorePreExchangeUnavailableHint = "no OAuth token request was sent; " + KeyStoreUnavailableHint // loaded or used to sign the protected resource request. KeyAccessUnavailableHint = "" /* 284-byte string literal not displayed */ )
const HeartbeatPath = "/accounts/status/heartbeat"
Variables ¶
var ErrInvalidProofResponse = errors.New("token endpoint returned " + InvalidProofOAuthError)
ErrInvalidProofResponse is a safe cause for typed errors derived from an InvalidProofOAuthError Token Endpoint response. It intentionally excludes the response description, token, proof, and key material.
var ErrKeyNotFound = errors.New("DPoP key not found")
var ErrRepeatedInvalidProof = errors.New("token endpoint rejected three consecutive DPoP proofs")
ErrRepeatedInvalidProof marks three consecutive explicit proof rejections during new token issuance. Callers own the preferred-mode fallback and key rollback.
Functions ¶
func IsClockRecoverySignal ¶
IsClockRecoverySignal reports whether a Token Endpoint response carries the complete server signal that permits a one-time DPoP clock correction. The OAuth error comparison is deliberately exact.
func NormalizeHTU ¶
NormalizeHTU produces the RFC 3986 form used by DPoP htu: scheme and host are lowercase, default ports/query/fragment/dot segments are removed, and percent encodings are canonicalized without changing path case.
func SynchronizeClock ¶
func SynchronizeClock(ctx context.Context, httpClient *http.Client, brand core.LarkBrand, key *Key) error
SynchronizeClock obtains the Accounts server time before a DPoP token request. The calibrated clock is kept on the key; callers decide when the corresponding key metadata becomes part of their token transaction.
Types ¶
type AdjustableClock ¶
type AdjustableClock struct {
// contains filtered or unexported fields
}
AdjustableClock is safe for concurrent proof generation and clock recovery.
func NewClock ¶
func NewClock(base Clock) *AdjustableClock
func NewClockWithState ¶
func NewClockWithState(base Clock, state ClockState) *AdjustableClock
func (*AdjustableClock) Now ¶
func (c *AdjustableClock) Now() time.Time
func (*AdjustableClock) RestoreState ¶
func (c *AdjustableClock) RestoreState(state ClockState)
RestoreState replaces the persisted calibration without reading the system clock. Token records can use this to remain the atomic source of truth for a UAT and its proof clock.
func (*AdjustableClock) SetServerTime ¶
func (c *AdjustableClock) SetServerTime(serverTime, localReceiveTime time.Time)
SetServerTime records serverTime-localReceiveTime as the shared DPoP clock offset used by proofs and DPoP-bound token lifetime calculations.
func (*AdjustableClock) State ¶
func (c *AdjustableClock) State() ClockState
type Binding ¶
type Binding struct {
Token string
KeyID string
JKT string
KeyStoreSecureLevel keysigner.SecurityLevel
// contains filtered or unexported fields
}
Binding associates a token with the only key that may prove possession of it.
func RestoreBinding ¶
type ClockState ¶
ClockState is the non-secret persistent state needed to restore a calibrated clock with its platform key.
type Key ¶
type Key struct {
// contains filtered or unexported fields
}
Key is a capability to sign with an ES256/P-256 key. It stores only the public key, a non-secret backend identifier, and the platform signer.
func (*Key) Clock ¶
func (k *Key) Clock() *AdjustableClock
func (*Key) SecurityLevel ¶
func (k *Key) SecurityLevel() keysigner.SecurityLevel
func (*Key) SignProofContext ¶
SignProofContext creates a one-use proof while preserving request cancellation through the platform signing boundary.
type KeyStore ¶
type KeyStore struct {
// contains filtered or unexported fields
}
KeyStore coordinates ordered signing backends with the CLI secret store. Metadata records contain no private keys. L3 keeps its file unlock secret in a separate keychain entry; the signer owns its encrypted private-key files.
func NewKeyStore ¶
func NewKeyStore(kc keychain.KeychainAccess) *KeyStore
func NewKeyStoreWithSigner ¶
func NewKeyStoreWithSigner(kc keychain.KeychainAccess, signer keysigner.Signer) *KeyStore
NewKeyStoreWithSigner is an injection seam for platform implementations and hermetic tests. Production callers should use NewKeyStore.
func (*KeyStore) DeleteContext ¶
func (*KeyStore) DeleteKeyContext ¶
DeleteKeyContext removes a key using the signer capability carried by the key itself. It is used to roll back a newly issued key before public metadata has been committed.
func (*KeyStore) EnsureContext ¶
EnsureContext opens or creates the key for a stable non-secret identifier. It is used for process-cached tenant tokens so repeated CLI invocations do not leave one new key per token issuance.
func (*KeyStore) Generate ¶
Generate creates a persistent P-256 key with the strongest usable backend. The caller must either Save it after the token transaction commits or delete it on failure.
func (*KeyStore) GenerateContext ¶
func (*KeyStore) LoadContext ¶
func (*KeyStore) PrepareReplaceableContext ¶
PrepareReplaceableContext opens a stable key or replaces unreadable backend state when no persisted token can still be bound to that key. This is intended for TAT, whose token and Binding are process-local. UAT callers must use LoadContext so an unusable bound key requires re-authorization instead of silent rebinding. Created is true only when the caller owns a new key and must delete it if the token issuance transaction does not commit. The identifier is a namespace: each backend uses its own stable key within it.
func (*KeyStore) ProbeKeyWritableContext ¶
ProbeKeyWritableContext validates metadata persistence and the exact signer already owned by a binding. It never selects or probes a different provider.
func (*KeyStore) ProbeWritableContext ¶
ProbeWritableContext verifies both public-metadata persistence and the exact generate/sign/delete capability needed by a DPoP flow. It must run before a Token Endpoint request when DPoP is required.
func (*KeyStore) RequireKeyWritableContext ¶
RequireKeyWritableContext validates metadata persistence and the exact signer already owned by a binding, returning the token-flow error shape on failure.
func (*KeyStore) RequireWritableContext ¶
RequireWritableContext fails before a Token Endpoint request when the resulting DPoP binding could not be persisted safely.
func (*KeyStore) RequireWritableForReauthorizationContext ¶
RequireWritableForReauthorizationContext performs the ordinary writable probe and repairs a definitively lost software unlock secret once. The repair deletes software keys that can no longer be decrypted, so callers must use it only while explicitly issuing a replacement credential.
type Transport ¶
type Transport struct {
Base http.RoundTripper
}
Transport signs access-token requests at the final request boundary. Place it inside retry transports so each attempt receives a fresh proof. Callers own destination policy and must clear DPoP headers and context whenever they remove Authorization; this transport does not restrict request origins.
func (*Transport) BaseRoundTripper ¶
func (t *Transport) BaseRoundTripper() http.RoundTripper
func (*Transport) WithBaseRoundTripper ¶
func (t *Transport) WithBaseRoundTripper(base http.RoundTripper) http.RoundTripper