Skip to content

Commit

Permalink
fixup - impl
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewSisley committed Jul 10, 2024
1 parent 42507fc commit e831117
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 109 deletions.
16 changes: 12 additions & 4 deletions acp/identity/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/lestrrat-go/jwx/v2/jwa"
"github.com/lestrrat-go/jwx/v2/jwt"
"github.com/sourcenetwork/immutable"
acptypes "github.com/sourcenetwork/sourcehub/x/acp/bearer_token"
)

// didProducer generates a did:key from a public key
Expand All @@ -35,7 +36,7 @@ type Identity struct {
// PublicKey is the actor's public key.
PublicKey *secp256k1.PublicKey
// PrivateKey is the actor's private key.
PrivateKey *secp256k1.PrivateKey // todo - remove, it is only used in test
PrivateKey *secp256k1.PrivateKey
// DID is the actor's unique identifier.
//
// The address is derived from the actor's public key,
Expand All @@ -46,7 +47,14 @@ type Identity struct {
}

// FromPrivateKey returns a new identity using the given private key.
func FromPrivateKey( // todo - doc params
//
// - duration: The [time.Duration] that this identity is valid for.
// - audience: The audience that this identity is valid for. This is required
// by the Defra http client. For example `github.com/sourcenetwork/defradb`
// - authorizedAccount: An account that this identity is authorizing to make
// SourceHub calls on behalf of this actor. This is currently required when
// using the SourceHub ACP module.
func FromPrivateKey(
privateKey *secp256k1.PrivateKey,
duration time.Duration,
audience immutable.Option[string],
Expand All @@ -59,7 +67,7 @@ func FromPrivateKey( // todo - doc params
}

subject := hex.EncodeToString(publicKey.SerializeCompressed())
now := time.Now() // todo - probably best to parameterise this
now := time.Now()

jwtBuilder := jwt.NewBuilder()
jwtBuilder = jwtBuilder.Subject(subject)
Expand All @@ -78,7 +86,7 @@ func FromPrivateKey( // todo - doc params
}

if authorizedAccount.HasValue() {
err = token.Set("authorized_account", authorizedAccount.Value()) // todo - const?
err = token.Set(acptypes.AuthorizedAccountClaim, authorizedAccount.Value())
if err != nil {
return Identity{}, err
}
Expand Down
126 changes: 26 additions & 100 deletions http/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,141 +10,67 @@

package http

/*
import (
"encoding/hex"
"testing"
"time"

"github.com/lestrrat-go/jwx/v2/jwt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

acpIdentity "github.com/sourcenetwork/defradb/acp/identity"
"github.com/sourcenetwork/defradb/crypto"
"github.com/sourcenetwork/immutable"
)

func TestBuildAuthToken(t *testing.T) {
privKey, err := crypto.GenerateSecp256k1()
require.NoError(t, err)
identity, err := acpIdentity.FromPrivateKey(privKey)
require.NoError(t, err)
token, err := buildAuthToken(identity.Value(), "abc123")
require.NoError(t, err)
subject := hex.EncodeToString(privKey.PubKey().SerializeCompressed())
assert.Equal(t, subject, token.Subject())
assert.True(t, token.NotBefore().Before(time.Now()))
assert.True(t, token.Expiration().After(time.Now()))
assert.Equal(t, []string{"abc123"}, token.Audience())
}
func TestSignAuthTokenErrorsWithPublicIdentity(t *testing.T) {
privKey, err := crypto.GenerateSecp256k1()
require.NoError(t, err)
identity, err := acpIdentity.FromPublicKey(privKey.PubKey())
require.NoError(t, err)
token, err := buildAuthToken(identity.Value(), "abc123")
require.NoError(t, err)
_, err = signAuthToken(identity.Value(), token)
assert.ErrorIs(t, err, ErrMissingIdentityPrivateKey)
}
func TestVerifyAuthToken(t *testing.T) {
privKey, err := crypto.GenerateSecp256k1()
require.NoError(t, err)
audience := "abc123"

identity, err := acpIdentity.FromPrivateKey(privKey)
require.NoError(t, err)
token, err := buildAndSignAuthToken(identity.Value(), "abc123")
privKey, err := crypto.GenerateSecp256k1()
require.NoError(t, err)

actual, err := verifyAuthToken(token, "abc123")
identity, err := acpIdentity.FromPrivateKey(
privKey,
time.Hour,
immutable.Some(audience),
immutable.None[string](),
)
require.NoError(t, err)

expected, err := acpIdentity.FromPublicKey(privKey.PubKey())
err = verifyAuthToken(identity, audience)
require.NoError(t, err)
assert.Equal(t, expected.Value().DID, actual.Value().DID)
}

func TestVerifyAuthTokenErrorsWithNonMatchingAudience(t *testing.T) {
privKey, err := crypto.GenerateSecp256k1()
require.NoError(t, err)

identity, err := acpIdentity.FromPrivateKey(privKey)
require.NoError(t, err)
token, err := buildAndSignAuthToken(identity.Value(), "valid")
require.NoError(t, err)
_, err = verifyAuthToken(token, "invalid")
assert.Error(t, err)
}
func TestVerifyAuthTokenErrorsWithWrongPublicKey(t *testing.T) {
privKey, err := crypto.GenerateSecp256k1()
require.NoError(t, err)
otherKey, err := crypto.GenerateSecp256k1()
require.NoError(t, err)
identity, err := acpIdentity.FromPrivateKey(privKey)
require.NoError(t, err)
token, err := buildAuthToken(identity.Value(), "123abc")
require.NoError(t, err)
// override subject
subject := hex.EncodeToString(otherKey.PubKey().SerializeCompressed())
err = token.Set(jwt.SubjectKey, subject)
require.NoError(t, err)
data, err := signAuthToken(identity.Value(), token)
identity, err := acpIdentity.FromPrivateKey(
privKey,
time.Hour,
immutable.Some("valid"),
immutable.None[string](),
)
require.NoError(t, err)

_, err = verifyAuthToken(data, "123abc")
err = verifyAuthToken(identity, "invalid")
assert.Error(t, err)
}

func TestVerifyAuthTokenErrorsWithExpired(t *testing.T) {
privKey, err := crypto.GenerateSecp256k1()
require.NoError(t, err)
audience := "abc123"

identity, err := acpIdentity.FromPrivateKey(privKey)
require.NoError(t, err)
token, err := buildAuthToken(identity.Value(), "123abc")
require.NoError(t, err)
// override expiration
err = token.Set(jwt.ExpirationKey, time.Now().Add(-15*time.Minute))
require.NoError(t, err)
data, err := signAuthToken(identity.Value(), token)
require.NoError(t, err)
_, err = verifyAuthToken(data, "123abc")
assert.Error(t, err)
}
func TestVerifyAuthTokenErrorsWithNotBefore(t *testing.T) {
privKey, err := crypto.GenerateSecp256k1()
require.NoError(t, err)

identity, err := acpIdentity.FromPrivateKey(privKey)
require.NoError(t, err)
token, err := buildAuthToken(identity.Value(), "123abc")
require.NoError(t, err)
// override not before
err = token.Set(jwt.NotBeforeKey, time.Now().Add(15*time.Minute))
require.NoError(t, err)
data, err := signAuthToken(identity.Value(), token)
identity, err := acpIdentity.FromPrivateKey(
privKey,
// negative expiration
-time.Hour,
immutable.Some(audience),
immutable.None[string](),
)
require.NoError(t, err)

_, err = verifyAuthToken(data, "123abc")
err = verifyAuthToken(identity, "123abc")
assert.Error(t, err)
}
*/
14 changes: 10 additions & 4 deletions internal/db/p2p_schema_root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,19 @@ package db

import (
"context"
"encoding/hex"
"fmt"
"testing"
"time"

"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/sourcenetwork/immutable"
"github.com/stretchr/testify/require"

"github.com/sourcenetwork/defradb/acp"
acpIdentity "github.com/sourcenetwork/defradb/acp/identity"
"github.com/sourcenetwork/defradb/client"
"github.com/sourcenetwork/defradb/datastore/memory"
"github.com/sourcenetwork/defradb/event"
)

Expand Down Expand Up @@ -241,7 +249,6 @@ func TestGetAllP2PCollections_WithMultipleValidCollections_ShouldSucceed(t *test
require.Equal(t, []string{schema2.Root, schema1.Root}, cols)
}

/*
// This test documents that we don't allow adding p2p collections that have a policy
// until the following is implemented:
// TODO-ACP: ACP <> P2P https://github.com/sourcenetwork/defradb/issues/2366
Expand Down Expand Up @@ -272,10 +279,10 @@ func TestAddP2PCollectionsWithPermissionedCollection_Error(t *testing.T) {
privKeyBytes, err := hex.DecodeString("028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f")
require.NoError(t, err)
privKey := secp256k1.PrivKeyFromBytes(privKeyBytes)
identity, err := acpIdentity.FromPrivateKey(privKey)
identity, err := acpIdentity.FromPrivateKey(privKey, time.Hour, immutable.None[string](), immutable.None[string]())
require.NoError(t, err)

ctx = SetContextIdentity(ctx, identity)
ctx = SetContextIdentity(ctx, immutable.Some(identity))
policyResult, err := db.AddPolicy(ctx, policy)
policyID := policyResult.PolicyID
require.NoError(t, err)
Expand All @@ -298,4 +305,3 @@ func TestAddP2PCollectionsWithPermissionedCollection_Error(t *testing.T) {
require.Error(t, err)
require.ErrorIs(t, err, ErrP2PColHasPolicy)
}
*/
7 changes: 6 additions & 1 deletion tests/integration/acp.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ const (
LocalACPType ACPType = "local"
)

const (
// authTokenExpiration is the expiration time for auth tokens.
authTokenExpiration = time.Minute * 1
)

var (
acpType ACPType
)
Expand Down Expand Up @@ -408,7 +413,7 @@ func getIdentity(s *state, nodeIndex int, index immutable.Option[int]) immutable

identity, err := acpIdentity.FromPrivateKey(
privateKey,
time.Minute,
authTokenExpiration,
audience,
immutable.Some(s.sourcehubAddress),
)
Expand Down

0 comments on commit e831117

Please sign in to comment.