Skip to content

Negotiate and JWT Bearer schemes to support Negotiate (Kerberos) authentication in an HTTP/2 context

License

Notifications You must be signed in to change notification settings

zyborg/Zyborg.AspNetCore.Authentication.NegotiatedToken

Repository files navigation

Zyborg.AspNetCore.Authentication.NegotiatedToken

Implements a compound authentication mechanism for ASP.NET Core using Negotiate and JWT Bearer schemes to support Negotiate (Kerberos) authentication in an HTTP/2 context.

⭐ I appreciate your star, it helps me decide to which OSS projects I should allocate my spare time.


GitHub WorkFlow - CI GitHub Release Notes (latest by date) Nuget  Release GitHub Preview


This repo defines a pair of complementary .NET Core packages (one each for server-side, and client-side) that implement a mechanism for effectively using Windows Authentication (NTLM/Kerberos/Negotiate) with an HTTP/2 connection, such as in the case of gRPC calls.

The Problem

Currently the use of Windows Authentication over HTTP is limited to HTTP/1.x connections because the Negotiate protocol is undefined and not supported for HTTP/2 connections.

In some cases this can be overcome by supporting mixed protocol versions within a single application, however this limitation poses a significant challenge for gRPC calls because gRPC is explicitly defined atop HTTP/2.

This Solution

In this repo we leverage the combination of two authentication schemes, Negotiate and JWT Bearer tokens, to provide a workable solution to this problem. The overall solution works as follows.

On the server-side, in an ASP.NET Core application:

  • Both HTTP/1.x and HTTP/2 should be enabled.
  • Both Negotiate and JWT Bearer authentication schemes are enabled and configured.
  • The JWT Bearer scheme is configured as the default authentication scheme.
  • A token endpoint is exposed that is explicitly protected by the Negotiate scheme.
  • The token endpoint returns a generated JWT token that contains some key identifying details about the authenticated user context extracted from the Negotiate scheme.
  • By default all other protected resources use the JWT Bearer scheme to authenticate.
  • The JWT Bearer scheme is configured to reproduce the authenticated user context extracted from the JWT token's user identifying details (i.e. reproduces the claims that were originally captured from the Negotiate scheme)
  • The JWT token has a relatively short lifetime (such as a few minutes) and so this process should be repeated every so often to minimize security attacks vulnerabilities

Because the JWT Bearer Token scheme is fully supported under gRPC (and thus under HTTP/2) we can protect gRPC services with this surrogate token and still have access to security context details from the Negotiate authentication scheme.

On the client-side, an application would need to implement a flow that is compatible with this setup:

  • A client would need to maintain some state associated with the server, specifically a JWT token.
  • The client needs to maintain a valid token (i.e. the token exists and has not expired).
  • For every call, regardless of which HTTP protocol version is being used for that call (HTTP/1.x or HTTP/2), the client checks for a valid token first; if the client does not have a valid token, it would first connect to the configured token endpoint on the target server to retrieve a fresh surrogate token to retrieve a fresh surrogate token. It would do so using HTTP/1.1 and with compatible Windows Authentication credentials.
  • For every call (or every call to a known authenticated endpoint), the client injects the surrogate token.

This Solution's Packages

This repo provides two nuget packages to implement the behavior above.

For the server-side, the Zyborg.AspNetCore.Authentication.NegotiatedToken package is provided that configures the two authentication schemes, Negotiate and JWT Bearer token. To work in a compatible fashion. It includes support for generating the JWT token with information extracted from the Negotiate scheme context, and for reproducing a security context from the incomging JWT tokens.

For the client-side the Zyborg.NegotiatedToken.Client provides a delegating HTTP handler that can be configured for an HTTP client that implements most of the logic described above. This client should be configured in concert with your own HTTP handler to ensure that Windows Authentication credentials are provided when prompted by the token endpoint authenticated by the Negotiate scheme.

Usage

Please see the examples provided for usage:

BONUS -- Call Windows Authenticated gRPC Services from AWS Lambda

  • Do you use AWS?
  • Do you use serverless functions via AWS Lambda?
  • Would you like to be able to call Windows Authenticated gRPC Services from your Lambda functions?

Take a look at this sample project that combines the Lambda Kerberos library with this NegotiatedToken compound authentication scheme to support this exact scenario.

About

Negotiate and JWT Bearer schemes to support Negotiate (Kerberos) authentication in an HTTP/2 context

Resources

License

Stars

Watchers

Forks

Languages