refactor: rename UCAN -> Token
Merge pull request #3 from qri-io/refactor_token
This commit is contained in:
@@ -36,10 +36,10 @@ LOOP:
|
||||
return true
|
||||
}
|
||||
|
||||
// AttenuationConstructor is a function that creates an attenuation from a map
|
||||
// AttenuationConstructorFunc is a function that creates an attenuation from a map
|
||||
// Users of this package provide an Attenuation Constructor to the parser to
|
||||
// bind attenuation logic to a UCAN
|
||||
type AttenuationConstructor func(v map[string]interface{}) (Attenuation, error)
|
||||
type AttenuationConstructorFunc func(v map[string]interface{}) (Attenuation, error)
|
||||
|
||||
// Attenuation is a capability on a resource
|
||||
type Attenuation struct {
|
||||
|
||||
20
context.go
20
context.go
@@ -8,19 +8,19 @@ import (
|
||||
// package
|
||||
type CtxKey string
|
||||
|
||||
// UCANCtxKey is the key for adding an access UCAN to a context.Context
|
||||
const UCANCtxKey CtxKey = "UCAN"
|
||||
// TokenCtxKey is the key for adding an access UCAN to a context.Context
|
||||
const TokenCtxKey CtxKey = "UCAN"
|
||||
|
||||
// CtxWithUCAN adds a UCAN value to a context
|
||||
func CtxWithUCAN(ctx context.Context, t UCAN) context.Context {
|
||||
return context.WithValue(ctx, UCANCtxKey, t)
|
||||
// CtxWithToken adds a UCAN value to a context
|
||||
func CtxWithToken(ctx context.Context, t Token) context.Context {
|
||||
return context.WithValue(ctx, TokenCtxKey, t)
|
||||
}
|
||||
|
||||
// FromCtx extracts a Dataset reference from a given
|
||||
// context if one is set, returning nil otherwise
|
||||
func FromCtx(ctx context.Context) *UCAN {
|
||||
iface := ctx.Value(UCANCtxKey)
|
||||
if ref, ok := iface.(*UCAN); ok {
|
||||
// FromCtx extracts a token from a given context if one is set, returning nil
|
||||
// otherwise
|
||||
func FromCtx(ctx context.Context) *Token {
|
||||
iface := ctx.Value(TokenCtxKey)
|
||||
if ref, ok := iface.(*Token); ok {
|
||||
return ref
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/qri-io/ucan"
|
||||
)
|
||||
|
||||
func ExampleWalkthrough() {
|
||||
func Example() {
|
||||
source, err := ucan.NewPrivKeySource(keyOne)
|
||||
panicIfError(err)
|
||||
|
||||
@@ -23,7 +23,7 @@ func ExampleWalkthrough() {
|
||||
zero := time.Time{}
|
||||
|
||||
// create a root UCAN
|
||||
origin, err := source.NewOriginUCAN(subjectDID, att, nil, zero, zero)
|
||||
origin, err := source.NewOriginToken(subjectDID, att, nil, zero, zero)
|
||||
panicIfError(err)
|
||||
|
||||
id, err := origin.CID()
|
||||
@@ -35,7 +35,7 @@ func ExampleWalkthrough() {
|
||||
{caps.Cap("SUPER_USER"), ucan.NewStringLengthResource("dataset", "third:resource")},
|
||||
}
|
||||
|
||||
if _, err = source.NewAttenuatedUCAN(origin, subjectDID, att, nil, zero, zero); err != nil {
|
||||
if _, err = source.NewAttenuatedToken(origin, subjectDID, att, nil, zero, zero); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ func ExampleWalkthrough() {
|
||||
{caps.Cap("OVERWRITE"), ucan.NewStringLengthResource("dataset", "b5:world_bank_population:*")},
|
||||
}
|
||||
|
||||
derivedToken, err := source.NewAttenuatedUCAN(origin, subjectDID, att, nil, zero, zero)
|
||||
derivedToken, err := source.NewAttenuatedToken(origin, subjectDID, att, nil, zero, zero)
|
||||
panicIfError(err)
|
||||
|
||||
id, err = derivedToken.CID()
|
||||
@@ -67,7 +67,7 @@ func panicIfError(err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func exampleParser() *ucan.UCANParser {
|
||||
func exampleParser() *ucan.TokenParser {
|
||||
caps := ucan.NewNestedCapabilities("SUPER_USER", "OVERWRITE", "SOFT_DELETE", "REVISE", "CREATE")
|
||||
|
||||
ac := func(m map[string]interface{}) (ucan.Attenuation, error) {
|
||||
@@ -95,5 +95,5 @@ func exampleParser() *ucan.UCANParser {
|
||||
}
|
||||
|
||||
store := ucan.NewMemTokenStore()
|
||||
return ucan.NewUCANParser(ac, ucan.StringDIDPubKeyResolver{}, store.(ucan.CIDBytesResolver))
|
||||
return ucan.NewTokenParser(ac, ucan.StringDIDPubKeyResolver{}, store.(ucan.CIDBytesResolver))
|
||||
}
|
||||
|
||||
52
token.go
52
token.go
@@ -42,8 +42,9 @@ const (
|
||||
CapKey = "cap"
|
||||
)
|
||||
|
||||
// UCAN is a JSON Web Token (JWT) that contains special keys
|
||||
type UCAN struct {
|
||||
// Token is a JSON Web Token (JWT) that contains special keys that make the
|
||||
// token a UCAN
|
||||
type Token struct {
|
||||
// Entire UCAN as a signed JWT string
|
||||
Raw string
|
||||
// the "inputs" to this token, a chain UCAN tokens with broader scopes &
|
||||
@@ -57,7 +58,7 @@ type UCAN struct {
|
||||
}
|
||||
|
||||
// CID calculates the cid of a UCAN using the default prefix
|
||||
func (t *UCAN) CID() (cid.Cid, error) {
|
||||
func (t *Token) CID() (cid.Cid, error) {
|
||||
pref := cid.Prefix{
|
||||
Version: 1,
|
||||
Codec: cid.Raw,
|
||||
@@ -69,7 +70,7 @@ func (t *UCAN) CID() (cid.Cid, error) {
|
||||
}
|
||||
|
||||
// PrefixCID calculates the CID of a token with a supplied prefix
|
||||
func (t *UCAN) PrefixCID(pref cid.Prefix) (cid.Cid, error) {
|
||||
func (t *Token) PrefixCID(pref cid.Prefix) (cid.Cid, error) {
|
||||
return pref.Sum([]byte(t.Raw))
|
||||
}
|
||||
|
||||
@@ -115,8 +116,8 @@ type CIDBytesResolver interface {
|
||||
// implementations of Source must conform to the assertion test defined in the
|
||||
// spec subpackage
|
||||
type Source interface {
|
||||
NewOriginUCAN(subjectDID string, att Attenuations, fct []Fact, notBefore, expires time.Time) (*UCAN, error)
|
||||
NewAttenuatedUCAN(parent *UCAN, subjectDID string, att Attenuations, fct []Fact, notBefore, expires time.Time) (*UCAN, error)
|
||||
NewOriginToken(subjectDID string, att Attenuations, fct []Fact, notBefore, expires time.Time) (*Token, error)
|
||||
NewAttenuatedToken(parent *Token, subjectDID string, att Attenuations, fct []Fact, notBefore, expires time.Time) (*Token, error)
|
||||
}
|
||||
|
||||
type pkSource struct {
|
||||
@@ -127,7 +128,7 @@ type pkSource struct {
|
||||
verifyKey *rsa.PublicKey
|
||||
signKey *rsa.PrivateKey
|
||||
|
||||
ap AttenuationConstructor
|
||||
ap AttenuationConstructorFunc
|
||||
resolver CIDBytesResolver
|
||||
store TokenStore
|
||||
}
|
||||
@@ -187,19 +188,19 @@ func NewPrivKeySource(privKey crypto.PrivKey) (Source, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *pkSource) NewOriginUCAN(subjectDID string, att Attenuations, fct []Fact, nbf, exp time.Time) (*UCAN, error) {
|
||||
return a.newUCAN(subjectDID, nil, att, fct, nbf, exp)
|
||||
func (a *pkSource) NewOriginToken(subjectDID string, att Attenuations, fct []Fact, nbf, exp time.Time) (*Token, error) {
|
||||
return a.newToken(subjectDID, nil, att, fct, nbf, exp)
|
||||
}
|
||||
|
||||
func (a *pkSource) NewAttenuatedUCAN(parent *UCAN, subjectDID string, att Attenuations, fct []Fact, nbf, exp time.Time) (*UCAN, error) {
|
||||
func (a *pkSource) NewAttenuatedToken(parent *Token, subjectDID string, att Attenuations, fct []Fact, nbf, exp time.Time) (*Token, error) {
|
||||
if !parent.Attenuations.Contains(att) {
|
||||
return nil, fmt.Errorf("scope of ucan attenuations must be less than it's parent")
|
||||
}
|
||||
return a.newUCAN(subjectDID, append(parent.Proofs, Proof(parent.Raw)), att, fct, nbf, exp)
|
||||
return a.newToken(subjectDID, append(parent.Proofs, Proof(parent.Raw)), att, fct, nbf, exp)
|
||||
}
|
||||
|
||||
// CreateToken returns a new JWT token
|
||||
func (a *pkSource) newUCAN(subjectDID string, prf []Proof, att Attenuations, fct []Fact, nbf, exp time.Time) (*UCAN, error) {
|
||||
func (a *pkSource) newToken(subjectDID string, prf []Proof, att Attenuations, fct []Fact, nbf, exp time.Time) (*Token, error) {
|
||||
// create a signer for rsa 256
|
||||
t := jwt.New(a.signingMethod)
|
||||
|
||||
@@ -241,7 +242,7 @@ func (a *pkSource) newUCAN(subjectDID string, prf []Proof, att Attenuations, fct
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &UCAN{
|
||||
return &Token{
|
||||
Raw: raw,
|
||||
Attenuations: att,
|
||||
Facts: fct,
|
||||
@@ -249,10 +250,13 @@ func (a *pkSource) newUCAN(subjectDID string, prf []Proof, att Attenuations, fct
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DIDPubKeyResolver turns did:key Decentralized IDentifiers into a public key,
|
||||
// possibly using a network request
|
||||
type DIDPubKeyResolver interface {
|
||||
ResolveDIDKey(ctx context.Context, did string) (crypto.PubKey, error)
|
||||
}
|
||||
|
||||
// DIDStringFromPublicKey creates a did:key identifier string from a public key
|
||||
func DIDStringFromPublicKey(pub crypto.PubKey) (string, error) {
|
||||
rawPubBytes, err := pub.Raw()
|
||||
if err != nil {
|
||||
@@ -261,8 +265,12 @@ func DIDStringFromPublicKey(pub crypto.PubKey) (string, error) {
|
||||
return fmt.Sprintf("did:key:%s", base64.URLEncoding.EncodeToString(rawPubBytes)), nil
|
||||
}
|
||||
|
||||
// StringDIDPubKeyResolver implements the DIDPubKeyResolver interface without
|
||||
// any network backing. Works if the key string given contains the public key
|
||||
// itself
|
||||
type StringDIDPubKeyResolver struct{}
|
||||
|
||||
// ResolveDIDKey extracts a public key from a did:key string
|
||||
func (StringDIDPubKeyResolver) ResolveDIDKey(ctx context.Context, didStr string) (crypto.PubKey, error) {
|
||||
// id, err := did.Parse(didStr)
|
||||
// if err != nil {
|
||||
@@ -277,14 +285,16 @@ func (StringDIDPubKeyResolver) ResolveDIDKey(ctx context.Context, didStr string)
|
||||
return crypto.UnmarshalRsaPublicKey(data)
|
||||
}
|
||||
|
||||
type UCANParser struct {
|
||||
ap AttenuationConstructor
|
||||
// TokenParser parses a raw string into a Token
|
||||
type TokenParser struct {
|
||||
ap AttenuationConstructorFunc
|
||||
cidr CIDBytesResolver
|
||||
didr DIDPubKeyResolver
|
||||
}
|
||||
|
||||
func NewUCANParser(ap AttenuationConstructor, didr DIDPubKeyResolver, cidr CIDBytesResolver) *UCANParser {
|
||||
return &UCANParser{
|
||||
// NewTokenParser constructs a token parser
|
||||
func NewTokenParser(ap AttenuationConstructorFunc, didr DIDPubKeyResolver, cidr CIDBytesResolver) *TokenParser {
|
||||
return &TokenParser{
|
||||
ap: ap,
|
||||
cidr: cidr,
|
||||
didr: didr,
|
||||
@@ -292,11 +302,11 @@ func NewUCANParser(ap AttenuationConstructor, didr DIDPubKeyResolver, cidr CIDBy
|
||||
}
|
||||
|
||||
// ParseAndVerify will parse, validate and return a token
|
||||
func (p *UCANParser) ParseAndVerify(ctx context.Context, raw string) (*UCAN, error) {
|
||||
func (p *TokenParser) ParseAndVerify(ctx context.Context, raw string) (*Token, error) {
|
||||
return p.parseAndVerify(ctx, raw, nil)
|
||||
}
|
||||
|
||||
func (p *UCANParser) parseAndVerify(ctx context.Context, raw string, child *UCAN) (*UCAN, error) {
|
||||
func (p *TokenParser) parseAndVerify(ctx context.Context, raw string, child *Token) (*Token, error) {
|
||||
tok, err := jwt.Parse(raw, p.matchVerifyKeyFunc(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -337,14 +347,14 @@ func (p *UCANParser) parseAndVerify(ctx context.Context, raw string, child *UCAN
|
||||
return nil, fmt.Errorf(`"prf" key is not an array`)
|
||||
}
|
||||
|
||||
return &UCAN{
|
||||
return &Token{
|
||||
Raw: raw,
|
||||
Attenuations: att,
|
||||
Proofs: prf,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *UCANParser) matchVerifyKeyFunc(ctx context.Context) func(tok *jwt.Token) (interface{}, error) {
|
||||
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 {
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestPrivKeySource(t *testing.T) {
|
||||
}
|
||||
zero := time.Time{}
|
||||
|
||||
root, err := source.NewOriginUCAN(didStr, att, nil, zero, zero)
|
||||
root, err := source.NewOriginToken(didStr, att, nil, zero, zero)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -71,7 +71,7 @@ func TestPrivKeySource(t *testing.T) {
|
||||
{caps.Cap("OVERWRITE"), ucan.NewStringLengthResource("dataset", "b5:world_bank_population:*")},
|
||||
}
|
||||
|
||||
derivedToken, err := source.NewAttenuatedUCAN(root, didStr, att, nil, zero, zero)
|
||||
derivedToken, err := source.NewAttenuatedToken(root, didStr, att, nil, zero, zero)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -130,14 +130,14 @@ func TestTokenParse(t *testing.T) {
|
||||
}
|
||||
|
||||
store := ucan.NewMemTokenStore()
|
||||
p := ucan.NewUCANParser(ac, ucan.StringDIDPubKeyResolver{}, store.(ucan.CIDBytesResolver))
|
||||
p := ucan.NewTokenParser(ac, ucan.StringDIDPubKeyResolver{}, store.(ucan.CIDBytesResolver))
|
||||
_, err := p.ParseAndVerify(context.Background(), raw)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func mustCidString(t *testing.T, tok *ucan.UCAN) string {
|
||||
func mustCidString(t *testing.T, tok *ucan.Token) string {
|
||||
t.Helper()
|
||||
id, err := tok.CID()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user