diff --git a/nats.go b/nats.go index bea0d3dfc..ec28bb7b6 100644 --- a/nats.go +++ b/nats.go @@ -1083,6 +1083,28 @@ func UserCredentials(userOrChainedFile string, seedFiles ...string) Option { return UserJWT(userCB, sigCB) } +// UserJWTAndSeed is a convenience function that takes the JWT and seed +// values as strings. +func UserJWTAndSeed(jwt string, seed string) Option { + userCB := func() (string, error) { + return jwt, nil + } + + sigCB := func(nonce []byte) ([]byte, error) { + kp, err := nkeys.FromSeed([]byte(seed)) + if err != nil { + return nil, fmt.Errorf("unable to extract key pair from seed: %v", err) + } + // Wipe our key on exit. + defer kp.Wipe() + + sig, _ := kp.Sign(nonce) + return sig, nil + } + + return UserJWT(userCB, sigCB) +} + // UserJWT will set the callbacks to retrieve the user's JWT and // the signature callback to sign the server nonce. This an the Nkey // option are mutually exclusive. diff --git a/nats_test.go b/nats_test.go index 1b5ce5ef5..176f6d0e1 100644 --- a/nats_test.go +++ b/nats_test.go @@ -1576,6 +1576,21 @@ func TestUserCredentialsChainedFile(t *testing.T) { } } +func TestUserJWTAndSeed(t *testing.T) { + if server.VERSION[0] == '1' { + t.Skip() + } + ts := runTrustServer() + defer ts.Shutdown() + + url := fmt.Sprintf("nats://127.0.0.1:%d", TEST_PORT) + nc, err := Connect(url, UserJWTAndSeed(uJWT, string(uSeed))) + if err != nil { + t.Fatalf("Expected to connect, got %v", err) + } + nc.Close() +} + func TestExpiredAuthentication(t *testing.T) { // The goal of these tests was to check how a client with an expiring JWT // behaves. It should receive an async -ERR indicating that the auth