sonr/crypto/didkey/resolver.go
Prad Nukala 31bcc21c35
feature/1121 implement ucan validation (#1176)
- **refactor: remove unused auth components**
- **refactor: improve devbox configuration and deployment process**
- **refactor: improve devnet and testnet setup**
- **fix: update templ version to v0.2.778**
- **refactor: rename pkl/net.matrix to pkl/matrix.net**
- **refactor: migrate webapp components to nebula**
- **refactor: protobuf types**
- **chore: update dependencies for improved security and stability**
- **feat: implement landing page and vault gateway servers**
- **refactor: Migrate data models to new module structure and update
related files**
- **feature/1121-implement-ucan-validation**
- **refactor: Replace hardcoded constants with model types in attns.go**
- **feature/1121-implement-ucan-validation**
- **chore: add origin Host struct and update main function to handle
multiple hosts**
- **build: remove unused static files from dwn module**
- **build: remove unused static files from dwn module**
- **refactor: Move DWN models to common package**
- **refactor: move models to pkg/common**
- **refactor: move vault web app assets to embed module**
- **refactor: update session middleware import path**
- **chore: configure port labels and auto-forwarding behavior**
- **feat: enhance devcontainer configuration**
- **feat: Add UCAN middleware for Echo with flexible token validation**
- **feat: add JWT middleware for UCAN authentication**
- **refactor: update package URI and versioning in PklProject files**
- **fix: correct sonr.pkl import path**
- **refactor: move JWT related code to auth package**
- **feat: introduce vault configuration retrieval and management**
- **refactor: Move vault components to gateway module and update file
paths**
- **refactor: remove Dexie and SQLite database implementations**
- **feat: enhance frontend with PWA features and WASM integration**
- **feat: add Devbox features and streamline Dockerfile**
- **chore: update dependencies to include TigerBeetle**
- **chore(deps): update go version to 1.23**
- **feat: enhance devnet setup with PATH environment variable and
updated PWA manifest**
- **fix: upgrade tigerbeetle-go dependency and remove indirect
dependency**
- **feat: add PostgreSQL support to devnet and testnet deployments**
- **refactor: rename keyshare cookie to token cookie**
- **feat: upgrade Go version to 1.23.3 and update dependencies**
- **refactor: update devnet and testnet configurations**
- **feat: add IPFS configuration for devnet**
- **I'll help you update the ipfs.config.pkl to include all the peers
from the shell script. Here's the updated configuration:**
- **refactor: move mpc package to crypto directory**
- **feat: add BIP32 support for various cryptocurrencies**
- **feat: enhance ATN.pkl with additional capabilities**
- **refactor: simplify smart account and vault attenuation creation**
- **feat: add new capabilities to the Attenuation type**
- **refactor: Rename MPC files for clarity and consistency**
- **feat: add DIDKey support for cryptographic operations**
- **feat: add devnet and testnet deployment configurations**
- **fix: correct key derivation in bip32 package**
- **refactor: rename crypto/bip32 package to crypto/accaddr**
- **fix: remove duplicate indirect dependency**
- **refactor: move vault package to root directory**
- **refactor: update routes for gateway and vault**
- **refactor: remove obsolete web configuration file**
- **refactor: remove unused TigerBeetle imports and update host
configuration**
- **refactor: adjust styles directory path**
- **feat: add broadcastTx and simulateTx functions to gateway**
- **feat: add PinVault handler**
2024-12-02 14:27:18 -05:00

133 lines
3.3 KiB
Go

package didkey
import (
"context"
"fmt"
"github.com/golang-jwt/jwt"
"github.com/ucan-wg/go-ucan"
"github.com/ucan-wg/go-ucan/didkey"
)
// DIDPubKeyResolver turns did:key Decentralized IDentifiers into a public key,
// possibly using a network request
type DIDPubKeyResolver interface {
ResolveDIDKey(ctx context.Context, did string) (ID, error)
}
// TokenParser parses a raw string into a Token
type TokenParser struct {
ap ucan.AttenuationConstructorFunc
cidr ucan.CIDBytesResolver
didr DIDPubKeyResolver
}
// NewTokenParser constructs a token parser
func NewTokenParser(ap ucan.AttenuationConstructorFunc, didr DIDPubKeyResolver, cidr ucan.CIDBytesResolver) *TokenParser {
return &TokenParser{
ap: ap,
cidr: cidr,
didr: didr,
}
}
// ParseAndVerify will parse, validate and return a token
func (p *TokenParser) ParseAndVerify(ctx context.Context, raw string) (*ucan.Token, error) {
return p.parseAndVerify(ctx, raw, nil)
}
func (p *TokenParser) parseAndVerify(ctx context.Context, raw string, _ *ucan.Token) (*ucan.Token, error) {
tok, err := jwt.Parse(raw, p.matchVerifyKeyFunc(ctx))
if err != nil {
return nil, fmt.Errorf("parsing UCAN: %w", err)
}
mc, ok := tok.Claims.(jwt.MapClaims)
if !ok {
return nil, fmt.Errorf("parser fail")
}
var iss didkey.ID
// TODO(b5): we're double parsing here b/c the jwt lib we're using doesn't expose
// an API (that I know of) for storing parsed issuer / audience
if issStr, ok := mc["iss"].(string); ok {
iss, err = didkey.Parse(issStr)
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf(`"iss" key is not in claims`)
}
var aud didkey.ID
// TODO(b5): we're double parsing here b/c the jwt lib we're using doesn't expose
// an API (that I know of) for storing parsed issuer / audience
if audStr, ok := mc["aud"].(string); ok {
aud, err = didkey.Parse(audStr)
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf(`"aud" key is not in claims`)
}
var att ucan.Attenuations
if acci, ok := mc[ucan.AttKey].([]interface{}); ok {
for i, a := range acci {
if mapv, ok := a.(map[string]interface{}); ok {
a, err := p.ap(mapv)
if err != nil {
return nil, err
}
att = append(att, a)
} else {
return nil, fmt.Errorf(`"att[%d]" is not an object`, i)
}
}
} else {
return nil, fmt.Errorf(`"att" key is not an array`)
}
var prf []ucan.Proof
if prfi, ok := mc[ucan.PrfKey].([]interface{}); ok {
for i, a := range prfi {
if pStr, ok := a.(string); ok {
prf = append(prf, ucan.Proof(pStr))
} else {
return nil, fmt.Errorf(`"prf[%d]" is not a string`, i)
}
}
} else if mc[ucan.PrfKey] != nil {
return nil, fmt.Errorf(`"prf" key is not an array`)
}
return &ucan.Token{
Raw: raw,
Issuer: iss,
Audience: aud,
Attenuations: att,
Proofs: prf,
}, nil
}
func (p *TokenParser) matchVerifyKeyFunc(ctx context.Context) func(tok *jwt.Token) (interface{}, error) {
return func(tok *jwt.Token) (interface{}, error) {
mc, ok := tok.Claims.(jwt.MapClaims)
if !ok {
return nil, fmt.Errorf("parser fail")
}
iss, ok := mc["iss"].(string)
if !ok {
return nil, fmt.Errorf(`"iss" claims key is required`)
}
id, err := p.didr.ResolveDIDKey(ctx, iss)
if err != nil {
return nil, err
}
return id.VerifyKey()
}
}