1

I have a web app which authenticates the user using an external identity provider (Microsoft Entra with MSAL library). This give us an access token to access our API.

After authentication (so, we already have the token), the user must select the company he wants to work with. The "company list" shows only those for which the user has permissions.

We would like to have the CompanyId in the token, but it is not known for the Identity Server at the moment of login (user interaction is needed to pick a company and Companies are a table in our DB, not in Active Directory).

After our user picks a Company, the CompanyId is added (as a custom header) to all http requests.

At this point, we are concerned about the security implicances. A malicious user could change the CompanyId (even if it is a hash) and access other's company data.

Is it a legit concern? What could we do to mitigate this risk?

We have considered:

  • Issue a second token (after Company pick) and include on it the CompanyId. Unfortunately, MSAL does not allow to build a token with data obtained outside of MSAL (as far as we know).
  • Check if the user has access to the company in every query to the DB.
  • Cypher the CompanyId in such a way that would not be useful to copy and paste for future use.

What would you recommend?

asked Feb 3, 2024 at 14:22
3
  • I think you can add custom claims to the token : learn.microsoft.com/en-us/entra/identity-platform/… Commented Feb 3, 2024 at 15:38
  • Thanks Ewan. Yes, we have tried that way, unfortunately Active Directory needs to know the CompanyId to generate the token. In our case, the user needs to pick this Id after login. Moreover, the Active Directory doesn't have any table with CompanyIds to pick from. Yes, we could assign a set of CompanyIds to each user (in a custom claim), but we will not know which one has been picked during authentication... unless somehow we add a kind of Select-box during login, but in that case, Active Directory would need to know the Company DB contents. Probably we are missing something tho. Commented Feb 3, 2024 at 18:08
  • if the user selects the company when they sign in, then you have no security hjowever you cut it. I assumed the user is selecting from an allowed list? you could put the allowed list in the token and validate the selected company against it Commented Feb 3, 2024 at 21:56

1 Answer 1

1

Is it a legit concern?

Yes. The Company-Id: header field you are describing is what's known as "attacker controlled data", so you should not blindly trust it.

After our user picks a Company, the CompanyId is added (as a custom header) to all http requests.

This makes it sound like User is running your JS in his browser, where he could e.g. modify the running code or interpose a MitM proxy. So our User controls the content of all web headers sent from client side.

Well, it's simple. Roll a secret random GUID, and call it key. It stays strictly on your server(s), and is never revealed to clients. Feel free to do routine key aging by re-rolling a new one every N weeks.

Think of the MSAL-issued token as being immutable. Look, but don't touch. It contains a username. The form of the token visible to your server will be called token. Server validates token each time it reads it, throwing fatal exception if it sees a tampered-with invalid one.

Upon obtaining validated token server prompts User to choose from his authorized set of companies, e.g. "Ace Chemicals" or "ACME". User is not authorized for "Ajax", a company an attacker would like to access.

Subsequent requests might include these headers, where 2nd one is an attack:

Company-Id: ACME
Company-Id: Ajax

As part of the prompting flow, server computes and sends a prefix of this validator: SHA3(key, username, "ACME") so we wind up with a header that looks like this:

Company-Id: ACME;3d8505637f64bb3c

(I am depicting hex nybbles, but you might prefer more efficient base64 encoding.)

The point is that server produces a validator just once, when the external identity provider has convinced it that User may legitimately access ACME. Thereafter, when reading the Company-Id: header, server will always re-compute the validator hash, and throw fatal exception upon mismatch. A company ID that survives this process may be trusted by server code.

answered Feb 3, 2024 at 15:37
1
  • Wonderful, this is a perfect match for our situation. Thanks! Commented Feb 3, 2024 at 18:01

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.