From e734f0198917efeb08cce6ca2dadb85a4155b5e1 Mon Sep 17 00:00:00 2001 From: Ivan Kozlovic Date: Wed, 20 May 2020 13:54:56 -0600 Subject: [PATCH] [ADDED] Support for JWT BearerToken Disables nonce signature for JWT that has the BearerToken boolean set to true. Signed-off-by: Ivan Kozlovic --- server/auth.go | 44 ++++++++++++++++++++++++-------------------- server/jwt_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 20 deletions(-) diff --git a/server/auth.go b/server/auth.go index d76327d9..2ae26655 100644 --- a/server/auth.go +++ b/server/auth.go @@ -427,28 +427,32 @@ func (s *Server) processClientOrLeafAuthentication(c *client) bool { c.Debugf("Account JWT has expired") return false } - // Verify the signature against the nonce. - if c.opts.Sig == "" { - c.Debugf("Signature missing") - return false - } - sig, err := base64.RawURLEncoding.DecodeString(c.opts.Sig) - if err != nil { - // Allow fallback to normal base64. - sig, err = base64.StdEncoding.DecodeString(c.opts.Sig) - if err != nil { - c.Debugf("Signature not valid base64") + // skip validation of nonce when presented with a bearer token + // FIXME: if BearerToken is only for WSS, need check for server with that port enabled + if !juc.BearerToken { + // Verify the signature against the nonce. + if c.opts.Sig == "" { + c.Debugf("Signature missing") + return false + } + sig, err := base64.RawURLEncoding.DecodeString(c.opts.Sig) + if err != nil { + // Allow fallback to normal base64. + sig, err = base64.StdEncoding.DecodeString(c.opts.Sig) + if err != nil { + c.Debugf("Signature not valid base64") + return false + } + } + pub, err := nkeys.FromPublicKey(juc.Subject) + if err != nil { + c.Debugf("User nkey not valid: %v", err) + return false + } + if err := pub.Verify(c.nonce, sig); err != nil { + c.Debugf("Signature not verified") return false } - } - pub, err := nkeys.FromPublicKey(juc.Subject) - if err != nil { - c.Debugf("User nkey not valid: %v", err) - return false - } - if err := pub.Verify(c.nonce, sig); err != nil { - c.Debugf("Signature not verified") - return false } if acc.checkUserRevoked(juc.Subject) { c.Debugf("User authentication revoked") diff --git a/server/jwt_test.go b/server/jwt_test.go index 183bda0f..4dbdf963 100644 --- a/server/jwt_test.go +++ b/server/jwt_test.go @@ -2449,3 +2449,49 @@ func TestJWTAccountLimitsMaxConnsAfterExpired(t *testing.T) { return nil }) } + +func TestBearerToken(t *testing.T) { + okp, _ := nkeys.FromSeed(oSeed) + akp, _ := nkeys.CreateAccount() + apub, _ := akp.PublicKey() + nac := jwt.NewAccountClaims(apub) + ajwt, err := nac.Encode(okp) + if err != nil { + t.Fatalf("Error generating account JWT: %v", err) + } + + nkp, _ := nkeys.CreateUser() + pub, _ := nkp.PublicKey() + nuc := newJWTTestUserClaims() + nuc.Subject = pub + // Set bearer token. + nuc.BearerToken = true + jwt, err := nuc.Encode(akp) + if err != nil { + t.Fatalf("Error generating user JWT: %v", err) + } + + s := opTrustBasicSetup() + defer s.Shutdown() + buildMemAccResolver(s) + addAccountToMemResolver(s, apub, ajwt) + + c, cr, _ := newClientForServer(s) + defer c.close() + + // Skip nonce signature... + + // PING needed to flush the +OK/-ERR to us. + cs := fmt.Sprintf("CONNECT {\"jwt\":%q,\"verbose\":true,\"pedantic\":true}\r\nPING\r\n", jwt) + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + c.parse([]byte(cs)) + wg.Done() + }() + l, _ := cr.ReadString('\n') + if !strings.HasPrefix(l, "+OK") { + t.Fatalf("Expected +OK, got %s", l) + } + wg.Wait() +}