Implementing authorization on top of NServiceBus

I’m implementing authorization on top of NServiceBus + RabbitMQ. We are using TLS.

For the actual authorization we are using ClaimsPrincipal/ClaimsIdentity. It’s stored in the contex.Extensions bag (we have an extension method to easily access it).

To transport the principal to our micro services I’m using transport behaviors where I serialize the principal into a JWT token that are stored in an extra NSB message header. The secret used to generate the JWT token is stored in a protected location (haven’t decided on ProtectedStorage or just a shared folder with limited access).

To make sure that someone haven’t just copied that header and injected it into other messages I’m also calculating a HMAC checksum using the message body + the OriginatingEndpoint.

Is the OriginatingEndpoint header easily spoofed? Are there a better way to make sure that the message is from a trusted source?

Hi @jgauffin,

in theory any header can be easily spoofed, as it’s just a string/string key value. If you’re signing the message then the only option for a malicious user would be to gain access to the broker and send a malicious message. If they got access to the broker, they are already inside the system which means that any message/endpoint level defense is basically worthless, or near to worthless.

The only thing that can be a mitigation is that the message signing is done through a certificate that needs to be available to the endpoint, which means that a malicious user needs to gain access to one of te existing machines to get access to the certificate and it’s not anymore enough to get access to the broker only.

.m

Isn’t that the same thing as signing the message with HMAC though? The secret is protected on the local machine and you need to have access to the service account to retrieve it.

(I’ll just sign the message and skip the header when generating the hash).

Right. If the secret is in the machine protected strage, then yes. You need to gain access to the machine, and if that happens you’re already in trouble.

The other thing you need to think about is if the JWT token has an expiration mechanism built-in, I know very little of JWT tokens. Because if that’s the case what happens if message processing fails and the message if sent to the error queue? When the message is retried the JWT token might be expired.

I’ve set an expiration time to a week, so it’s handled.

Thank you for all the feedback.

Hi Jonas

More as an FYI. We recently updated our username using headers example to include a principle accessor

In case you require to inject the principles into other components via dependency injection this shows you how to achieve it. Of course using the context extension bag is an elegant way if you want to float the information into the handlers only without needing to rely on DI and “black magic” like AsyncLocals

Regards
Daniel