From 1ddeceefd4542ce8909642ac83b71b751b329bc5 Mon Sep 17 00:00:00 2001 From: Derek Collison Date: Wed, 14 Dec 2022 13:33:16 -0800 Subject: [PATCH] Force authorization requests to have a public user nkey. This will be required for the user claim sent back from the authorization service to avoid replay attacks. Signed-off-by: Derek Collison --- v2/authorization_claims.go | 6 ++++++ v2/authorization_claims_test.go | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/v2/authorization_claims.go b/v2/authorization_claims.go index 0104835..f1eccc5 100644 --- a/v2/authorization_claims.go +++ b/v2/authorization_claims.go @@ -73,6 +73,7 @@ type ClientTLS struct { // will be sent to an external authorization service. type AuthorizationRequest struct { Server ServerID `json:"server_id"` + UserNkey string `json:"user_nkey"` ClientInformation ClientInformation `json:"client_info"` ConnectOptions ConnectOptions `json:"connect_opts"` TLS *ClientTLS `json:"client_tls,omitempty"` @@ -98,6 +99,11 @@ func NewAuthorizationRequestClaims(subject string) *AuthorizationRequestClaims { // Validate checks the generic and specific parts of the auth request jwt. func (ac *AuthorizationRequestClaims) Validate(vr *ValidationResults) { + if ac.UserNkey == "" { + vr.AddError("User nkey is required") + } else if !nkeys.IsValidPublicUserKey(ac.UserNkey) { + vr.AddError("User nkey %q is not a valid user public key", ac.UserNkey) + } ac.ClaimsData.Validate(vr) } diff --git a/v2/authorization_claims_test.go b/v2/authorization_claims_test.go index ea3ccb6..feb2746 100644 --- a/v2/authorization_claims_test.go +++ b/v2/authorization_claims_test.go @@ -27,8 +27,30 @@ func TestNewAuthorizationClaims(t *testing.T) { ac.Server.Name = "NATS-1" vr := CreateValidationResults() + + // Make sure that user nkey is required. ac.Validate(vr) + if vr.IsEmpty() || !vr.IsBlocking(false) { + t.Fatalf("Expected blocking error on an nkey user not being specified") + } + + // Make sure it is required to be valid public user nkey. + ac.UserNkey = "derek" + vr = CreateValidationResults() + ac.Validate(vr) + if vr.IsEmpty() || !vr.IsBlocking(false) { + t.Fatalf("Expected blocking error on invalid user nkey") + } + kp, err := nkeys.CreateUser() + if err != nil { + t.Fatalf("Error creating user: %v", err) + } + pub, _ := kp.PublicKey() + + ac.UserNkey = pub + vr = CreateValidationResults() + ac.Validate(vr) if !vr.IsEmpty() { t.Fatal("Valid authorization request will have no validation results") }