'How to forward/pass windows authentication from client to another REST API in an ASP.NET Core app with Angular?

I am currently implementing an ASP.NET Core app with Angular as described here. With the help I got in this question, I was already able to get the application working locally and also on an IIS server in our test environment.

In this application, I have to communicate with another REST API which supports the following authentication types:

  • Kerberos
  • Basic
  • Bearer
  • Anonymous

For every request I perform against this API, I need to be authenticated as the same user which authenticated against my application (backend) via windows authentication. The reason for this is that all permissions regarding that API are connected to specific windows users or groups, so the API must know which user is performing the request so it only returns data which the user has access to.

Right now, I am a little bit confused about how to make this work because I never had to implement something similar before.

Which authentication method of the API do I have to use and what else do I have to consider/configure in order to forward the credentials/identity of the user to the API?



Solution 1:[1]

In order to come up with the best solution to your problem, first, you need to understand how Kerberos works at a conceptual level. A ticket by the caller (ex. user's browser) is obtained for a specific counterparty (service) by asking Active Directory KDC for a service ticket. This is done by presenting something called TGT ticket (think session / refresh token) to the KDC to prove caller's identity. TGT is obtained once when the app starts (and refreshed when closed to expiration). The KDC server will return a service ticket which contains the identity of the caller (user) and is encrypted with the password of the service. This means that anyone in possession of the credentials of the service to which the ticket is to be sent can decrypt the ticket and extract the user's identity. There's no communication to the Active Directory on the receiving side.

If you have a multi-hop service interaction such as yours where you need to propagate identity downstream, Kerberos has explicit support for this via a feature called delegation. Delegation allows the middle service to obtain new tickets as if they were the original user. There are few flavors to this feature:

Unconstrained delegation:

Unconstrained delegation is the oldest and most insecure method of propagating identity. Fundamentally it involves including a TGT ticket into the payload sent to the intermediatory service. Since anyone in possession of TGT ticket can be used to obtain new tickets to which it belongs, it allows intermediatory service to obtain tickets from KDC as if they were the original caller. For the purposes let's pretend Bob is the original user, Alex is a middle service, and Mike is the backend service where request actually ends up. The interaction works like this:

Unconstrained Delegation

  1. Bob: Hey KDC, I need a ticket to prove my identity to Alex. Here’s my Ticket Granting Ticket (TGT) to prove that I’m Bob
  2. KDC: Ok Bob, here’s your ticket to show to Alex that proves your identity. Since Alex is a trusted guy, I’m also including your TGT into the ticket so he can get stuff on your behalf by pretending to be you
  3. Bob: Hey Alex, I’m Bob, KDC told me to show you this ticket - you should be able to open it. And while you’re at it, fetch me a beer
  4. Alex (Bob): Hey KDC, I’m Bob and because I got this TGT, give me a ticket to prove my identity to Mike
  5. KDC: Ok Bob, here’s the ticket to show to Mike
  6. Alex (Bob): Hey Mike, get me a beer because I’m Bob, here’s a ticket from KDC proving that I’m Bob
  7. Mike: Hey Bob, you’re allowed to get beer, here you go.

This method has a serious security risk in that if the ticket sent by Bob to Alex is ever intercepted and "cracked", the attacker can use it to impersonate Bob to anyone on the network. If Bob is an AD admin and called a website that has a security flaw that allowed that ticket to be intercepted, there's a real risk that the attacker has obtained rights to do anything on your AD. Furthermore, since Kerberos tickets are derivatives of a user's password, a brute force attack can potentially expose the original password.

Constrained delegation

Constrained delegation improves significantly on security flaws of the unconstrained delegation. The way it works is we put a special flag on the intermediatory account (Alex) that allows him to obtain tickets from KDC to preconfigured list of counterparties. For example in the image below, Alex is allowed to impersonate Bob to Mike and nobody else. He's not even required to have any interaction with Bob - he can do it entirely on his own behalf. The interaction works as follows:

Constrained delegation

  1. Bob: Hey KDC, I need a ticket to prove my identity to Alex. Here’s my Ticket Granting Ticket (TGT) to prove that I’m Bob
  2. KDC: Ok Bob, here’s your ticket to show to Alex that proves your identity. 
  3. Bob: Hey Alex, I’m Bob, KDC told me to show you this ticket - you should be able to open it. And while you’re at it, fetch me a beer
  4. Alex: Hey KDC, I’m Alex (here’s my TGT), I want to be issued a ticket as if I’m Bob to prove my identity to Mike
  5. KDC: Ok Alex, I trust you to impersonate others when talking to Mike, here’s the ticket that will let you pretend that you’re Bob to show to Mike
  6. Alex (Bob): Hey Mike, get me a beer because I’m Bob, here’s a ticket from KDC proving that I’m Bob
  7. Mike: Hey Bob, you’re allowed to get beer, here you go.

Coming back to your specific scenario, you could go with the Kerberos delegation route. This will require some special configuration in active directory to setup - there's plenty of articles on the internet on how to configure each type of delegation.

But let's explore another option. You mentioned that downstream service supports Bearer (I assume JWT). Who's the the signer of these tickets? Because bearer tickets are often not scoped to specific audience (receiving party), anyone in possession of one can act as the original caller. This means that if you make your app obtain a JWT from an issuer that the downstream service trusts, you can just forward it to downstream without any special configuration. I'm going to assume your authentication provider is ADFS. Now you can configure ADFS to issue your app a JWT token that contains all the claims about the user. Assuming the JWT token it has the necessary claims to satisfy security requirements of both your app and the downstream app, the interaction would look as following:

  1. User tries to access a secure page on your app
  2. Your app redirects them to ADFS to obtain a JWT ticket.
  3. The user logs into ADFS (which may happen automatically if ADFS itself is configured to use Kerberos)
  4. The user is redirected back to your app and your app obtains JWT ticket via back channel
  5. You forward this JWT ticket to the trusted party as part of your service request (add HTTP header "Authorize: Bearer ").

One other thing that may be useful to you. I have a project that is able to convert Kerberos tickets into JWT and backwards. It acts like a proxy for your app (or a sidecar), manipulating the requests as they pass through. It may be helpful for your specific scenario. One advantage is that you're not tied to Windows with this: https://github.com/nmica/nmica.security

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Andrew Stakhov