= Setting up with Shiro

:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
:page-partial:

This section describes how to set up and configure SecMan as an xref:refguide:core:index/security/authorization/Authorizor.adoc[], with framework's xref:security:shiro:about.adoc[Shiro integration] being used as the xref:refguide:core:index/security/authentication/Authenticator.adoc[].

The primary use case this enables is for authentication to be performed through an external mechanism, for example LDAP.
This is implemented through the SecMan's shiro realm submodule, which provides an implementation of Apache Shiro's `Realm` interface that then calls back into SecMan.

== Local Authentication

The diagram below sketches the high-level architecture:

.SecMan with Shiro local authentication
image:secman-shiro-architecture.drawio.svg[]

Thus:

* Apache Causeway' xref:security:shiro:about.adoc[Shiro security] integration sets up Shiro web filters to intercept every http request, as well as the xref:refguide:security:index/shiro/authentication/AuthenticatorShiro.adoc[AuthenticatorShiro] implementation.
* The `AuthenticatorShiro` calls to the Shiro Security Manager to obtain the authenticated principal.
* The Shiro Security Manager uses the `shiro.ini` configuration file to look up the realm to perform the authentication; in this case we configure it to use Secman's realm (xref:refguide:extensions:index/secman/delegated/shiro/realm/CausewayModuleExtSecmanShiroRealm.adoc[CausewayModuleExtSecmanShiroRealm]).
* Secman's realm implementation queries the database and uses this to create an instance of `PrincipalForApplicationUser`, where the `Principal` interface is Shiro's representation of an authenticated user.
The `PrincipalForApplicationUser` is backed by xref:refguide:extensions:index/secman/applib/user/dom/ApplicationUser.adoc[ApplicationUser], which all of the permissions to object members for this particular user.
* to render a page, the Apache Causeway viewer uses configured `Authorizor`, in this case
Secman's own xref:refguide:extensions:index/secman/integration/authorizor/AuthorizorSecman.adoc[AuthorizorSecman].
This looks up the current xref:refguide:extensions:index/secman/applib/user/dom/ApplicationUser.adoc[ApplicationUser] (which will already reside in-memory) and renders the page according to which object members are visible or not.


The above configuration allows Secman to be used to authenticate users; the password is stored as an (typically) encrypted property of the xref:refguide:extensions:index/secman/applib/user/dom/ApplicationUser.adoc[ApplicationUser].
These are called "local" users, as per the xref:refguide:extensions:index/secman/applib/user/dom/ApplicationUser.adoc[ApplicationUser]'s `accountType` property.


== Delegate Authentication

Local authentication - as described in the previous section - does not actually accomplish much; although Shiro's `Authenticator` implementation is in use, since the Shiro Realm just queries the SecMan database, there is no real difference from simply using SecMan's own `Authenticator` implementation.

Where things become more interesting and useful is that Secman's xref:refguide:extensions:index/secman/delegated/shiro/realm/CausewayModuleExtSecmanShiroRealm.adoc[Realm implementation] also allows an alternative "delegate" realm (eg LDAP) to be queried.
In such cases Shiro can obtain authentication of "delegated" users is performed by the delegate realm rather than locally.

The diagram below shows where this delegation occurs:

.SecMan with Shiro delegate authentication
image:secman-shiro-delegate-architecture.drawio.svg[]

When a delegate realm is configured, an `ApplicationUser` entity can be automatically created in the SecMan database for an external user.
Secman can be configured so that these users are either locked or unlocked by default, as required, see xref:#configure-properties[below].


== Dependencies

In addition to the xref:setting-up.adoc#dependencies[regular dependencies] required by Secman, also add in Secman's Shiro Realm implementation:


[source,xml]
.pom.xml
----
<dependencies>
    <dependency>
        <groupId>org.apache.causeway.extensions</groupId>
        <artifactId>causeway-extensions-secman-persistence-XXX</artifactId> <!--.-->
    </dependency>
    <dependency>
        <groupId>org.apache.causeway.extensions</groupId>
        <artifactId>causeway-extensions-secman-encryption-jbcrypt</artifactId> <!--.-->
    </dependency>
    <dependency>
        <groupId>org.apache.causeway.extensions</groupId>
        <artifactId>causeway-extensions-secman-delegated-shiro</artifactId>
    </dependency>
</dependencies>
----
<.> specify either `causeway-extensions-secman-persistence-jpa` or `causeway-extensions-secman-persistence-jdo`, as required
<.> provides an implementation of `PasswordEncryptionService`




[[_update-appmanifest]]
== Update AppManifest

In addition to the xref:setting-up.adoc#_update-appmanifest[other modules] that Secman requires to be added to your  application's `AppManifest`, also add:
You will also need to import the fixture module; SecMan uses fixture scripts to seed its entities:

[source,java]
.AppManifest.java
----
@Configuration
@Import({
        ...
        CausewayModuleExtSecmanRealmShiro.class,    // <.>
        ...
})
public class AppManifest {
}
----

<.> enables Shiro integration (so that Shiro delegates to Secman for authentication).
+
This brings in a transitive dependency on the `CausewayModuleSecurityShiro` module.

Ensure that no other `CausewayModuleSecurityXxx` module is imported into the AppManifest.




[#delegate-realms]
== Shiro (Delegate) Realm

SecMan's Shiro realm is configured using the `shiro.ini` file.
The following sets up Shiro _without_ delegation:

[source,ini]
.shiro.ini
----
[main]

authenticationStrategy=org.apache.causeway.extensions.secman.delegated.shiro.realm.AuthenticationStrategyForSecMan
causewayModuleSecurityRealm=org.apache.causeway.extensions.secman.delegated.shiro.realm.CausewayModuleExtSecmanShiroRealm

securityManager.authenticator.authenticationStrategy = $authenticationStrategy
securityManager.realms = $causewayModuleSecurityRealm

[users]
[roles]
----

The `[users]` and `[roles]` sections are required but are unused.

The main point of introducing Shiro though is to introduce support for authentication by external mechanisms such as LDAP.
In this case we configure Shiro to use the external realm as the primary realm, with Secman's Shiro realm set up as a "delegate" realm.
We specify the delegate realm implementation in the `shiro.ini` file, and "inject" it into the Secman realm.

For example, to use Shiro's link:https://github.com/apache/shiro/blob/main/core/src/main/java/org/apache/shiro/realm/ldap/DefaultLdapRealm.java[LDAP Realm] as a delegate:

[source,ini]
.shiro.ini
----
[main]

...
contextFactory = org.apache.shiro.realm.ldap.JndiLdapContextFactory #<.>
contextFactory.url = ldap://localhost:10389                         #<.>
contextFactory.systemUsername = uid=admin,ou=system
contextFactory.systemPassword = secret
contextFactory.authenticationMechanism = CRAM-MD5

ldapRealm = org.apache.shiro.realm.ldap.DefaultLdapRealm            #<.>
ldapRealm.contextFactory = $contextFactory

causewayModuleSecurityRealm.delegateAuthenticationRealm=$ldapRealm  #<.>

...
----
<.> instantiate a JNDI LDAP context ...
<.> \... configured with credentials to query users
<.> instantiate the LDAP realm
<.> specify the LDAP realm as the delegate realm for SecMan's own realm.

The users should then be defined in the LDAP server appropriately.
For example, if using link:https://directory.apache.org/apacheds[ApacheDS] server:

* the users are stored under the SASL `searchBaseDn` attribute
+
for ApacheDS 1.5.7 this can be found in the `server.xml` file):

* and can be defined as an `inetOrgPerson` with the `uid` and `userPassword` defining the credentials:
+
image::060-create-inetOrgPerson.png[width=600]

With this configuration, the user/password is defined in LDAP, while their users permissions are taken from their user/group/perms defined in SecMan.

=== A simpler LDAP configuration

In fact, it's also possible to simplify matters by just configuring Shiro to use LDAP realm, and not define a secman realm at all.

For example:

[source,ini]
.shiro.ini
----
[main]

contextFactory = org.apache.shiro.realm.ldap.JndiLdapContextFactory
contextFactory.url = ldap://localhost:10389
contextFactory.systemUsername = uid=admin,ou=system
contextFactory.systemPassword = secret
contextFactory.authenticationMechanism = CRAM-MD5

ldapRealm = org.apache.shiro.realm.ldap.DefaultLdapRealm

ldapRealm.contextFactory = $contextFactory

securityManager.realms = $ldapRealm
----

Although simpler, the key difference with this approach is that will not auto-create ``ApplicationUser``s within secman; they must be created by some separate means.
If there is an entry in LDAP, but none in secman, then the end-user will be able to "login" but will have access to no features.

[#configure-properties]
== Configuration Properties

As mentioned in the introduction, if delegate authentication has been set up, this means that authentication may pass for a user that Secman knows nothing about.
In this case Secman will automatically create an `ApplicationUser` for this externally delegated authenticated user, with the type set to "DELEGATED".

We can configure whether such automatically created accounts should be unlocked or locked by default:

[source,yaml]
.application.yml
----
causeway:
  extensions:
    secman:
      delegated-users:
        auto-create-policy: AUTO_CREATE_AS_LOCKED
----


