Is there a way to get a non-null Principal/Authentication using Spring Security with anonymous access? - authentication

I'm using Spring Security, and want to be able to run with a "local" profile with security off. I can do this by using a profile-controlled WebSecurityConfigurerAdapter which allows anonymous access, but the problem is that any Principal or Authentication arguments to controller methods are null.
The way I've solved this before is by passing the arguments through an adapter, which has a non-local pass-through implementation and a "local"-profile implementation that substitutes a configured value:
#GetMapping()
public ResponseEntity<List<Thing>> getThings(Principal principal) {
Principal myPrincipal = securityAdapter.principal(principal);
...
}
But this feels really clunky. Is there some way to configure Spring Security to make the substitution so that I can keep the code clean?

Unfortunately it is a SpringSecurity feature: the AnonymousAuthenticationToken is not injected in controller methods. I could find some references for that in this issue.
A possible workaround (from above issue) is to inject a custom trust resolver that pretends that the AnonymousAuthenticationToken is not anonymous...
#Bean
public AuthenticationTrustResolver trustResolver() {
return new AuthenticationTrustResolver() {
#Override
public boolean isRememberMe(final Authentication authentication) {
return false;
}
#Override
public boolean isAnonymous(final Authentication authentication) {
return false;
}
};
}
Rather ugly, but as it is intended to run in a profile where anonymous authentication is expected to be valid, it could be enough.

Related

Resharp DI and DNS resolution

I'm upgrading to version 107 restsharp and i'm wondering if both these options below are ok ways of doing dependency injection in dotnet with restsharp.
The documents say don't create a new restsharp for every request (connection pool exhaustion resaons) but if the httpclient is injected via the constructor will I be get the benefit of DNS resolution changes even though rest client is contained in transient scoped object (i think that's what AddHttpClient will do). I know there will be some price to pay for creating a transient object, but for a general purpose business app maybe that's fine?
Recommended way as described in the documentation
services.AddSingleton<IMyClient, MyClient>();
public class MyClient : IMyClient
{
protected readonly RestClient _restClient;
public MyClient()
{
_restClient = new RestClient();
}
}
OR: is it ok to do this?
services.AddHttpClient<IMyClient, MyClient>();
public class MyClient : IMyClient
{
protected readonly RestClient _restClient;
public MyClient(HttpClient httpClient)
{
_restClient = new RestClient(httpClient);
}
}
You should AddSingleton, not AddHttpClient as per official documentation:
https://restsharp.dev/v107/#restclient-lifecycle
If you use a dependency-injection container, register your API client as a singleton.
I believe it's becouse RestClient is managing the connection pools and addressing known issues, that AddHttpClient would typically address.
If you would use HttpClient directly, you should follow Microsofts recommendations from below URL, where you have a choice of Singleton or AddHttpClient:
https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines#recommended-use
Also, not sure how your 2nd option works at this point.
Also, great video explaining more about what AddHttpClient does (sets HttpClient as Transient etc):
https://www.youtube.com/watch?v=Z6Y2adsMnAA&t=335s

Is there any way to avoid challenging all registered authentication schemes when one of them succeeds?

I am facing an issue related to handling multiple authentication schemes in an asp.net core application which exposes API.
In particular, I am attempting to make two different authentication modes available, by registering two schemes, each with its own handler.
At the moment my configuration code (simplified) looks like this:
public class Startup {
public void ConfigureServices(IServiceCollection services) {
services
.AddAuthentication()
.AddScheme<AuthenticationSchemeOptions, BasicAuthHandler>("Basic", o => {});
.AddScheme<AuthenticationSchemeOptions, ApiKeyAuthHandler>("ApiKey", o => {});
services.AddAuthorization(o => {
o.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("Basic", "ApiKey").Build();
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
...
app.UseAuthentication();
app.UseAuthorization();
...
}
}
public class BasicAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions> {
protected override async Task<AuthenticateResult> HandleAuthenticateAsync() {
Console.WriteLine("Challenging Basic Authentication");
if( ... ) {
return AuthenticateResult.Success(...);
}
return AuthenticateResult.Fail(...);
}
}
public class ApiKeyAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions> {
protected override async Task<AuthenticateResult> HandleAuthenticateAsync() {
Console.WriteLine("Challenging ApiKey Authentication");
if( ... ) {
return AuthenticateResult.Success(...);
}
return AuthenticateResult.Fail(...);
}
}
The ApiKeyAuthHandler authenticates requests depending on a custom header (say X-ApiKey) value, the BasicAuthHandler authenticates requests depending on credentials provided through Authorization: Basic BASE_ENCODED_USERNAME_AND_PASSWORD header.
Both handlers work fine: I can provide Authorization header with basic auth credentials and I can provide an api-key through the custom header.
Generally speaking, the two registered handlers are executed sequentially, in the same order I've registered them. So far, so good.
However, when I provide both basic credentials in Authorization header and api-key through X-ApiKey header, I noticed that
the first handler (BasicAuthHandler) is executed, returning AuthenticateResult.Success
the second handler (ApiKeyAuthHandler) is executed, even the first already authenticated the request successfylly, also returning AuthenticateResult.Success
the identity finally available in my controller is the one built by the second handler
I'm wondering why the second handler is executed after the first completed authentication successfully: I googled about this but can't found any configuration flags to enable a sort of short-circuit after the first success result.
The reason seems to be this foreach statement that iterates over all available authentication schemes regardless of theirs results.
Does anyone have any idea of a way to challenge available authentication scheme while no one is successful, stopping when the first succeeds?
No doubt I could implement a CompositeAuthHandler in order to manage this requirement, but I would prefer an already-made, official solution to my problem.
A note about the context which justifies the requirement of short-circuit handler evaluation: the example provided above is simplified and uses two very cheap authentication handlers, but the real case I'm facing off involves at least one very slow handler, that perform paid calls to an external system - so I would like to avoid calling it for requests already authenticated by former handlers.

Is there a way to specify which IAuthProvider to use for authentication on a particular Service class?

I have two services within the same project:
[Authenticate]
public class OnlyDoesBasicAuth : Service
{
}
[Authenticate]
public class OnlyDoesJwtAuth : Service
{
}
//AppHost
public override void Configure(Container container)
{
Plugins.Add(new AuthFeature(
() => new AuthUserSession(),
new IAuthProvider[]
{
new BasicAuthProvider(AppSettings),
new JwtAuthProvider(AppSettings)
}
)
{
HtmlRedirect = null
});
}
The way this is set up, I can get into both services using Basic Authentication or with a valid Bearer token. I'd prefer to have it so that only one service can do one means of authentication. Is there a way to specify with provider to use on authentication?
I'm at a loss on how to approach this. I was thinking that maybe there was a way via global request filter or something to that effect, but maybe that's not the way to go. I could split the project into two projects, which will definitely work, but it's not the way I want to approach it.
I'm just looking for a way for the OnlyDoesBasicAuth to only use the BasicAuthProvider on authentication and OnlyDoesJwtAuth to only use the JwtAuthProvider within the same project. Any and all suggestions will be greatly appreciated.
Thanks in advance.
Typically once you're authenticated using any of the Auth Providers you're considered as an Authenticated User everywhere in ServiceStack.
You can restrict access so that a Service needs to be Authenticated with by specifying the AuthProvider name in the [Authenticate] attribute, e.g:
[Authenticate(BasicAuthProvider.Name)]
public class OnlyDoesBasicAuth : Service
{
}
[Authenticate(JwtAuthProvider.Name)]
public class OnlyDoesJwtAuth : Service
{
}
Alternatively you can validate within your Service that they need to be authenticated with a specific Auth Provider, e.g:
if (SessionAs<AuthUserSession>().AuthProvider != JwtAuthProvider.Name)
throw HttpError.Forbidden("JWT Required");

Symfony: Why some user checks should be performed after authentication?

I don't get this. UserCheckerInterface has two methods: checkPreAuth and checkPostAuth. Now let's look at their implementation in the class UserChecker:
class UserChecker implements UserCheckerInterface
{
/**
* {#inheritdoc}
*/
public function checkPreAuth(UserInterface $user)
{
if (!$user instanceof AdvancedUserInterface) {
return;
}
if (!$user->isAccountNonLocked()) {
$ex = new LockedException('User account is locked.');
$ex->setUser($user);
throw $ex;
}
if (!$user->isEnabled()) {
$ex = new DisabledException('User account is disabled.');
$ex->setUser($user);
throw $ex;
}
if (!$user->isAccountNonExpired()) {
$ex = new AccountExpiredException('User account has expired.');
$ex->setUser($user);
throw $ex;
}
}
/**
* {#inheritdoc}
*/
public function checkPostAuth(UserInterface $user)
{
if (!$user instanceof AdvancedUserInterface) {
return;
}
if (!$user->isCredentialsNonExpired()) {
$ex = new CredentialsExpiredException('User credentials have expired.');
$ex->setUser($user);
throw $ex;
}
}
}
Why should isCredentialsNonExpired() be done AFTER authentication? Shouldn't we just not allow the user with expired credentials to authenticate? And bonus question: Where should we really do this "post authentication" check? After setting the authentication token?
I believe the reason the methods are split is because when using session based authentication there are some things you don't want to check every time.
When using sessions, Symfony will serialize the token (and related user). When the next request comes in the PreAuthenticatedToken will contain the credentials you need for authorization.
Some examples of pre-authenticated tokens are: (stolen from docs)
authentication based on a "remember me" cookie.
authentication based on your session.
authentication using a HTTP basic or HTTP digest header
To improve performance if you have a token stored in the session you can remove some checks. The only example I have of the UserCheckerInterface is the one provided by Symfony. As you've seen, validation of the user's account is done inside preAuth and postAuth only checks if the credentials have expired.
In actual case looking at services that use these methods you can see that there isn't much distinction. The GuardAuthenticationProvider calls both sequentially.
Symfony's PreAuthenticatedAuthenticationProvider only calls postAuth so perhaps someone in Symfony decided that for session based authentication to shave a few milliseconds off the response time they could separate authentication checks that need to be done on first authentication from those that need to be done on every request.
In your case if you're creating a custom UserChecker I think you can decide from yourself if you need to use both. Find out if you have other bundles that have authentication providers calling either of these methods. Find all the places where they are called and you might find that you only need to implement one, or, if you have a lot of complex authentication logic, split it.

TPL Task in WCF service fails to use correct IIS security Credentials (SQL Connection)

I have a WCF service method that calls a SQL stored proc. I'm developing using IIS 5 (can't do much about that, II6/7 not available)
To get some gains, I'm doing a number of async calls to this stored proc by putting the call into a c# TPL Task.
When run as a Task, I'm getting an SQL Exception...
"Login failed. The login is from an untrusted domain and cannot be used with Windows authentication"
However, If I run the exact same process without using a Task, I have no problems with SQL connection
It would appear to me that the credentials for the IIS Virtual folder (WCF) are not being delegated to the Task? Any ideas how I can specificy credentials for the TPL Task thread, ie to use the same as the parent etc ?
I am using Windows Authentication (sspi), and impersonation to be able to connect to the seperate SQL box.
Your help appreciated.
You have two choices.
1) Opt your entire application into always flowing the identity using:
<runtime>
<alwaysFlowImpersonationPolicy enabled="true"/>
</runtime>
This has a side effect of overhead and the danger of accidentally executing some unintended code with the priviledges of the currently calling user rather than the application identity. I would personally avoid this and go with #2 where you explicitly opt-in.
2) Capture the WindowsIdentity before setting up your TPL tasks and explicitly impersonate where you need to make the calls using Impersonate + WindowsImpersonationContext:
public void SomeWCFOperation()
{
WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
Task.Factory.StartNew(() =>
{
// some unpriviledged code here
using(WindowsImpersonationContext impersonationContext = currentIdentity.Impersonate())
{
// this code will execute with the priviledges of the caller
}
// some more unpriviledged code here
});
}
As another workaround, you can create extensions to the TPL as follows:
public static class TaskFactoryExtensions
{
public static Task StartNewImpersonated(this TaskFactory taskFactory, Action action)
{
var identity = WindowsIdentity.GetCurrent();
return taskFactory.StartNew(() =>
{
using (identity.Impersonate())
{
action();
}
});
}
public static Task<TResult> StartNewImpersonated<TResult>(this TaskFactory taskFactory, Func<TResult> function)
{
var identity = WindowsIdentity.GetCurrent();
return taskFactory.StartNew<TResult>(() =>
{
using (identity.Impersonate())
{
return function();
}
});
}
}
You would then call these new methods in place of the standard StartNew methods.
The downside to this is that there are a lot of methods to override.