Symfony authentication across two applications - symfony

I have two apps with distinct install directories and a shared SESSION table (in mysql).
I have multiple authenticators setup on the 'main' app and I can login just fine. When I navigate over to a second app (same domain, different port), Symfony is loading the user from the session and choking somewhere.
I've installed symfony security bundle (in both apps), but made the user and provider non-doctrine in the 2nd.
I am getting this series of exceptions:
Full authentication is required to access this resource.
Symfony\Component\HttpKernel\Exception\
HttpException
Symfony\Component\Security\Core\Exception\
InsufficientAuthenticationException
Full authentication is required to access this resource.
Symfony\Component\Security\Core\Exception\
AccessDeniedException
Access Denied.
https://symfony.com/doc/current/security/user_provider.html#understanding-how-users-are-refreshed-from-the-session
Suggests that as long as my User object in the second app is identical to the main app - I should be good - alternatively I could implement User::isEqualTo() - which I've done.
It's not even being called, so something way before this is halting my code...
Any thoughts? What have I misconfigured?

Related

Login fails for user '' -- using an ASP.NET SqlDataSource in Azure using a managed identity

I'm working on an old webpage which the client is trying to migrate to Azure. The app has worked forever, so it's not a question of "maybe the code is broken". Instead, it's the migration to Azure that's been throwing up issues. The differences between a localhost build and the Azure build are significant, since I don't have a Managed Identity local. But the differences are primarily configuration, other than bits of code to add an Access Token to SQL connections.
The app uses dozens of asp:SqlDataSource objects defined in .aspx pages to do all sorts of work. But that's fine, they use a standard connection string, pulled from the web.config, to talk to the database:
<add name="MyConnectionString"
connectionString="Server=tcp:MyDatabaseServer.database.windows.net,1433;
Initial Catalog=MyDatabaseName;
Persist Security; Info=False; MultipleActiveResultSets=False;
Encrypt=True; TrustServerCertificate=False;
Connection Timeout=30" providerName="System.Data.SqlClient"/>
For security reasons, the client now has to use a Managed Identity to talk to the database, rather than our previous service account model.
I added an OnSelecting event to the SqlDataSource where I set an access token on the connection. I'm not getting any exceptions or complaints about that code, so either it's running fine or it's not running at all. The managed identity is created, and it has reader, writer, and executor roles on the database, but this bit of code is the first time that the managed identity is being put through its paces.
What I get is an error
[SqlException (0x80131904): Login failed for user ''.]
Is there some other permissions or flags I need to set on the managed identity, or some missing configuration? Should I be using a different event than the OnSelecting event? Is the URL for an access token different in this situation? Is there a place to find more detailed error logs?
First note that I haven't seen any possible way to use SQL-based session state with a managed identity. Switch your Session storage to InProc and see if your login problem goes away.
Second, I've found that making a web request to 169.254.169.254 to obtain a token doesn't work in a sovereign Azure environment. Instead, do this:
var credential = new Azure.Identity.DefaultAzureCredential();
var token = credential.GetToken(new Azure.Core.TokenRequestContext(new[] { "https://database.windows.net/.default" }));
connection.AccessToken = token.Token;
Using the OnSelecting event to assign the access token to the connection will work fine for a SqlDataSource. Instead of creating credentials and getting a token every time a stored procedure is called, store the token in the app and just re-use it; and make sure to purge the token when the user logs out.

Does ActiveMQ Artemis automatically reload LDAP-based Security Settings?

I've read about the automatic configuration reload which - according to the docs - also includes security settings. What I could not figure out yet (and did not see any indications for ) is if Artemis also updates Roles etc. when the LDAP auth is active.
Question is: In an ActiveMQ Artemis deployment where OpenLDAP is used for authentication and authorization do I need to take care about updating the roles etc. myself or is this done automatically?
The documentation you cited is related to reloading broker.xml when a change is detected. It isn't really applicable to the LDAP authorization data since that data is in LDAP and not in broker.xml. However, the documentation for the LegacyLDAPSecuritySettingsPlugin is relevant as it discusses the enableListener option:
enableListener. Whether or not to enable a listener that will automatically receive updates made in the LDAP server and update the broker's authorization configuration in real-time. The default value is true.
Since enableListener defaults to true then changes made to your LDAP authorization data should automatically be reflected in the broker.
The listener is an implementation of both javax.naming.event.NamespaceChangeListener and javax.naming.event.ObjectChangeListener and is registered using the javax.naming.event.EventDirContext#addNamingListener(java.lang.String, java.lang.String, javax.naming.directory.SearchControls, javax.naming.event.NamingListener) method.
That said, you may run into ARTEMIS-2671 which will be resolved in the next release (i.e. 2.12.0). It's also possible that your particular LDAP server doesn't actually support this listener functionality. If that's the case then restarting the broker is your only option to reload the LDAP data. Modifying broker.xml won't reload it.

What are valid values for framework.session.storage_id?

In the Symfony configuration there is an entry framework.session.storage_id. This setting also appears in the default config on the Symfony configuration documentation but it is not explained. My assumption is that it defines where session data is stored on the server side.
Values I have seen for this entry include session.storage.mock_file, session.storage.native and session.storage.filesystem. I am unsure of what these values exactly mean (e.g. what is the difference between a mock file and a filesystem?) and also think that this is not the complete list of possible values.
So what exactly does this configuration key control and what values are valid?
Valid values for framework.session.storage_id are following:
session.storage.mock_file - for testing. It doesn't start session at all.
session.storage.filesystem - for testing. It is an alias for session.storage.mock_file.
session.storage.native - default implementation using defined session handler
session.storage.php_bridge - for legacy apps
From developer perspective, there is a session service that abstracts working with session. session service depends on some session storage service. Session storage implements session management from PHP perspective (calling session_start() function for example). Storage also depends on some session handler. Handler is implementation of \SessionStorage and it tells how and where will be session physically stored.
This three layer design allows creating storage for testing which does not call session_start() at all and does not use handler (session.storage.mock_file). Or creating of handler that can store and load session from anywhere (session.storage.native). session.storage.php_bridge solves situation when session_start() is called by external PHP code (not by Symfony session storage).
I hope it is clear to understand.
Session management in Symfony is based on two main rules.
Symfony must start the session.
The Symfony sessions are designed to replace the use of PHP native functions session_*() and $_SESSION global.
However, some exceptions exist. Sometimes it may be necessary to integrate Symfony in a legacy application, which starts the session with session_start().
With session.storage.php_bridge directive, you can manage the session using a special gateway that is designed to allow to Symfony working with a session that was started outside the framework.
In goal to make the code using sessions testable, session.storage.mock_file directive allows to simulate the flow of a PHP session without starting it really.

ASP.NET Impersonation by Role

I modified the ASP.NET login control to also allow specifying UserRole ('Employee' or 'Volunteer'). Users are authenticated via a call to a webservice written by our client, which accepts username/password/role and returns true or false.
If role is 'Employee' it represents an active directory user. The application should impersonate the user with the given username/password.
If role is 'Volunteer' the application should run under a set Windows account whose username/password are known in advance (i.e. hard-coded in web.config file).
The server runs on Windows Server 2003. I am confused by the myriad of configuration choices and trying to understand my options;
Is it possible to have multiple scenarios as described?
Should I specify the impersonation programmatically or can it be done through the config file? If so, is it required to use LogonUser or WindowsIdentity?
What config file setup should I use? (i.e. Forms authentication, impersonate=true, etc..)
Thank you in advance.
Because the decision about which identity to impersonate is based on run-time data, you'll likely have to deal with impersonation programmatically.
I use a combination of interop and WindowsIdentity to handle impersonation. The steps I follow are:
Log on using the interop LogonUserA(), which fills a handle to an IntPtr (token).
Duplicate the token with the interop DuplicateToken().
Create a new windows identity, a la: var identity = new WindowsIdentity(tokenDuplicate);.
Create an impersonation context via: var context = identity.Impersonate();
Close both tokens with the interop CloseHandle()
When finished impersonating, undo the impersonation context via: context.Undo();
I keep a disposable class around to handle the details. Steps 1-5 occur in a constructor, and step 6 occurs in the dispose routine. This helps ensure that I properly revert even in the face of an exception.
With this approach, since you are passing credentials via a service method, the web.config authentication scheme is not entirely forced. If, however, you are using integrated Windows auth, you could programmatically impersonate the current user from HttpContext.Current.User.Identity.Impersonate(), without passing credentials in a service method.
On an aside, and you may already know, PInvoke.net is a valuable resource for configuring signatures for interop methods.

Can't run Windows service from ASP.NET page?

I'm trying to start a Windows service on Windows Server 2003
from an ASP.NET page:
the code of line 35 is:
32. Dim controller As New ServiceController
33. controller.MachineName = System.Environment.MachineName
34. controller.ServiceName = "WindowsServiceRealName"
35. controller.Start()
The error code is
System.InvalidOperationException: Cannot open WindowsServiceRealName service on computer 'DARWIN'. ---> System.ComponentModel.Win32Exception: Access is denied --- End of inner exception stack trace --- at System.ServiceProcess.ServiceController.GetServiceHandle(Int32 desiredAccess) at System.ServiceProcess.ServiceController.Start(String[] args) at System.ServiceProcess.ServiceController.Start() at AfconParking.Import.StartService() in E:\ProjectsNet\AfconParking\AfconParking\system\Import.aspx.vb:line 35
The account used for the identity of your ASP.NET application pool ("Network Service" by default) does not have the permissions required to start a service.
To fix this issue, you have a few options:
Re-architect your site to not require interactions between ASP.NET pages and the service control manager. I really can't think of a good reason to require this (the service can simply be started at boot time, and remain running: if the service crashes, you should fix the cause of that, and/or use the corrective actions provided by the SCM. If a service restart is needed to kick of some kind of processing, use an IPC mechanism, such as sockets or named pipes, to communicate between your web app and the service instead).
Create a service account with the appropriate permissions (basically, membership of the local Administrators group) as described in detail here. Do note that this has several security implications, none of them particularly good.
Its a permissions issue, try to run the application pool with an Identity that has permissions to perform service control operations.
Read this kb to find out how to grant user such a permissions:
http://support.microsoft.com/kb/325349
Services have Access Control Lists (like files etc.). By default most normal and restricted user accounts (including the default account used by ASP.NET workers) do not have permissions to control or see the status any services.
You can either set an ACL on the service that allows the IIS worker to control the service, or run the web application with an account that already has rights.
The latter option would probably give the web application a dangerous level of access (e.g. what would happen if a web user found a security vulnerability), but is a quick approach to confirming that it is a service access permission.
Setting an ACL is the better solution, but I don't think there is a UI to set the ACL (except in group policy) which makes things harder. You'll need to use the command line tools (e.g. SUBINACL.exe)

Resources