You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by bu...@apache.org on 2017/05/07 17:39:50 UTC

svn commit: r1011800 - in /websites/staging/directory/trunk/content: ./ fortress/testimonials.html

Author: buildbot
Date: Sun May  7 17:39:50 2017
New Revision: 1011800

Log:
Staging update by buildbot for directory

Modified:
    websites/staging/directory/trunk/content/   (props changed)
    websites/staging/directory/trunk/content/fortress/testimonials.html

Propchange: websites/staging/directory/trunk/content/
------------------------------------------------------------------------------
--- cms:source-revision (original)
+++ cms:source-revision Sun May  7 17:39:50 2017
@@ -1 +1 @@
-1794226
+1794231

Modified: websites/staging/directory/trunk/content/fortress/testimonials.html
==============================================================================
--- websites/staging/directory/trunk/content/fortress/testimonials.html (original)
+++ websites/staging/directory/trunk/content/fortress/testimonials.html Sun May  7 17:39:50 2017
@@ -169,7 +169,364 @@
 }
 h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
 <h1 id="testimonials">Testimonials<a class="headerlink" href="#testimonials" title="Permanent link">&para;</a></h1>
-<p>insert here....</p>
+<h2 id="contributed-by-yudhi-karunia-surtan-for-pt-global-digital-niaga-bliblicom">Contributed by Yudhi Karunia Surtan for PT. Global Digital Niaga (blibli.com).<a class="headerlink" href="#contributed-by-yudhi-karunia-surtan-for-pt-global-digital-niaga-bliblicom" title="Permanent link">&para;</a></h2>
+<p>This document contains an overview of the URL filtering mechanism.</p>
+<p>I created this solution because at the time I was looking an IAM and SSO solution, and there were no open source solution to provide everything that I required.</p>
+<p>Basically, the idea is, I wanted to have a framework where the developer doesn't need to programmatically make authorization calls, use annotation or any other kind of “if condition” statements, in their code. With this solution, I'm can have a declarative mechanism capable of dynamic authorization decisions, even if the user hasn't been logged in or has the the proper role activated.  This is because the authorization has been centralized at the server and that server can activate and deactivate user roles that are needed to access the runtime environment.</p>
+<p>I searched for all available open source solutions and finally decided to use Apereo CAS and Apache Fortress as the combined solution. Apereo CAS does the authentication and Apache Fortress will handle the authorization.</p>
+<p>Apereo CAS is very good way to handle the Single Sign-On and Single Sign-Out problems, on the other hand Apereo CAS lacks authorization capaibilities because there are no standardized solutions for the authorization in that space yet. Apache Fortress is good at authorization because it uses standard RBAC. However, Apache Fortress doesn't have an SSO solution yet. That is why I think both can be combined and create a good solution because they complement each other.  Unfortunately, there isn't a good documentation resource available to combine both solution into wone which is why I needed to create this to other developers on my team and make their life easier.</p>
+<p>With this solution, I have successfully run inside a production environment since 2015 and have maintained this solution for almost 2 years now, I write this documentation to describe how it works and how you can try something like this as well.</p>
+<p>Here are the technologies stack used within my extended framework:</p>
+<ul>
+<li>Apereo CAS -&gt; 4.2.x</li>
+<li>Apache Fortress Enmasse (rest) -&gt; 1.0.0</li>
+<li>Apache Fortress Proxy -&gt; 1.0.0</li>
+<li>Apache Ignite -&gt; 1.7.0</li>
+<li>Spring Framework -&gt; 4.2.x-RELEASE</li>
+</ul>
+<p>There are two types of development required, one on server side and other on the client, which is then used by my team for managing security within their own web applications:</p>
+<ol>
+<li>CAS Server side development:</li>
+<li>Create own implementation for AbstractUsernamePasswordAuthenticationHandler</li>
+<li>
+<p>Implement Ignite Service Registry for CAS</p>
+</li>
+<li>
+<p>CAS Client side development:</p>
+</li>
+<li>Create own implementation for WebExpressionVoter</li>
+<li>Create own implementation for CasAuthenticationProvider</li>
+</ol>
+<h2 id="code-descriptions">Code Descriptions<a class="headerlink" href="#code-descriptions" title="Permanent link">&para;</a></h2>
+<h3 id="server-side-development">Server side development:<a class="headerlink" href="#server-side-development" title="Permanent link">&para;</a></h3>
+<h4 id="the-authentication-handler">The Authentication Handler<a class="headerlink" href="#the-authentication-handler" title="Permanent link">&para;</a></h4>
+<p>The interesting part for this solution is how to maintain both the Apereo CAS and Apache Fortress sessions. Luckily, CAS is using a token for maintaining their session and that token is also designed to have some extended attributes included with it.  Using this knowledge, we can modify the profile given by CAS Server to the client. Let's have a look what I've done with combining the Apereo CAS and Apache Fortress sessions in the code that follows.</p>
+<div class="codehilite"><pre><span class="cm">/*</span>
+<span class="cm"> * Copyright 2017 to PT. Global Digital Niaga(Blibli.com)</span>
+<span class="cm"> * </span>
+<span class="cm"> * Licensed under the Apache License, Version 2.0; you may not use this file except in compliance</span>
+<span class="cm"> * with the License. You may obtain a copy of the License at</span>
+<span class="cm"> * </span>
+<span class="cm"> * http://www.apache.org/licenses/LICENSE-2.0</span>
+<span class="cm"> * </span>
+<span class="cm"> * Unless required by applicable law or agreed to in writing, software distributed under the License</span>
+<span class="cm"> * is distributed on an &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express</span>
+<span class="cm"> * or implied. See the License for the specific language governing permissions and limitations under</span>
+<span class="cm"> * the License.</span>
+<span class="cm"> */</span>
+<span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">gdn</span><span class="o">.</span><span class="na">iam</span><span class="o">.</span><span class="na">cas</span><span class="o">;</span>
+
+<span class="kn">import</span> <span class="nn">java.io.StringWriter</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">java.security.GeneralSecurityException</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">java.util.HashMap</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">java.util.Map</span><span class="o">;</span>
+
+<span class="kn">import</span> <span class="nn">javax.xml.bind.JAXBContext</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">javax.xml.bind.JAXBException</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">javax.xml.bind.Marshaller</span><span class="o">;</span>
+
+<span class="kn">import</span> <span class="nn">org.apache.directory.fortress.core.AccessMgr</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.apache.directory.fortress.core.model.Session</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.apache.directory.fortress.core.model.User</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.jasig.cas.authentication.HandlerResult</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.jasig.cas.authentication.PreventedException</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.jasig.cas.authentication.UsernamePasswordCredential</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.slf4j.Logger</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.slf4j.LoggerFactory</span><span class="o">;</span>
+
+<span class="kd">public</span> <span class="kd">class</span> <span class="nc">IamAuthenticationHandler</span> <span class="kd">extends</span> <span class="n">AbstractUsernamePasswordAuthenticationHandler</span> <span class="o">{</span>
+
+  <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">Logger</span> <span class="n">LOG</span> <span class="o">=</span> <span class="n">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="n">IamAuthenticationHandler</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
+
+  <span class="kd">private</span> <span class="n">AccessMgr</span> <span class="n">accessManager</span><span class="o">;</span>
+  <span class="kd">private</span> <span class="n">JAXBContext</span> <span class="n">jaxbContext</span><span class="o">;</span>
+  <span class="kd">private</span> <span class="n">Marshaller</span> <span class="n">marshaller</span><span class="o">;</span>
+
+  <span class="kd">public</span> <span class="nf">IamAuthenticationHandler</span><span class="o">()</span> <span class="o">{</span>
+    <span class="k">try</span> <span class="o">{</span>
+      <span class="n">jaxbContext</span> <span class="o">=</span> <span class="n">JAXBContext</span><span class="o">.</span><span class="na">newInstance</span><span class="o">(</span><span class="n">Session</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
+      <span class="n">marshaller</span> <span class="o">=</span> <span class="n">jaxbContext</span><span class="o">.</span><span class="na">createMarshaller</span><span class="o">();</span>
+    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">JAXBException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">&quot;cannot bind Session with jaxb context&quot;</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
+    <span class="o">}</span>
+  <span class="o">}</span>
+
+  <span class="nd">@Override</span>
+  <span class="kd">protected</span> <span class="n">HandlerResult</span> <span class="nf">authenticateUsernamePasswordInternal</span><span class="o">(</span>
+      <span class="n">UsernamePasswordCredential</span> <span class="n">usernamePasswordCredential</span><span class="o">)</span>
+          <span class="kd">throws</span> <span class="n">GeneralSecurityException</span><span class="o">,</span> <span class="n">PreventedException</span> <span class="o">{</span>
+    <span class="n">String</span> <span class="n">username</span> <span class="o">=</span> <span class="n">usernamePasswordCredential</span><span class="o">.</span><span class="na">getUsername</span><span class="o">();</span>
+    <span class="n">String</span> <span class="n">password</span> <span class="o">=</span> <span class="n">usernamePasswordCredential</span><span class="o">.</span><span class="na">getPassword</span><span class="o">();</span>
+    <span class="n">Session</span> <span class="n">iamSession</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
+    <span class="n">String</span> <span class="n">iamXmlSession</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
+    <span class="k">try</span> <span class="o">{</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">trace</span><span class="o">(</span><span class="s">&quot;trying to authenticate username : {}, password : {}&quot;</span><span class="o">,</span>
+          <span class="k">new</span> <span class="n">Object</span><span class="o">[]</span> <span class="o">{</span><span class="n">username</span><span class="o">,</span> <span class="n">password</span><span class="o">});</span>
+      <span class="n">iamSession</span> <span class="o">=</span> <span class="n">accessManager</span><span class="o">.</span><span class="na">createSession</span><span class="o">(</span><span class="k">new</span> <span class="n">User</span><span class="o">(</span><span class="n">username</span><span class="o">,</span> <span class="n">password</span><span class="o">.</span><span class="na">toCharArray</span><span class="o">()),</span> <span class="kc">false</span><span class="o">);</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">trace</span><span class="o">(</span><span class="s">&quot;iam session : {}&quot;</span><span class="o">,</span> <span class="n">iamSession</span><span class="o">);</span>
+      <span class="k">if</span> <span class="o">(</span><span class="n">iamSession</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
+        <span class="n">StringWriter</span> <span class="n">writer</span> <span class="o">=</span> <span class="k">new</span> <span class="n">StringWriter</span><span class="o">();</span>
+        <span class="n">marshaller</span><span class="o">.</span><span class="na">marshal</span><span class="o">(</span><span class="n">iamSession</span><span class="o">,</span> <span class="n">writer</span><span class="o">);</span>
+        <span class="n">iamXmlSession</span> <span class="o">=</span> <span class="n">writer</span><span class="o">.</span><span class="na">toString</span><span class="o">();</span>
+        <span class="n">LOG</span><span class="o">.</span><span class="na">trace</span><span class="o">(</span><span class="s">&quot;iam xml session : {}&quot;</span><span class="o">,</span> <span class="n">iamXmlSession</span><span class="o">);</span>
+        <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">&gt;</span> <span class="n">attributes</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;&gt;();</span>
+        <span class="n">attributes</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">&quot;iamSession&quot;</span><span class="o">,</span> <span class="n">iamXmlSession</span><span class="o">);</span>
+        <span class="k">return</span> <span class="nf">createHandlerResult</span><span class="o">(</span><span class="n">usernamePasswordCredential</span><span class="o">,</span>
+            <span class="n">principalFactory</span><span class="o">.</span><span class="na">createPrincipal</span><span class="o">(</span><span class="n">username</span><span class="o">,</span> <span class="n">attributes</span><span class="o">),</span> <span class="kc">null</span><span class="o">);</span>
+      <span class="o">}</span>
+    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">org</span><span class="o">.</span><span class="na">apache</span><span class="o">.</span><span class="na">directory</span><span class="o">.</span><span class="na">fortress</span><span class="o">.</span><span class="na">core</span><span class="o">.</span><span class="na">SecurityException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
+      <span class="n">String</span> <span class="n">errorMessage</span> <span class="o">=</span> <span class="s">&quot;IAM authentication failed for [&quot;</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s">&quot;]&quot;</span><span class="o">;</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">trace</span><span class="o">(</span><span class="n">errorMessage</span><span class="o">);</span>
+      <span class="k">throw</span> <span class="k">new</span> <span class="nf">GeneralSecurityException</span><span class="o">(</span><span class="n">errorMessage</span><span class="o">);</span>
+    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">JAXBException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
+      <span class="n">String</span> <span class="n">errorMessage</span> <span class="o">=</span> <span class="s">&quot;cannot marshalling session with value : &quot;</span> <span class="o">+</span> <span class="n">iamSession</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="s">&quot;null&quot;</span>
+          <span class="o">:</span> <span class="n">iamSession</span><span class="o">.</span><span class="na">toString</span><span class="o">();</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">trace</span><span class="o">(</span><span class="n">errorMessage</span><span class="o">);</span>
+      <span class="k">throw</span> <span class="k">new</span> <span class="nf">GeneralSecurityException</span><span class="o">(</span><span class="n">errorMessage</span><span class="o">);</span>
+    <span class="o">}</span>
+    <span class="n">LOG</span><span class="o">.</span><span class="na">trace</span><span class="o">(</span><span class="s">&quot;returning default handler&quot;</span><span class="o">);</span>
+    <span class="k">return</span> <span class="nf">createHandlerResult</span><span class="o">(</span><span class="n">usernamePasswordCredential</span><span class="o">,</span>
+        <span class="n">principalFactory</span><span class="o">.</span><span class="na">createPrincipal</span><span class="o">(</span><span class="n">username</span><span class="o">),</span> <span class="kc">null</span><span class="o">);</span>
+  <span class="o">}</span>
+
+  <span class="kd">public</span> <span class="n">AccessMgr</span> <span class="nf">getAccessManager</span><span class="o">()</span> <span class="o">{</span>
+    <span class="k">return</span> <span class="n">accessManager</span><span class="o">;</span>
+  <span class="o">}</span>
+
+  <span class="kd">public</span> <span class="kt">void</span> <span class="nf">setAccessManager</span><span class="o">(</span><span class="n">AccessMgr</span> <span class="n">accessManager</span><span class="o">)</span> <span class="o">{</span>
+    <span class="k">this</span><span class="o">.</span><span class="na">accessManager</span> <span class="o">=</span> <span class="n">accessManager</span><span class="o">;</span>
+  <span class="o">}</span>
+
+<span class="o">}</span>
+</pre></div>
+
+
+<p>In the above source code you can see how I construct a new principal by creating a new attribute map with values contained withing the Apache Fortress Session xml.</p>
+<h4 id="attribute-populator">Attribute Populator<a class="headerlink" href="#attribute-populator" title="Permanent link">&para;</a></h4>
+<p>In order to populate fortress and pass it on to the client we need to override the casServiceValidationSuccess.jsp file, located at WEB-INF/view/jsp/protocol/2.0/, since its default view won't populating the necessary attributes. Here is how I was able to accomplish that:</p>
+<div class="codehilite"><pre><span class="err">&lt;</span>%@ page session=&quot;false&quot; contentType=&quot;application/xml; charset=UTF-8&quot; %&gt;
+<span class="err">&lt;</span>%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jsp/jstl/core&quot; %&gt;
+<span class="err">&lt;</span>%@ taglib uri=&quot;http://java.sun.com/jsp/jstl/functions&quot; prefix=&quot;fn&quot; %&gt;
+<span class="nt">&lt;cas:serviceResponse</span> <span class="na">xmlns:cas=</span><span class="s">&#39;http://www.yale.edu/tp/cas&#39;</span><span class="nt">&gt;</span>
+    <span class="c">&lt;!-- cas 2 validation success --&gt;</span>
+    <span class="nt">&lt;cas:authenticationSuccess&gt;</span>
+        <span class="nt">&lt;cas:user&gt;</span>${fn:escapeXml(assertion.primaryAuthentication.principal.id)}<span class="nt">&lt;/cas:user&gt;</span>
+        <span class="nt">&lt;c:if</span> <span class="na">test=</span><span class="s">&quot;${not empty assertion.primaryAuthentication.principal.attributes}&quot;</span><span class="nt">&gt;</span>
+        <span class="nt">&lt;cas:attributes&gt;</span>
+            <span class="nt">&lt;c:forEach</span> <span class="na">var=</span><span class="s">&quot;attr&quot;</span> <span class="na">items=</span><span class="s">&quot;${assertion.primaryAuthentication.principal.attributes}&quot;</span> <span class="nt">&gt;</span>
+                <span class="nt">&lt;cas:</span><span class="err">${fn:escapeXml(attr.key)}</span><span class="nt">&gt;</span><span class="cp">&lt;![CDATA[${attr.value}]]&gt;</span><span class="err">&lt;</span>/cas:${fn:escapeXml(attr.key)}&gt;
+            <span class="nt">&lt;/c:forEach&gt;</span>
+        <span class="nt">&lt;/cas:attributes&gt;</span>
+        <span class="nt">&lt;/c:if&gt;</span>
+        <span class="nt">&lt;c:if</span> <span class="na">test=</span><span class="s">&quot;${not empty pgtIou}&quot;</span><span class="nt">&gt;</span>
+                <span class="nt">&lt;cas:proxyGrantingTicket&gt;</span>${pgtIou}<span class="nt">&lt;/cas:proxyGrantingTicket&gt;</span>
+        <span class="nt">&lt;/c:if&gt;</span>
+        <span class="nt">&lt;c:if</span> <span class="na">test=</span><span class="s">&quot;${fn:length(assertion.chainedAuthentications) &gt; 1}&quot;</span><span class="nt">&gt;</span>
+          <span class="nt">&lt;cas:proxies&gt;</span>
+            <span class="nt">&lt;c:forEach</span> <span class="na">var=</span><span class="s">&quot;proxy&quot;</span> <span class="na">items=</span><span class="s">&quot;${assertion.chainedAuthentications}&quot;</span> <span class="na">varStatus=</span><span class="s">&quot;loopStatus&quot;</span> <span class="na">begin=</span><span class="s">&quot;0&quot;</span> <span class="na">end=</span><span class="s">&quot;${fn:length(assertion.chainedAuthentications)-2}&quot;</span> <span class="na">step=</span><span class="s">&quot;1&quot;</span><span class="nt">&gt;</span>
+                 <span class="nt">&lt;cas:proxy&gt;</span>${fn:escapeXml(proxy.principal.id)}<span class="nt">&lt;/cas:proxy&gt;</span>
+            <span class="nt">&lt;/c:forEach&gt;</span>
+          <span class="nt">&lt;/cas:proxies&gt;</span>
+        <span class="nt">&lt;/c:if&gt;</span>
+    <span class="nt">&lt;/cas:authenticationSuccess&gt;</span>
+<span class="nt">&lt;/cas:serviceResponse&gt;</span>
+</pre></div>
+
+
+<p>One thing that I love about CAS, even if you correctly extracted the attribute at this page (or maybe you just got hacked at this page), CAS is able to protect the returned attributes by changing the services registry configuration. see the HTTPSandIMAPS-10000001.json file. I’ve put ReturnAllAttributeReleasePolicy type for debuging all the attributes returned, you can change it later to make your application more secure as well.</p>
+<h4 id="apache-ignite-for-ticket-replication">Apache Ignite For Ticket Replication<a class="headerlink" href="#apache-ignite-for-ticket-replication" title="Permanent link">&para;</a></h4>
+<p>To have a production readiness we need to somehow manage a high availability requirement, so we're not just using a single cas server. That is why we needed to have a centralized or distributed ticket repository, to allow cas to scale. To scale the ticket repository, I chose Apache Ignite for distributing the tickets. To Implement is very simple, and is also written about in Apereo CAS documentation.</p>
+<h3 id="client-side-development">Client side development:<a class="headerlink" href="#client-side-development" title="Permanent link">&para;</a></h3>
+<h4 id="the-spring-voter">The Spring Voter<a class="headerlink" href="#the-spring-voter" title="Permanent link">&para;</a></h4>
+<p>Spring is a great framework, they allow you to add your own interceptors to use your own implementation. WebExpressionVoter is the class you need to extend in order to override the normal spring decision mechanism.  Usually you will use xml + regex for registering the condition. However, xml + regex is not the approach I wanted for my development team. See below code snippet, to understand what I did to make this more dynamic.</p>
+<div class="codehilite"><pre>  <span class="nd">@Override</span>
+  <span class="nd">@SuppressWarnings</span><span class="o">(</span><span class="s">&quot;static-access&quot;</span><span class="o">)</span>
+  <span class="kd">public</span> <span class="kt">int</span> <span class="nf">vote</span><span class="o">(</span><span class="n">Authentication</span> <span class="n">authentication</span><span class="o">,</span> <span class="n">FilterInvocation</span> <span class="n">fi</span><span class="o">,</span>
+      <span class="n">Collection</span><span class="o">&lt;</span><span class="n">ConfigAttribute</span><span class="o">&gt;</span> <span class="n">attributes</span><span class="o">)</span> <span class="o">{</span>
+    <span class="n">Authentication</span> <span class="n">securityContextAuthentication</span> <span class="o">=</span>
+        <span class="n">SecurityContextHolder</span><span class="o">.</span><span class="na">getContext</span><span class="o">().</span><span class="na">getAuthentication</span><span class="o">();</span>
+    <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="kd">super</span><span class="o">.</span><span class="na">vote</span><span class="o">(</span><span class="n">securityContextAuthentication</span><span class="o">,</span> <span class="n">fi</span><span class="o">,</span> <span class="n">attributes</span><span class="o">);</span>
+    <span class="k">if</span> <span class="o">(</span><span class="n">System</span><span class="o">.</span><span class="na">getenv</span><span class="o">(</span><span class="n">IAM_SECURITY_PARAMETER</span><span class="o">)</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">warn</span><span class="o">(</span><span class="s">&quot;iam security is disable, enable all access mode is enable&quot;</span><span class="o">);</span>
+      <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
+    <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">&quot;authentication = {}&quot;</span><span class="o">,</span>
+          <span class="n">ToStringBuilder</span><span class="o">.</span><span class="na">reflectionToString</span><span class="o">(</span><span class="n">securityContextAuthentication</span><span class="o">));</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">&quot;super vote for : {}&quot;</span><span class="o">,</span> <span class="n">result</span><span class="o">);</span>
+      <span class="k">if</span> <span class="o">(</span><span class="kd">super</span><span class="o">.</span><span class="na">ACCESS_GRANTED</span> <span class="o">==</span> <span class="n">result</span><span class="o">)</span> <span class="o">{</span>
+        <span class="n">String</span> <span class="n">requestMethod</span> <span class="o">=</span> <span class="n">fi</span><span class="o">.</span><span class="na">getRequest</span><span class="o">().</span><span class="na">getMethod</span><span class="o">().</span><span class="na">toLowerCase</span><span class="o">();</span>
+        <span class="n">String</span> <span class="n">filterUrl</span> <span class="o">=</span> <span class="n">getFilterUrl</span><span class="o">(</span><span class="n">fi</span><span class="o">.</span><span class="na">getHttpRequest</span><span class="o">());</span>
+        <span class="k">if</span> <span class="o">(</span><span class="n">filterUrl</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
+          <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
+        <span class="o">}</span>
+        <span class="k">try</span> <span class="o">{</span>
+          <span class="n">CasAuthenticationToken</span> <span class="n">casAuthenticationToken</span> <span class="o">=</span>
+              <span class="o">((</span><span class="n">CasAuthenticationToken</span><span class="o">)</span> <span class="n">securityContextAuthentication</span><span class="o">);</span>
+          <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">&quot;assertion : {}&quot;</span><span class="o">,</span>
+              <span class="n">ToStringBuilder</span><span class="o">.</span><span class="na">reflectionToString</span><span class="o">(</span><span class="n">casAuthenticationToken</span><span class="o">.</span><span class="na">getAssertion</span><span class="o">()));</span>
+          <span class="n">String</span> <span class="n">iamSessionXml</span> <span class="o">=</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">casAuthenticationToken</span><span class="o">.</span><span class="na">getAssertion</span><span class="o">().</span><span class="na">getAttributes</span><span class="o">()</span>
+              <span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">IAM_SESSION_ATTRIBUTE_KEY</span><span class="o">);</span>
+          <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">&quot;iam session xml == {}&quot;</span><span class="o">,</span> <span class="n">iamSessionXml</span><span class="o">);</span>
+          <span class="n">Session</span> <span class="n">iamSession</span> <span class="o">=</span> <span class="n">sessionCache</span><span class="o">.</span><span class="na">getIfPresent</span><span class="o">(</span><span class="n">casAuthenticationToken</span><span class="o">.</span><span class="na">getKeyHash</span><span class="o">());</span>
+          <span class="k">if</span> <span class="o">(</span><span class="n">iamSession</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
+            <span class="n">Unmarshaller</span> <span class="n">unmarshaller</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
+            <span class="k">try</span> <span class="o">{</span>
+              <span class="n">unmarshaller</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">createUnmarshaller</span><span class="o">();</span>
+            <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">JAXBException</span> <span class="n">ex</span><span class="o">)</span> <span class="o">{</span>
+              <span class="n">LOG</span><span class="o">.</span><span class="na">warn</span><span class="o">(</span><span class="s">&quot;cannot create unmarshaller : &quot;</span><span class="o">,</span> <span class="n">ex</span><span class="o">);</span>
+            <span class="o">}</span>
+            <span class="n">iamSession</span> <span class="o">=</span> <span class="o">(</span><span class="n">Session</span><span class="o">)</span> <span class="n">unmarshaller</span><span class="o">.</span><span class="na">unmarshal</span><span class="o">(</span><span class="k">new</span> <span class="n">StringReader</span><span class="o">(</span><span class="n">iamSessionXml</span><span class="o">));</span>
+            <span class="n">sessionCache</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">casAuthenticationToken</span><span class="o">.</span><span class="na">getKeyHash</span><span class="o">(),</span> <span class="n">iamSession</span><span class="o">);</span>
+          <span class="o">}</span>
+          <span class="n">StringBuilder</span> <span class="n">sessionPermissionKeyBuilder</span> <span class="o">=</span> <span class="k">new</span> <span class="n">StringBuilder</span><span class="o">(</span><span class="n">iamSession</span><span class="o">.</span><span class="na">getSessionId</span><span class="o">()).</span><span class="na">append</span><span class="o">(</span><span class="n">filterUrl</span><span class="o">).</span><span class="na">append</span><span class="o">(</span><span class="n">requestMethod</span><span class="o">);</span>
+          <span class="n">Boolean</span> <span class="n">isAllowed</span> <span class="o">=</span> <span class="n">accessCache</span><span class="o">.</span><span class="na">getIfPresent</span><span class="o">(</span><span class="n">sessionPermissionKeyBuilder</span><span class="o">.</span><span class="na">toString</span><span class="o">());</span>
+          <span class="k">if</span><span class="o">(</span><span class="n">isAllowed</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
+            <span class="n">isAllowed</span> <span class="o">=</span> <span class="n">accessManager</span><span class="o">.</span><span class="na">checkAccess</span><span class="o">(</span><span class="n">iamSession</span><span class="o">,</span> <span class="k">new</span> <span class="n">Permission</span><span class="o">(</span><span class="n">filterUrl</span><span class="o">,</span> <span class="n">requestMethod</span><span class="o">));</span>
+            <span class="n">accessCache</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">sessionPermissionKeyBuilder</span><span class="o">.</span><span class="na">toString</span><span class="o">(),</span> <span class="n">isAllowed</span><span class="o">);</span>
+          <span class="o">}</span>
+          <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">&quot;{} is {} to access {} with method {}&quot;</span><span class="o">,</span>
+              <span class="k">new</span> <span class="n">Object</span><span class="o">[]</span> <span class="o">{</span><span class="n">securityContextAuthentication</span><span class="o">.</span><span class="na">getName</span><span class="o">(),</span>
+                  <span class="n">isAllowed</span> <span class="o">?</span> <span class="s">&quot;granted&quot;</span> <span class="o">:</span> <span class="s">&quot;denied&quot;</span><span class="o">,</span> <span class="n">filterUrl</span><span class="o">,</span> <span class="n">requestMethod</span><span class="o">});</span>
+          <span class="k">if</span> <span class="o">(</span><span class="n">isAllowed</span><span class="o">)</span> <span class="o">{</span>
+            <span class="k">return</span> <span class="kd">super</span><span class="o">.</span><span class="na">ACCESS_GRANTED</span><span class="o">;</span>
+          <span class="o">}</span>
+        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
+          <span class="n">LOG</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">&quot;catch exception when communicate with iam server&quot;</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
+        <span class="o">}</span>
+      <span class="o">}</span>
+      <span class="k">return</span> <span class="kd">super</span><span class="o">.</span><span class="na">ACCESS_DENIED</span><span class="o">;</span>
+    <span class="o">}</span>
+  <span class="o">}</span>
+</pre></div>
+
+
+<p>Yep, I'm calling fortress to check if the user is allowed to access fortress permissions or not.</p>
+<h5 id="userdetail-populator">UserDetail Populator<a class="headerlink" href="#userdetail-populator" title="Permanent link">&para;</a></h5>
+<p>Spring uses the implementation of AbstractCasAssertionUserDetailsService to populate user details following successful authentication, you can see the example at IamUserDetails code, here is the snipet of that class:</p>
+<div class="codehilite"><pre><span class="nd">@Override</span>
+  <span class="kd">protected</span> <span class="n">UserDetails</span> <span class="nf">loadUserDetails</span><span class="o">(</span><span class="kd">final</span> <span class="n">Assertion</span> <span class="n">assertion</span><span class="o">)</span> <span class="o">{</span>
+    <span class="n">List</span><span class="o">&lt;</span><span class="n">GrantedAuthority</span><span class="o">&gt;</span> <span class="n">grantedAuthorities</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o">&lt;&gt;();</span>
+    <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">&quot;user asssertion : {}&quot;</span><span class="o">,</span> <span class="n">ToStringBuilder</span><span class="o">.</span><span class="na">reflectionToString</span><span class="o">(</span><span class="n">assertion</span><span class="o">));</span>
+    <span class="kt">boolean</span> <span class="n">accountNonExpired</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
+    <span class="kt">boolean</span> <span class="n">credentialsNonExpired</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
+    <span class="kt">boolean</span> <span class="n">accountNonLocked</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
+    <span class="kt">boolean</span> <span class="n">enabled</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
+    <span class="k">for</span> <span class="o">(</span><span class="n">String</span> <span class="n">attribute</span> <span class="o">:</span> <span class="k">this</span><span class="o">.</span><span class="na">attributes</span><span class="o">)</span> <span class="o">{</span>
+      <span class="n">String</span> <span class="n">value</span> <span class="o">=</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">assertion</span><span class="o">.</span><span class="na">getPrincipal</span><span class="o">().</span><span class="na">getAttributes</span><span class="o">().</span><span class="na">get</span><span class="o">(</span><span class="n">attribute</span><span class="o">);</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">&quot;value = {}&quot;</span><span class="o">,</span> <span class="n">value</span><span class="o">);</span>
+      <span class="k">if</span> <span class="o">(</span><span class="n">value</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
+        <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">&quot;adding default authorization to user&quot;</span><span class="o">);</span>
+    <span class="n">grantedAuthorities</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="n">SimpleGrantedAuthority</span><span class="o">(</span><span class="n">ROLE_USER</span><span class="o">));</span>
+
+        <span class="n">Unmarshaller</span> <span class="n">unmarshaller</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>    
+        <span class="n">Session</span> <span class="n">iamSession</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
+        <span class="k">try</span> <span class="o">{</span>
+          <span class="n">unmarshaller</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">createUnmarshaller</span><span class="o">();</span>
+          <span class="n">iamSession</span> <span class="o">=</span> <span class="o">(</span><span class="n">Session</span><span class="o">)</span> <span class="n">unmarshaller</span><span class="o">.</span><span class="na">unmarshal</span><span class="o">(</span><span class="k">new</span> <span class="n">StringReader</span><span class="o">(</span><span class="n">value</span><span class="o">));</span>
+          <span class="k">for</span> <span class="o">(</span><span class="n">UserRole</span> <span class="n">role</span> <span class="o">:</span> <span class="n">iamSession</span><span class="o">.</span><span class="na">getRoles</span><span class="o">())</span> <span class="o">{</span>
+            <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">&quot;adding {} authorization to user&quot;</span><span class="o">,</span> <span class="n">role</span><span class="o">.</span><span class="na">getName</span><span class="o">().</span><span class="na">toUpperCase</span><span class="o">());</span>
+            <span class="n">grantedAuthorities</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="n">SimpleGrantedAuthority</span><span class="o">(</span><span class="n">role</span><span class="o">.</span><span class="na">getName</span><span class="o">().</span><span class="na">toUpperCase</span><span class="o">()));</span>
+          <span class="o">}</span>
+        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">Exception</span> <span class="n">ex</span><span class="o">)</span> <span class="o">{</span>
+          <span class="n">LOG</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">&quot;cannot generate user details&quot;</span><span class="o">,</span> <span class="n">ex</span><span class="o">);</span>
+        <span class="o">}</span>
+      <span class="o">}</span>
+    <span class="o">}</span>
+    <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span>
+        <span class="s">&quot;accountNonExpired : {}, credentialsNonExpired : {}, accountNonLocked : {}, enabled : {}&quot;</span><span class="o">,</span>
+        <span class="k">new</span> <span class="n">Object</span><span class="o">[]</span> <span class="o">{</span><span class="n">accountNonExpired</span><span class="o">,</span> <span class="n">credentialsNonExpired</span><span class="o">,</span> <span class="n">accountNonLocked</span><span class="o">,</span> <span class="n">enabled</span><span class="o">});</span>
+    <span class="k">return</span> <span class="k">new</span> <span class="nf">User</span><span class="o">(</span><span class="n">assertion</span><span class="o">.</span><span class="na">getPrincipal</span><span class="o">().</span><span class="na">getName</span><span class="o">().</span><span class="na">toLowerCase</span><span class="o">().</span><span class="na">trim</span><span class="o">(),</span> <span class="n">NON_EXISTENT_PASSWORD_VALUE</span><span class="o">,</span> <span class="n">enabled</span><span class="o">,</span>
+        <span class="n">accountNonExpired</span><span class="o">,</span> <span class="n">credentialsNonExpired</span><span class="o">,</span> <span class="n">accountNonLocked</span><span class="o">,</span> <span class="n">grantedAuthorities</span><span class="o">);</span>
+  <span class="o">}</span>
+</pre></div>
+
+
+<p>You can change the implementation later for your needs.</p>
+<h5 id="network-might-be-a-problem">Network Might Be a Problem<a class="headerlink" href="#network-might-be-a-problem" title="Permanent link">&para;</a></h5>
+<p>Since this is running inside a production environment, we needed to consider that sometimes there might be a trouble over our network that causes problems and requires retries. That is why it's important to allow a little delay time in our application.  Here's an example of how allow a small delay, in order to allow temorary network glitches and slowdowns to work themselves out.</p>
+<div class="codehilite"><pre><span class="cm">/*</span>
+<span class="cm"> * Copyright 2017 to PT. Global Digital Niaga(Blibli.com)</span>
+<span class="cm"> * </span>
+<span class="cm"> * Licensed under the Apache License, Version 2.0; you may not use this file except in compliance</span>
+<span class="cm"> * with the License. You may obtain a copy of the License at</span>
+<span class="cm"> * </span>
+<span class="cm"> * http://www.apache.org/licenses/LICENSE-2.0</span>
+<span class="cm"> * </span>
+<span class="cm"> * Unless required by applicable law or agreed to in writing, software distributed under the License</span>
+<span class="cm"> * is distributed on an &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express</span>
+<span class="cm"> * or implied. See the License for the specific language governing permissions and limitations under</span>
+<span class="cm"> * the License.</span>
+<span class="cm"> */</span>
+<span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">gdn</span><span class="o">.</span><span class="na">iam</span><span class="o">.</span><span class="na">spring</span><span class="o">.</span><span class="na">security</span><span class="o">;</span>
+
+<span class="kn">import</span> <span class="nn">org.slf4j.Logger</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.slf4j.LoggerFactory</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.springframework.security.cas.authentication.CasAuthenticationProvider</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.springframework.security.core.Authentication</span><span class="o">;</span>
+<span class="kn">import</span> <span class="nn">org.springframework.security.core.AuthenticationException</span><span class="o">;</span>
+
+<span class="kd">public</span> <span class="kd">class</span> <span class="nc">GdnCasAuthenticationProvider</span> <span class="kd">extends</span> <span class="n">CasAuthenticationProvider</span> <span class="o">{</span>
+
+  <span class="kd">private</span> <span class="kd">static</span> <span class="kd">transient</span> <span class="n">Logger</span> <span class="n">LOG</span> <span class="o">=</span> <span class="n">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="n">GdnCasAuthenticationProvider</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
+  <span class="kd">private</span> <span class="kt">long</span> <span class="n">sleepForDistributeTicketTime</span> <span class="o">=</span> <span class="mi">300</span><span class="o">;</span>
+
+  <span class="nd">@Override</span>
+  <span class="kd">public</span> <span class="n">Authentication</span> <span class="nf">authenticate</span><span class="o">(</span><span class="n">Authentication</span> <span class="n">authentication</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">AuthenticationException</span> <span class="o">{</span>
+    <span class="k">try</span> <span class="o">{</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">trace</span><span class="o">(</span>
+          <span class="s">&quot;will try to sleep for waiting ticket to be distributed to other node, sleep time : {}&quot;</span><span class="o">,</span>
+          <span class="n">getSleepForDistributeTicketTime</span><span class="o">());</span>
+      <span class="n">Thread</span><span class="o">.</span><span class="na">sleep</span><span class="o">(</span><span class="n">getSleepForDistributeTicketTime</span><span class="o">());</span>
+    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">InterruptedException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
+      <span class="n">LOG</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">&quot;something wrong when sleeping&quot;</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
+    <span class="o">}</span>
+    <span class="k">return</span> <span class="kd">super</span><span class="o">.</span><span class="na">authenticate</span><span class="o">(</span><span class="n">authentication</span><span class="o">);</span>
+  <span class="o">}</span>
+
+  <span class="kd">public</span> <span class="kt">long</span> <span class="nf">getSleepForDistributeTicketTime</span><span class="o">()</span> <span class="o">{</span>
+    <span class="k">return</span> <span class="n">sleepForDistributeTicketTime</span><span class="o">;</span>
+  <span class="o">}</span>
+
+  <span class="kd">public</span> <span class="kt">void</span> <span class="nf">setSleepForDistributeTicketTime</span><span class="o">(</span><span class="kt">long</span> <span class="n">sleepForDistributeTicketTime</span><span class="o">)</span> <span class="o">{</span>
+    <span class="k">this</span><span class="o">.</span><span class="na">sleepForDistributeTicketTime</span> <span class="o">=</span> <span class="n">sleepForDistributeTicketTime</span><span class="o">;</span>
+  <span class="o">}</span>
+
+<span class="o">}</span>
+</pre></div>
+
+
+<h3 id="descriptions-of-authentication-flow">Descriptions of authentication flow<a class="headerlink" href="#descriptions-of-authentication-flow" title="Permanent link">&para;</a></h3>
+<p>The CAS authentication flow will be the same, no changes are required in terms of that authentication flow. Furthermore, you can see that flow at Apereo CAS 4.2.x documentation page.</p>
+<p>The main difference now is we don't put the ticket registry inside an in-memory database, we put it inside an Apache Ignite cache, so when other nodes are there it can replicate the ticket between them which increases efficiencies.</p>
+<h3 id="descriptions-of-authorization-flow">Descriptions of authorization flow<a class="headerlink" href="#descriptions-of-authorization-flow" title="Permanent link">&para;</a></h3>
+<p>Spring Security usually has the authorization role configuration inside your spring context xml file or using annotations in source. This is the only difference between plain spring security and that using my extended framework solution.  We put the configuration inside of Fortress. Everytime the user changes the URL, it will check the user has access to that specific URL and not through the extended voter class. If the user is authorized then the app will give them the correct page, otherwise it will route to 40X http error status page.</p>
+<h3 id="instructions-to-test">Instructions to test<a class="headerlink" href="#instructions-to-test" title="Permanent link">&para;</a></h3>
+<p>For testing this example, you need to understand that Apache Fortress configuration is necessary to find fortress.properties on the classpath so it might be good if you put that configuration file at the same classpath, for instance, if you are using tomcat remove all the fortress.properties inside the classes directory and put it on $TOMCAT_HOME/lib/ folder. Make sure get Apache Fortress running at the first step. Here are the detailed instructions for testing this example:</p>
+<h4 id="server-section">Server Section<a class="headerlink" href="#server-section" title="Permanent link">&para;</a></h4>
+<p>Read and find the instruction at :
+ * https://github.com/apache/directory-fortress-core
+ * https://github.com/apache/directory-fortress-enmasse
+ * https://github.com/apache/directory-fortress-commander
+ * and configure your Apache Fortress properly.
+ * Clone the project from link at Where to download section below, change the configuration properly inside cas-fortress-servers/src/main/resources folder and package it using mvn clean package.
+ * Copy the war file from cas-fortress-server/target into the web-container deploy directory.
+ * Start your web-container and you get cas fortress integrated.</p>
+<h4 id="client-section">Client Section<a class="headerlink" href="#client-section" title="Permanent link">&para;</a></h4>
+<ul>
+<li>Simply put the war file inside the web-container deploy directory.</li>
+<li>Open and login to your commander(fortress-web)</li>
+<li>Create a user with role ROLE_USER (you can change to what ever role). The role need to align with spring-security.xml for this statement <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />. This is the mandatory role, with this role we are seperate between the anonymous role and authenticate one.</li>
+<li>Create a permission object containing your restricted url, for instance http://localhost:8080/cas-fortress-client/profile and http://localhost:8080/cas-fortress-client/catalog.</li>
+<li>Map the permission object and role at permission tab at your commander. Currently we only support get for both of the url.</li>
+<li>Start your web-container and play with your cas-fortress-client later on.</li>
+</ul>
+<h3 id="where-to-download">Where to download<a class="headerlink" href="#where-to-download" title="Permanent link">&para;</a></h3>
+<ul>
+<li>https://github.com/bliblidotcom/cas-fortress-example</li>
+</ul>
+<h2 id="next-steps">Next Steps<a class="headerlink" href="#next-steps" title="Permanent link">&para;</a></h2>
+<p>The next step should be implementing ARBAC solution. Since I donn't allow people to create a conditional statement inside their code to check for roles, buttons or page elements that should be not accessible for specific users will appear, even they can't perform that action.  This causes some confusion in terms or usability for my users. With ARBAC I believe I can do a whitelist for the page attributes and increase the usability for the user.</p>