-
-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement NTLM Authentication #402
Comments
With #433, I'm considering making this an extension module for Pode instead - as it has to very Windows only interop functions that are required 🤔 |
I think it would make sense to drop this completely and have it handled by IIS on Windows instead, this avoids having too much Windows only code and uses builtin board functions available on Client and Server Windows Systems. |
I was thinking the same thing last week when I looked back at this issue, as IIS will take care of all NTLM and Kerberos auth. I'll add some notes to the IIS docs to reference NTLM/Kerberos auth (for anyone who searches the docs for them), and then close this issue. |
What if I want to host it on a non-windows machine. Seeing as pode is cross platform ? |
@ArieHein, this was an issue I was trying to find a solution to, but I couldn't find a decent way of doing NTLM/Kerberos on Linux. I managed to do the AD auth cross-plat due to OpenLDAP pretty much being a standard on most nix machines, but for NTLM I haven't found anything yet 🤔 I'll do the IIS docs and leave this issue open, because it would be nice to have a way of doing this without any extra hosting and cross-platform. One wild and crazy idea I had, which would make xplat easier, and using the existing AD support, was to move the 16-byte challenge that the AD generates into Pode - and Pode generates the Type 2 401 challenge. Though I'm not sure how this would fair security wise, and it would basically turn it into Digest. |
I have just successfully tested Kerberos authentication via IIS and I am excited about how easy it is to use something like this thanks Pode now in PoSh :-). Now since a few months there is the Pode.Kestrel module. Now I just read that Kestrela can also do Kerberos. Is there with the module the possibility of a Kerberos authentication without IIS? |
Yeah, I imagine it'll be similar to how HttpListener handled it via HTTP.sys. I want to add in Kerberos authentication support for Pode, without IIS, but I want it to be cross-platform. When I last looked trying to find useful resources was difficult, but perhaps that's changed since then 🤔 When I get chance I'll have to have another look, see if I can find anything. |
I guess if you'd want to implement it cross-platform, then it'd need to utilize keytab files like apache does with Kerberos. |
So, I've had a crack at trying Kerberos.NET, brought up in #819 by @ittchmh, and using the middleware sample found here. I can get the library loaded, and seemingly validating requests however, for me I only ever seem to use NTLM - it never wants to use Kerberos 🤔 I'm not very well versed in the world of Kerberos, so I'm very more than likely doing something wrong somewhere haha 😂 If anyone has any ideas, or would love to have a crack too (above commit), it'd be more than appreciated 😄 I've setup an example at |
Maybe it's the SPN? There must be an account for the respective service (or for the computer) and for this account there must be a SPN for the destination address. For example for myserver.mydom.net and the AD account myservice the following command must be executed (I have not tested the following and these are not working examples): Setspn -S http/myserver.mydom.net myservice If the service runs under a computer account (Network Service): Setspn -S http/myserver.mydom.net ADComputerAccount https://petri.com/how-to-use-setspn-to-set-active-directory-service-principal-names-2 |
@Badgerati Windows by default tries to use Kerberos, if it fails it falls back to NTLM, so what your seeing is a correct behavior. |
I will look on this soon, thanks
|
Had another shot, didn't realise you had to connect via a valid hostname rather than IP address. This time it negotiated with Kerberos rather than falling back to NTLM 😄 Now facing a crypto error the with keytab, but getting further! |
I want to try Kerberos branch |
Hey @ittchmh, Yep, definitely possible! You'll need the Invoke-Build module, and then you should be able to run |
I wanted to test this branch once and created a buld. Presumably the password for the account under which the process is started (for me 'mydom\podeserviceaccount') must be inserted here:
Furthermore, an SPN for port 8090 and the 'podeserviceaccount' must be set. This did not work at least at first. Did I forget something? |
I have now tried it with a keyfile, as found in the description of kerberos.net. Unfortunately without success. Shouldn't a request for authentication appear in every case? Does the "Kestrel Listener" have to be active? $kf = New-Object Kerberos.NET.Crypto.KeyTable([System.IO.File]::ReadAllBytes("C:\PodeKerberos\sample.keytab")) |
The password for This should work with Pode on its own, no Kestrel needed. The example I was playing with above doesn't use sessions, so it should prompt for auth each time; I was testing using |
Hi! I was able to use To create KeyTab file:
To Authenticate using Kerberos:
To get Working code: Start-PodeServer {
Add-PodeEndpoint -Address * -Port 9090 -Protocol Http
New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging -Levels Debug,Error,Informational,Warning,Verbose
$scheme = New-PodeAuthScheme -Name 'Negotiate' -Custom -ScriptBlock {
$kf = [Kerberos.NET.Crypto.KeyTable]::new([System.IO.File]::ReadAllBytes("D:\Projects\PodeServer\podekerb.keytab"))
$kf | Out-PodeHost
$header = Get-PodeHeader -Name 'Authorization'
$WebEvent.Request.Headers | Out-PodeHost
if ($null -eq $header) {
return @{
Message = 'No Authorization header found'
Code = 401
}
}
$a = [Kerberos.NET.KerberosAuthenticator]::new($kf)
$v = [Kerberos.NET.KerberosValidator]::new($kf)
# $v | GM | Out-PodeHost
$v.ValidateAfterDecrypt = 64
$ticketBytes = [System.Convert]::FromBase64String($header.Split(" ")[1])
$decrypted = $v.Validate($ticketBytes)
"Decrypted ticket Result" | Out-PodeHost
$decrypted.Result | Out-PodeHost
# "Decrypted ticket Ticket" | Out-PodeHost
# $decrypted.Result.Ticket
# "Decrypted ticket SessionKey" | Out-PodeHost
# $decrypted.Result.SessionKey | Out-PodeHost
# "Decrypted ticket AuthorizationData" | Out-PodeHost
# $decrypted.Result.AuthorizationData | Export-Clixml -Path .\decrypted.txt
# $decrypted | Export-Clixml -Path .\decrypted.txt
##
$i = $a.Authenticate($header)
$i.Wait().Result | Out-PodeHost
$principal = [System.Security.Claims.ClaimsPrincipal]::new($i.Result)
$principal | Out-PodeHost
Set-PodeState -Name "claims" -Value $principal
return @($principal)
}
$scheme | Add-PodeAuth -Name 'Login' -Sessionless -ScriptBlock {
param($identity)
$identity | Out-PodeHost
return @{ User = $identity }
}
Add-PodeRoute -Method Get -Path '/' -Authentication Login -ScriptBlock {
Write-PodeJsonResponse -Value @{ result = 'Hello' }
}
} Now as authentication works, Pode server must set Like here Or like Pode on IIS, and IIS set Auth Headers @Badgerati please try to replicate! |
That's very cool. Thank you for making the effort. I will test it again as soon as possible! It is already very good that this is now a successfully tested function with many possibilities for sso :-) |
It works perfectly for me that way too. This also provides the user who submits the ticket. I started the service as "administrator". A delegate for the kerberos user was not necessary. I also did not have to set an SPN. However, small configurations for the browser (Intranet Zone) |
@AndreasNick Pode Host must be added to Intranet Zone for Kerberos Please take a look on this issue as well |
Hey @ittchmh, That's amazing work! I'll look to test it as soon as possible 😄 For the last part, with regards to the headers, you can return custom headers from a scheme/auth in the hashtable returned. For example: $header = Get-PodeHeader -Name 'Authorization'
if ($null -eq $header) {
return @{
Message = 'No Authorization header found'
Code = 401
Headers = @{
'WWW-Authenticate' = 'Negotiate'
}
}
} ^ this will force the And then the below should also let you set a session token as well, plus the return @{
User = $identity
Headers = @{
'Persistent-Auth' = 'true'
'WWW-Authenticate' = "Negotiate $($someToken)"
}
} |
Thanks @Badgerati, |
Hi @ittchmh, I managed to get some quick time to test the above, and can confirm it worked for me 😄. The only difficulty I had was that it would only work in PS6+, but not PS5.1, due to not finding a "System.Buffers" dll. Even the dll the library comes with didn't work in PS5.1, and it seems it could be a well know issue with .NET Framework 😕 Not the end of the world, and since this will be a separate module more than likely, I might have an idea to fix it. I tried to find the session token as well, but with no luck 😂 I did test the headers trick about, and it worked for forcing WWW-Auth and not having a Realm (without having to change core Pode code). |
@Badgerati thanks for update, I will continue working on this on Sunday/Monday |
Hello, |
No, this solution is platform agnostic, meaning it needs a common way to be able to request kerberos tickets and establish a trust with the client that authenticates. What's the issue with the keytab file? |
…en dotnet tries to use local nuget cache
I'm returning back to this again, in hopes of getting it out with v2.11.0 😃 The commits above are in a fresh new branch ( A few notes/changes:
To setup the auth and use via route: New-PodeAuthScheme -Negotiate -KeytabPath '.\user.keytab' | Add-PodeAuth -Name 'Login' -Sessionless -ScriptBlock {
param($identity)
return @{ User = $identity }
}
Add-PodeRoute -Method Get -Path '/' -Authentication Login -ScriptBlock {
Write-PodeJsonResponse -Value @{ result = 'hello' }
} To generate the keytab file will need ktpass -princ HTTP/pode.example.com@EXAMPLE.COM -mapuser EXAMPLE\pode-user -pass Pa$$w0rD -out pode-user.keytab -kvno 0 -crypto all -ptype KRB5_NT_PRINCIPAL -mapop set and if you need to use setspn -A HTTP/pode.example.com EXAMPLE\pode-user I currently do not have the proper means to test this out unfortunately, so I'll require some assistance in doing so. I also want to see if a general To test this will require checking out the |
Hi @Badgerati I will test this on this or next weekends |
Related Issues
#398
Describe the Feature
Pode has support for Basic/Windows LDAP authentication, but is currently missing NTLM auth. Looking at it, it seems very similar to Basic Auth - but with an initial challenge request before the Auth Header.
This will also require the
WWW-Authenticate
header to be implemented on 401s.Additional Context
Useful links:
The text was updated successfully, but these errors were encountered: