Restrict Endpoints by IP address(es)

Is there any way to restrict access to specific endpoints by IP address(s)? This coincides with my other topic about App Token Length, as a potential workaround to my conundrum with a device we need to talk with having a character limit of 256 in the part of its config that allows for custom header entries (such as for the authorization token). If I can restrict access to the endpoint(s) by IP address, I could theoretically disable the requirement for authentication altogether, knowing it’s still not entirely wide open to the world.

1 Like

If there isn’t a way during login there is a variable that is available to routes that holds the remote IP. I believe it’s $RemoteIpAddress.

The policy / role script only includes the claims principal. It would be fantastic to include IP information too so we could do more evaluations.

Funny thing is that we are also looking at something similar, and we were just discussing this yesterday. We are looking at creating some sort of lookup table that Is referenced as soon as the route executes to verify the given ip is allowed on top of the token.

One other option that I haven’t dug into yet but will be testing is to use middleware to do the check. If the check fails it wouldn’t even make it to the route but it looks like it might have a slight impact on performance.

We could do the filtering on the load balancer, but any changes needed (like if we add a new set of devices or need to adjust an existing block - such as if the client gets a new public address space) would require involving another department to make the adjustment, which is more burdensome than we’d like.

In our case, this would be unnecessary if there were a way to shorten the app token length from its current 563 characters to 248 or fewer (to account for the word “Bearer” and the space after it) to fit into a field that limits us to 256 characters.

The tokens are standard jwt tokens, I decoded one yesterday and they have very little in them compared to the jwt tokens we get from our providers like entra ad. A couple basic claims and that’s it. I don’t see the tokens really getting smaller but I obviously can’t say that for sure.

In their current form, sure, but I see no reason why PSU couldn’t also be made to accept Basic authentication, which would mean username:password converted into Base64, or to allow for custom app tokens (such as one made in an external password generator) instead of ones programmatically created within PSU.

It does do basic auth as of a couple of months ago. It’s the forms auth. You have to write the logic yourself in the forms auth script block but we implemented basic and it works really well. Needed it for legacy applications.

1 Like

Nice. So, it seems there’s some documentation inconsistency then. The endpoint documentation page makes no mention of Basic authentication but Security | v4 | PowerShell Universal does. I’ll set that up tomorrow. Thanks.

1 Like
1 Like

I’ve got Basic auth working for the endpoint I needed it on, but I didn’t need to do anything to the Forms authentication.ps1 file to do it. What modifications did you make to yours (the logic you added)? I’m just curious.

Sure…

We use AD authentication when using basic auth…

So I validate credentials against a System.DirectoryServices.AccountManagement.PrincipalContext object. I then use
a System.DirectoryServices.DirectorySearcher to pull a list of all AD groups and then add each of those groups to
the claims of the authenticating user. We use that because the PS AD functions are painfully slow to ramp up…

This is a rough idea of how we are adding claims.

$Authenticated = $DirectoryService.ValidateCredentials(
	($Credential.UserName),
	($Credential.GetNetworkCredential().Password)
)

If ($Authenticated -eq $False) {
	New-PSUAuthenticationResult -ErrorMessage 'Bad username or password'
} else {
	New-PSUAuthenticationResult -UserName "mydomain\$username" -Success -Claims {
		$Groups = System.DirectoryServices.DirectorySearcher....

		Foreach ($Record in $Groups) {
			New-PSUAuthorizationClaim -Type 'groups' -Value $Record -Issuer '<whateveryouwant>'
		}
	}
}

Adding them as groups claims makes it easy for us to auto assign to a role the same that our OIDC auth does.

But the same basic approach would work for any way you store user data. If the user and password match, return the needed claims inside of a New-PSUAuthenticationResult call

1 Like

I see. Thanks. Ours uses SAML2 for the administrative access, and the default Forms authentication had previously only been there during the initial setup and then because it was forced to be enabled as a backdoor in the event the other authentication method(s) broke. Now, of course, it needs to be on for the APIs we need to use Basic auth. with in lieu of another type (such as Bearer).