mirror of
https://github.com/hanzoai/idv.git
synced 2026-10-30 18:33:39 +00:00
A webhook carries a verdict about a person's identity and arrives on an endpoint reachable from the public internet, so authenticity is the first thing ParseWebhook establishes. Two primitives, one policy: verifyHMAC — hex-encoded HMAC-SHA256 over the raw body, constant-time over the decoded digest. An empty secret refuses rather than skips: HMAC under a known-empty key is computable by any caller. header — case-insensitive lookup, because net/http canonicalizes the wire's X-SHA2-Signature to X-Sha2-Signature and an exact match finds nothing. Onfido now checks X-SHA2-Signature against WebhookToken before decoding; the field was declared for that purpose and never read, so any caller who could reach the endpoint could inject an approved verdict. Jumio keeps Callback-Sig but routes through the shared primitives, which closes the empty-secret case its own comparison admitted. Plaid refuses: its verdicts are signed by a JWT whose key must be fetched from Plaid, so CheckStatus is the authenticated path and the unreachable result fetch is gone. LexisNexis, Intellicheck, IDMerit and Berbix refuse for the same reason — no scheme implemented, no claim believed — and now satisfy the Provider interface they were written against, which the compile-time assertions in provider.go keep true. TestProviderWebhookAuth drives the property from every provider in the package plus a sweep of the factory registry, so one added later inherits it: no signature, a wrong one, a valid one over different bytes, and an empty secret each yield an error and no event. The positive tests pin the other failure mode — a guard that refuses everything, including genuine callbacks — across both header spellings and either hex case. The service binary passes IDV_API_SECRET to Jumio and Plaid, which it previously dropped; without it the guard can never admit a real callback and polling cannot authenticate. Co-authored-by: Hanzo Dev <[email protected]>
31 lines
1.0 KiB
Go
31 lines
1.0 KiB
Go
// Package berbix implements the IDV provider for Berbix.
|
|
package provider
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
type BerbixConfig struct {
|
|
BaseURL string
|
|
APIKey string
|
|
APISecret string
|
|
}
|
|
|
|
type Berbix struct{ cfg BerbixConfig }
|
|
|
|
func NewBerbix(cfg BerbixConfig) *Berbix { return &Berbix{cfg: cfg} }
|
|
func (p *Berbix) Name() string { return ProviderBerbix }
|
|
func (p *Berbix) InitiateVerification(ctx context.Context, user *VerificationRequest) (*VerificationResponse, error) {
|
|
return nil, fmt.Errorf("berbix: not yet implemented")
|
|
}
|
|
func (p *Berbix) CheckStatus(ctx context.Context, sessionID string) (*VerificationStatusResult, error) {
|
|
return nil, fmt.Errorf("berbix: not yet implemented")
|
|
}
|
|
|
|
// ParseWebhook refuses every payload: with no Berbix callback signature scheme
|
|
// implemented here, an arriving payload is a caller's claim, not a verdict.
|
|
func (p *Berbix) ParseWebhook(body []byte, headers map[string]string) (*WebhookEvent, error) {
|
|
return nil, fmt.Errorf("berbix webhook verification is not implemented: %w", ErrWebhookUnsigned)
|
|
}
|