TYPO3 Neos: authentication provider for a package - typo3

There are many examples to setup an authentication provider with an login, but I can't find an example how to setup one for a package.
TYPO3 Neos v1.2.x
I have a package with an editor for the backend. The editor should communicate via controller. So far all works, but I have no access to the controller now. If I have a look at the TYPO3 Neos package Settings.yaml there is an option controllerObjectName.
Typo3BackendProvider:
provider: 'PersistedUsernamePasswordProvider'
requestPatterns:
controllerObjectName: 'TYPO3\Neos\Controller\.*|TYPO3\Neos\Service\.*|TYPO3\Media\Controller\.*'
entryPoint: 'WebRedirect'
entryPointOptions:
routeValues:
'#package': 'TYPO3.Neos'
'#controller': 'Login'
'#action': 'index'
'#format': 'html'
If I add to this Option my controller too, then it works:
controllerObjectName: 'TYPO3\Neos\Controller\.*|TYPO3\Neos\Service\.*|TYPO3\Media\Controller\.*|Vendor\Package\Controller\Backend\.*'
But I can't imagin, that the answer is to overwrite the Neos settings.
So I tried to add an own provider with the same settings of Typo3BackendProvider.
VendorPackageProvider:
provider: 'PersistedUsernamePasswordProvider'
requestPatterns:
controllerObjectName: 'Vendor\Package\Controller\Backend\.*'
entryPoint: 'WebRedirect'
entryPointOptions:
routeValues:
'#package': 'TYPO3.Neos'
'#controller': 'Login'
'#action': 'index'
'#format': 'html'
Cause this will not work I tried to use the tokenClass and defined it at Typo3BackendProvider and VendorPackageProvider with the same name. Don't works.
The log are also not helpful:
14-12-25 17:52:25 66198 127.0.0.1 INFO Flow Session 52exQd3r1orQA35gTfjQZhhOae4x5SVh contains auth token TYPO3\Flow\Security\Authentication\Token\UsernamePassword for provider VendorPackageProvider. Status: no credentials given
14-12-25 17:52:25 66198 127.0.0.1 INFO Flow Access denied (0 denied, 0 granted, 1 abstained) to method Vendor\Package\Controller\Backend\MyController::indexAction().
14-12-25 17:52:25 66198 127.0.0.1 INFO Flow Redirecting to authentication entry point
routeValues => array (
#package => TYPO3.Neos
#controller => Login
#action => index
#format => html
)
At least my Policy.yaml:
resources:
methods:
Vendor_Package_BackendAccess: 'method(Vendor\Package\Controller\Backend\MyController->(initalize|index)Action())'
acls:
'TYPO3.Neos:Editor':
methods:
Vendor_Package_BackendAccess: GRANT

For anybody else wondering about this in Flow Framework / Neos authentication providers.
It is possible to avoid overwriting the provider set by the main package of Neos and add your own provider, but it is not clean and has serious drawbacks.
The trick is to add another provider with the same name but different uppercase/lowercase. For example here you have Typo3BackendProvider, so you can complement this with typo3backendprovider (all lowercase, but you can change one letter up/down as you like). In this provider entry you set the same providerclass and your requestpattern with a small overlap on the controller for the entrypoint. The second part of the trick is to set the authenticationStrategy to atLeastOneToken.
So in your package's Settings.yaml:
providers:
authenticationStrategy: atLeastOneToken
typo3backendprovider:
provider: 'PersistedUsernamePasswordProvider'
requestPatterns:
controllerObjectName: 'TYPO3\Neos\Controller\LoginController\?.*|Vendor\Package\Controller\Backend\.*'
(Your package must be behind the Neos package in PackageStates.php or composer.json or you must put this in the global Configuration)
Now on login, the Flow authentication framework will find two active authentication providers and authenticate both with the same credentials. And when it is in the Neos backend controllers it will find one authenticated token, and in your backend controllers it will also find one authenticated token. On logout the authenticationmanager will destroy the session with both tokens even if it technically only logged out one token or the other.
This trick has the obvious drawback of being a little vague to someone querying the configuration and seeing two authentication providers that look very much alike. Also on login the hash time is doubled because it is checked twice, so this is not scalable to multiple packages composing their backend spaces together. Finally the atLeastOneToken strategy may lead to unexpected effects of unintentional multifactor authentications if another provider would have taken the authentication before this and carried on.
Better set it global
Given the disadvantages, I would say that overwriting the controllerObjectName of the default provider is not a bad thing to do. It does actually mean that the
Typo3BackendProvider governs the authentication token for that precise area. It should be set in the global Configuration/Settings.yaml and not in the package itself, to avoid problems with multiple packages defining controllerObjectName and leaving only the last one standing. Inside the Packages' settings you could just set it also, so that it would leave the normal backend clearly not working if you forgot the global configuration.

Related

Is there an elegant way to clone a Keycloak realm with all its configurations (clients and roles) for a multitenant application?

I'm building a multitenant application and I'm using Keycloak for authentication and authorization.
Foreach each tenant, the idea is to have a dedicated Keycloak realm. Each tenant will have exactly the same roles and clients.
I have tried to export one existing realm, use it as template and import it for new tenant. Problem: I'm facing database constraint violation due to internal id.
Question: Is there an elegant way to achieve this, having a template to create a new realm ?
Be sure that the feature for uploading script is enabled. For a deployment with a docker-compose just add this:
command: -Dkeycloak.profile.feature.upload_scripts=enabled
Export your realm (the one to be used as model)
Remove all line containing "id:" and "_id:"
Search and replace template realm name by the new realm name
In Keycloak UI admin console, Add new realm, provide the file and that is all.
You can use the cleaned exported file as template.
Can't comment due to rep,
but I'd like to add to #Youssouf Maiga's answer,
that you should also modify any fields that contain values under "authenticationFlowBindingOverrides":
Replace any entries that have values assigned under "direct_grant" or "browser"
i.e
"authenticationFlowBindingOverrides": {
"direct_grant": "f5d1wb45e-27eb-4466-937439-9cc8a615ad65e",
"browser": "5b23141a1c-7af8d-410e-a9b451f-0eec12039c72e9"
},
replaced with
"authenticationFlowBindingOverrides": {},
I tried cloning my realm based on this and got an error saying:
"Unable to resolve auth flow binding override for: direct_grant" when importing the modified realm export.
Keycloak version 16.1.1
What you could do is configure everything using the Keycloak Terraform provider. That way you only have to define the configuration once, in code, and then apply it using Terraform. See for the documentation: https://registry.terraform.io/providers/mrparkers/keycloak/latest/docs
An advantage of this is that you can put your code in an SCM tool (e.g. git), so you can track your changes, and go back to a previous version if necessary.

Securing NodeRED dashboard from unwanted access

I'm trying to create some kind of user authentication to prevent unwanted access to my NodeRED's User Interface. I've searched online and found 2 solutions, that for some reason didn't worked out. Here they are:
Tried to add the httpNodeAuth{user:"user", pass:"password"} key to the bluemix-settings.js but after that my dashboard kept prompting me to type username and password, even after I typed the password defined at pass:"password" field.
Added the user defined Environtment Variables NODE_RED_USERNAME : username and NODE_RED_PASSWORD : password . But nothing has changed.
Those solutions were sugested here: How could I prohibit anonymous access to my NodeRed UI Dashboard on IBM Cloud(Bluemix)?
Thanks for the help, guys!
Here is a little bit of the 'bluemix-settings.js'
autoInstallModules: true,
// Move the admin UI
httpAdminRoot: '/red',
// Serve up the welcome page
httpStatic: path.join(__dirname,"public"),
//GUI password authentication (ALEX)
httpNodeAuth: {user:"admin",pass:"$2y$12$W2VkVHvBTwRyGCEV0oDw7OkajzG3mdV3vKRDkbXMgIjDHw0mcotLC"},
functionGlobalContext: { },
// Configure the logging output
logging: {
As described in the Node-RED docs here, you need to add a section as follows to the settings.js (or in the case of Bluemix/IBM Cloud the bluemix-settings.js file.
...
httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."},
...
The pass files is a bcrypt hash of the password. There are 2 ways listed in the docs about how to generate the hash in the correct way.
if you have a local copy of Node-RED installed you can use the following command:
node-red admin hash-pw
As long as you have a local NodeJS install you can use the following:
node -e "console.log(require('bcryptjs').hashSync(process.argv[1], 8));" your-password-here
You may need to install bcryptjs first with npm install bcryptjs first.

How do I Re-route Ghost Blog Admin URL without modifying the API Address?

Ghost blog platform has a setting that allows you to change the admin panel login location (which starts as: https://whateveryoursiteis.com/ghost). Methodology / docs for changing that setting can be found here: https://ghost.org/docs/config/#admin-url
However — when using the above methodology the API Url that is used for Search etc etc is ALSO modified meaning all requests to the ghost API will also be forwarded to the alternate domain (not just the admin access).
My question is — what is the best way to achieve a redirect of the admin URL to a different Domain / protocol while allowing the API url used by Ghost to remain the same?
More background.
We are running ghost on top of GKE (Google Kubernetes Engine) on a Multi-Region Ingress which allows us to dump our CloudSQL DB down to a SQLite file and then build that database into our production Docker Containers which are then deployed to the different Kubernetes nodes that are fronted by the GCE-Ingress load balancer.
Since we need to rebuild that database / container on content change (not just on code change) we need to have a separate Admin URL backed by Cloud SQL where we can persist / modify our data which then triggers the rebuild on our Ci pipeline via Ghost Webhooks.
Another related question might be:
Is it possible to use standard ghost redirects (created via: https://docs.ghost.org/concepts/redirects/) to redirect the admin panel URL (ie. https://whateveryoursiteis.com/ghost) to a different domain (ie. https://youradminsite.com/ghost)?
Another Related GKE / GCE-Ingress Question:
Is it possible to create 301 redirects natively using Kuberentes GCE-Ingress on GKE without adding an nGinx container etc?
That will be my first attempt after posting this — but I figured either way maybe it helps another ghost platform fan down the line someplace — I will attempt to respond back as I find answers to those questions (assuming someone doesn't beat me to it!).
Regarding your question if it's possible to create 301 redirects without adding a nginx container, I can suggest to use istio, find out more information about traffic routing here.
OK. So as it turns out the Ghost team currently has things setup to point API connections at the Admin URL. So if you change your Admin URL expect your clients to attempt to connect to that URL.
I am going to be raising the potential of splitting these off as a feature request over on the ghost forums (as soon as I get out from under pre-launch hell on the current project).
Here's the official Ghost response:
What is referred as 'official docker image' is not something that we
as a Ghost team support.
The APIs are indeed hosted under the same URL as the admin and that's
by design and not really a bug. Introducing configuration options for
each API Ghost instance hosts would be a feature and should be
discussed at our forum first 👍 I think it's a nice idea to be able to
serve APIs from different host, but it's not something that is within
our priorities at the moment.
In case you need more granular handling of admin site, you could
introduce those on your proxy level and for example, handle requests
that are coming to /ghost/api with a different set of rules.
See the full discussion over here on the TryGhost GitHub:
https://github.com/TryGhost/Ghost/issues/10441#issuecomment-460378033
I haven't looked into what it would take to implement the feature but the suggestion on proxying the request could work... if only I didn't need to run on GKE Multi region (which requires use of GCE-Ingress which doesn't have support for redirection hah!). This would be relatively easy to solve the nGinx ingress.
Hopefully this helps someone — I will update as I work through the process. As of now I solved it by dumping my GCP CloudSQL database down to a SQLite db file during build time (thereby allowing me to keep my admin instance clean and separate from the API endpoint — which for me remains the same URL).

Setting up load-balancer based on authenticated users

I'm trying to set up a loadbalancer that would redirect to specific version of an application certein users. So far i was using Blue/Green deployment strategy (so once i made new version of an app i created new environment and redirected traffic there). Now i would like to change this approach. I want to be able to specify users (more experienced or whatever) that would see new site after authentication while the others would still be redirected to old one. If something goes wrong with new version all users will see old version. Currently my loadbalancing is made in apache and authentication is done on application level. So is this even possible? I know i could hardcode it in application but what if there is a bug in new feature and new users are still being redirected there? I would then need to stop application for all users and rollback to old version and that's bad i guess. I was thinking about using external CAS however didnt find any information if it would be possible then. So i would like to ask is it possible and are there any tools (maybe some apache plugin) for that purpose?
Here's a working solution with nginx
create conf.d/balancer.conf
put the code into it (see below)
docker run -p8080:8080 -v ~/your_path/conf.d:/etc/nginx/conf.d openresty/openresty:alpine
use curl to play with it
balancer.conf:
map $cookie_is_special_user $upstream {
default http://example.com;
~^1$ http://scooterlabs.com/echo;
}
server {
listen 8080;
resolver 8.8.8.8;
location / {
proxy_pass $upstream;
}
}
testing
curl --cookie "is_special_user=1" http://localhost:8080
It would return the contents of scooterlabs.com dumping the request it receives
curl http://localhost:8080
Produces the contents of example.com
explanation
the idea is that you set a special cookie to the users you treat as special by the backend app after they get authorized as usual
of course it would only work if both app versions are served on the same domain so that the cookie is seen by both versions
after that you balance them to a desired server depending on the cookie value
you can easily disable such routing by tweaking your nginx config file
with this approach you can come up with even more complex scenarios like setting random cookie values in the range 1-10 and then gradually switching some of the special users in your config file i.e. start with those having value 1, after that 1-2 etc

AEM Error with ExternalLoginModule

I created author AEM6 on localhost:4504.
When I load any page on the server, I have a lot of the following errors:
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule No IDP found with name cortexCSR. Will not be used for login.
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule No IDP found with name cortex. Will not be used for login.
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule No IDP found with name ldap. Will not be used for login.
Does anyone know how to fix this problem?
It sounds like you may have an instance that is configured for LDAP authentication. Check these URLs to see if that is the case.
Go to http://localhost:4504/system/console/configMgr and search for "ExternalLoginModule" or "org.apache.jackrabbit.oak" and then edit the config to see what is set for any items you find. It sounds like you have an ExternalLoginModuleFactory configured to look for an LDAPIdentityProvider that hasn't been configured. Most likely you need to add the configuration for the providers. See https://docs.adobe.com/docs/en/aem/6-0/administer/security/ldap-config.html for info on how to configure those. It could be that there is an OSGI config file that is runmode specific, so if your localhost isn't running with the same runmode it would not have applied the configuration in that case.
Also see http://abani-behera.blogspot.com/2014/07/ldap-integration-with-aem6-osgi-config.html for more details.