title: CakePHP 3 REST API authentication while still using the existing controllers
body: <p>I am having trouble implementing a REST API authentication for mobile in CakePHP 3.</p>
  
  <p>Reading the Authentication official CakePHP 3 documentation:</p>
  
  <p><a href="http://book.cakephp.org/3.0/en/controllers/components/authentication.html#id1" rel="nofollow noreferrer">http://book.cakephp.org/3.0/en/controllers/components/authentication.html#id1</a></p>
  
  <p>It said that I can use Stateless Basic Authentication instead of Form Authentication. However, I also read in one of the forums that you cannot use both Basic and Form Authentication at the same time.</p>
  
  <p>I also researched on using prefix route for REST API.</p>
  
  <p><a href="http://www.bravo-kernel.com/2015/04/how-to-prefix-route-a-cakephp-3-rest-api/" rel="nofollow noreferrer">http://www.bravo-kernel.com/2015/04/how-to-prefix-route-a-cakephp-3-rest-api/</a></p>
  
  <p>By doing so, I can now perform the Basic Authentication to the prefix route and the Form Authentication to the non-prefix route. However, this requires controllers to be defined in its prefix namespace which violates CakePHP's concept of keeping your code DRY; as my controllers already consist logic catering for web and mobile devices.</p>
  
  <p>If I were to just use Form Authentication, I can just create a POST request from my mobile to the web system but the response would be in HTML format. It would not be a good approach to parse the entire HTML format.</p>
  
  <p>I am stuck and do not know what to do. I kept on researching the entire afternoon and still failed in finding a solution. </p>
  
  <p>All I want is to be able to authenticate through my mobile app while still using the same controllers. </p>
  
  <p>EDIT: Workaround</p>
  
  <pre><code>class AppController extends Controller
  {
      public function initialize()
      {
          parent::initialize();
          $this-&gt;loadComponent('Auth', [
              'authorize' =&gt; 'Controller',
              'authenticate' =&gt; [
                  'Form' =&gt; [
                      'fields' =&gt; [
                          'username' =&gt; 'username',
                          'password' =&gt; 'password'
                      ]
                  ]
              ],
              'loginAction' =&gt; ['controller' =&gt; 'Users', 'action' =&gt; 'login'],
              'unauthorizedRedirect' =&gt; $this-&gt;referer()
          ]);
      }
  
      public function beforeFilter(Event $event)
      {
          if($this-&gt;request-&gt;params['_ext'] === 'json')
          {
              $this-&gt;Auth-&gt;config('authenticate', ['Basic' =&gt; ['userModel' =&gt; 'Users']]);
              $this-&gt;Auth-&gt;config('storage', 'Memory');
              $this-&gt;Auth-&gt;config('unauthorizedRedirect', false);
          }
          return parent::beforeFilter($event);
      }
  }
  </code></pre>
  
  <p>Managed to make it work by conditionally adding Basic Authentication to the authenticate configuration.</p>
  
  <p>However, this is not the perfect solution as it certainly has pitfalls.</p>
  
  <p>This will only work under the assumptions that:</p>
  
  <ol>
  <li><p>Referring to this post: CakePHP will do a priority based on the order of authentication schemes. Since the Form Auth came before the Basic Auth, the Basic Auth will not execute if the Form Auth is successful.</p>
  
  <p><a href="https://stackoverflow.com/questions/11134080/cakephp-2-1-as-a-web-application-and-rest-service-with-authentication?rq=1">CakePHP 2.1 - As a web application and REST service with Authentication</a></p></li>
  <li><p>Normally, web users will not visit URL with the file extension of json, so the user will be redirected to the user login page using Form Authentication.</p></li>
  <li><p>Once the user is authenticated through Form Authentication, the Basic Authentication won't pop up even if the user will indirectly visit URL ending with .json using AJAX.</p></li>
  </ol>
  
  <p>Is there any better way? </p>