In C# .NET Framework 4.8, I need to generate kerberos token in SPNGEO format so I can send it in Authorization header as Negotiate to my IIS server, where I have Windows Authentication enabled.
I am using code from this topic How to get Service Token from Kerberos using SSPI It is generating the kerberos token, but its not in SPNEGO format, so its not working when I use it.
I would like to obtain the same token as is generated with the use of Kerberos.NET library. Their token is working for me, but the issue is that I need to use credentials for generation and I don't want that, so I cannot use this library. I want to use DefaultCredentials but to get same token as with the use of from Kerberos.NET library. I was also trying to use SSPI directly and set package to Negotiate, which should give me SPNEGO format, but the token generated was not same as from Kerberos.NET library so its also not working.
How can I solve this please? Or maybe is there any configuraiton on my IIS that it will also accept tokens which are not in SPENGO format? Please help
In C# .NET Framework 4.8, I need to generate kerberos token in SPNGEO format so I can send it in Authorization header as Negotiate to my IIS server, where I have Windows Authentication enabled.
I am using code from this topic How to get Service Token from Kerberos using SSPI It is generating the kerberos token, but its not in SPNEGO format, so its not working when I use it.
I would like to obtain the same token as is generated with the use of Kerberos.NET library. Their token is working for me, but the issue is that I need to use credentials for generation and I don't want that, so I cannot use this library. I want to use DefaultCredentials but to get same token as with the use of from Kerberos.NET library. I was also trying to use SSPI directly and set package to Negotiate, which should give me SPNEGO format, but the token generated was not same as from Kerberos.NET library so its also not working.
How can I solve this please? Or maybe is there any configuraiton on my IIS that it will also accept tokens which are not in SPENGO format? Please help
Share Improve this question edited Jan 24 at 17:41 exeq asked Jan 17 at 15:00 exeqexeq 531 gold badge5 silver badges16 bronze badges 2- Are you expecting a 1:1 identical token from SSPI and Kerberos.NET? The question of format aside, Kerberos tokens are single-use (unlike tickets), so two calls will always return slightly different tokens. – grawity_u1686 Commented Jan 17 at 15:10
- Kereberos.NET is always creatring the same token. Ok so there is some difference between token and ticket? Maybe I need to generate a ticket. It doesn't need to be identical it it will work – exeq Commented Jan 17 at 15:18
1 Answer
Reset to default 1Looks like this is what you need:
Recommended Way
I'd recommend using the built-in framework classes WebRequest
or HttpClient
which can do Negotiate (SPNEGO) authorization this way:
var webRequest = WebRequest.CreateHttp(uri);
webRequest.UseDefaultCredentials = true;
using var httpClient = new HttpClient(new HttpClientHandler {
UseDefaultCredentials = true,
});
Workarounds
You can still try to generate the token on your own, but since Negotiate is a handshake, you would still need to get a server response to complete the handshake.
.NET 8
using System.Net;
using System.Net.Security;
var authClientOptions = new NegotiateAuthenticationClientOptions
{
Package = "Negotiate",
TargetName = $"HTTP/{hostFqdn}",
RequiredProtectionLevel = ProtectionLevel.Sign,
Credential = CredentialCache.DefaultNetworkCredentials,
};
using var authContext = new NegotiateAuthentication(authClientOptions);
var authClientToServer = authContext.GetOutgoingBlob("", out var statusCode);
Console.WriteLine(authClientToServer);
// statusCode is ContinueNeeded
Verify:
curl <url> -s -v -o nul -H "Authorization: Negotiate <token>"
.NET 4.8
Some of the classes that can do Negotiate handshake under the hood are NegotiateClient
and NegotiateStream
.
using var ms = new MemoryStream();
using var ns = new NegotiateStream(ms);
try
{
ns.AuthenticateAsClient(
CredentialCache.DefaultNetworkCredentials,
binding: null,
$"HTTP/{hostFqdn}",
ProtectionLevel.Sign,
TokenImpersonationLevel.Delegation);
}
catch (AuthenticationException e)
{
}
const int headerSize = 5;
var authClientToServer = Convert.ToBase64String(
ms.GetBuffer(),
headerSize,
(int)ms.Length - headerSize);
Console.WriteLine(authClientToServer);