Skip to content

Commit

Permalink
Change Get() API (#990)
Browse files Browse the repository at this point in the history
* Chage Get(string) (interface{}, bool) to Get(string, interface{}) error

* fix example code

* run go mod tidy

* more bazel tweaks

* Documentation fixes

* Generate jws docs

* fix go.mod
  • Loading branch information
lestrrat committed Dec 6, 2023
1 parent ed3e38c commit 7b06ff0
Show file tree
Hide file tree
Showing 47 changed files with 1,700 additions and 702 deletions.
4 changes: 2 additions & 2 deletions bench/performance/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etly
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8=
Expand Down
2 changes: 1 addition & 1 deletion cmd/jwx/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc v1.0.4 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
Expand Down
4 changes: 2 additions & 2 deletions cmd/jwx/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etly
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8=
Expand Down
3 changes: 2 additions & 1 deletion docs/01-jwt.md
Original file line number Diff line number Diff line change
Expand Up @@ -1234,7 +1234,8 @@ Please [look at the JWS documentation for it](./02-jws.md#parse-a-jws-message-an
Any field in the token can be accessed in an uniform away using `(jwt.Token).Get()`

```go
v, ok := token.Get(name)
var v interface{} // can be concrete type, if you know the type beforehand
err := token.Get(name, &v)
```

If the field corresponding to `name` does not exist, the second return value will be `false`.
Expand Down
4 changes: 2 additions & 2 deletions docs/20-global-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ This tells the decoder that when it encounters a JWT token with the field named
access this value by using `Get()`

```go
v, _ := token.Get(`x-foo-bar`)
foobar := v.(mypkg.FooBar)
var v mypkg.FooBar
_ = token.Get(`x-foo-bar`, &v)
```

Do be aware that this has *global* effect. In the above example, all JWT tokens containing
Expand Down
30 changes: 15 additions & 15 deletions examples/jwe_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,24 +82,24 @@ func ExampleJWE_ComplexDecrypt() {
// I would personally recommend creating a real type for your specific needs
// instead of passing adhoc closures. YMMV.
kp := func(ctx context.Context, sink jwe.KeySink, _ jwe.Recipient, msg *jwe.Message) error {
rawhint, _ := msg.ProtectedHeaders().Get(`jwx-hints`)
//nolint:forcetypeassert
hint, ok := rawhint.(string)
if ok && hint == `foobar` {
// This is where we are setting the key to be used.
//
// In real life you would look up the key or something.
// Here we just assign the key to use.
//
// You may opt to set both the algorithm and key here as well.
// BUT BE CAREFUL so that you don't accidentally create a
// vulnerability
sink.Key(jwa.RSA_OAEP, privkey)
return nil
var hint string
if err := msg.ProtectedHeaders().Get(`jwx-hints`, &hint); err == nil {
if hint == `foobar` {
// This is where we are setting the key to be used.
//
// In real life you would look up the key or something.
// Here we just assign the key to use.
//
// You may opt to set both the algorithm and key here as well.
// BUT BE CAREFUL so that you don't accidentally create a
// vulnerability
sink.Key(jwa.RSA_OAEP, privkey)
return nil
}
}

// If there were errors, just return it, and the whole jwe.Decrypt will fail.
return fmt.Errorf(`invalid value for jwx-hints: %s`, rawhint)
return fmt.Errorf(`invalid value for jwx-hints`)
}

// Calling jwe.Decrypt with the extra argument of jwe.WithPostParser().
Expand Down
18 changes: 12 additions & 6 deletions examples/jwt_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,18 @@ func ExampleJWT_Sign_WithImportJWK() {

fmt.Printf("%s\n", buf)

if v, ok := t.Get(`privateClaimKey`); ok {
fmt.Printf("privateClaimKey -> '%s'\n", v)
var pc string
if err := t.Get(`privateClaimKey`, &pc); err != nil {
fmt.Printf("failed to fetch private claim\n")
return
}
fmt.Printf("privateClaimKey -> '%s'\n", pc)

//convert jwk in bytes and return a new key
jwkey, err := jwk.ParseKey([]byte(jwkStr))

if err != nil {
log.Fatal("erro")
fmt.Printf("failed to parse key: %s\n", err)
return
}

// signed and return a jwt
Expand Down Expand Up @@ -205,9 +208,12 @@ func ExampleJWT_Token() {
fmt.Printf("%s\n", buf)
fmt.Printf("aud -> '%s'\n", t.Audience())
fmt.Printf("iat -> '%s'\n", t.IssuedAt().Format(time.RFC3339))
if v, ok := t.Get(`privateClaimKey`); ok {
fmt.Printf("privateClaimKey -> '%s'\n", v)
var pc string
if err := t.Get(`privateClaimKey`, &pc); err != nil {
fmt.Printf("failed to fetch private claim\n")
return
}
fmt.Printf("privateClaimKey -> '%s'\n", pc)
fmt.Printf("sub -> '%s'\n", t.Subject())

// OUTPUT:
Expand Down
35 changes: 17 additions & 18 deletions examples/jwt_get_claims_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,23 @@ func ExampleJWT_GetClaims() {
var _ string = tok.Issuer()
var _ string = tok.Subject()

var v interface{}
var ok bool

// But you can also get them via the generic `.Get()` method.
// However, v is of type interface{}, so you might need to
// use a type switch to properly use its value.
// However, you would need to decide for yourself what the
// return type is. If you don't need the exact type, you could
// use interface{}, or you could use the specific time.Time
// type
//
// For the key name you could also use jwt.IssuedAtKey constant
v, ok = tok.Get(`iat`)
var iat time.Time
_ = tok.Get(`iat`, &iat)

// var iat interface{} would also work, but you would need to
// convert the type if you need time.Time specific behavior

// Private claims
v, ok = tok.Get(`claim1`)
v, ok = tok.Get(`claim2`)
var dummy interface{}
_ = tok.Get(`claim1`, &dummy)
_ = tok.Get(`claim2`, &dummy)

// However, it is possible to globally specify that a private
// claim should be parsed into a custom type.
Expand All @@ -50,18 +54,13 @@ func ExampleJWT_GetClaims() {
fmt.Printf(`failed to parse token: %s`, err)
return
}
v, ok = tok.Get(`claim2`)
if !ok {
fmt.Printf(`failed to get private claim "claim2"`)
return
}
if _, ok := v.(time.Time); !ok {
fmt.Printf(`claim2 expected to be time.Time, but got %T`, v)

// now you can use the exact type
var claim2 time.Time
if err := tok.Get(`claim2`, &claim2); err != nil {
fmt.Printf("failed to get private claim \"claim2\": %s\n", err)
return
}

_ = v
_ = ok

// OUTPUT:
}
11 changes: 3 additions & 8 deletions jwe/gh402_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/lestrrat-go/jwx/v3/jwa"
"github.com/lestrrat-go/jwx/v3/jwe"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// Pin represents the structured clevis data which can be used to decrypt the jwe message
Expand Down Expand Up @@ -86,14 +87,8 @@ func TestGH402(t *testing.T) {
return
}

v, ok := m.ProtectedHeaders().Get("clevis")
if !assert.True(t, ok, `m.Get("clevis") should be true`) {
return
}

if !assert.IsType(t, Pin{}, v, `result of m.Get("clevis") should be an instance of Pin{}`) {
return
}
var v Pin
require.NoError(t, m.ProtectedHeaders().Get("clevis", &v), `m.Get("clevis") should be succeed`)
}
}
decrypt(false)
Expand Down
Loading

0 comments on commit 7b06ff0

Please sign in to comment.