Uncategorized

PlayFramework SecureSocial and MongoDB

In this blog post we will cover on how to integrate SecureSocial into a PlayFramework Application.
SecureSocial is an authentication module for Play Framework applications supporting OAuth, OAuth2, OpenID, Username/Password and custom authentication schemes. SecureSocial has an example where the tokens and users are all stored in memory , but to make it a bit more interesting we will store all the users into MongoDB using Play ReactiveMongo Plugin.

Lets get started.

Installation

Add the required dependencies to the projects/Build.scala

project/Build.scala
<span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<code class="scala"><span class="line"><span class="k">object</span> <span class="nc">ApplicationBuild</span> <span class="k">extends</span> <span class="nc">Build</span> <span class="o">{</span>
</span>
<span class="line">  <span class="k">val</span> <span class="n">appName</span>         <span class="k">=</span> <span class="s">"crowdsource"</span>
</span><span class="line">  <span class="k">val</span> <span class="n">appVersion</span>      <span class="k">=</span> <span class="s">"1.0-SNAPSHOT"</span>
</span>
<span class="line">  <span class="k">val</span> <span class="n">appDependencies</span> <span class="k">=</span> <span class="nc">Seq</span><span class="o">(</span>
</span><span class="line">    <span class="c1">// Add your project dependencies here,</span>
</span><span class="line">    <span class="n">jdbc</span><span class="o">,</span>
</span><span class="line">    <span class="n">anorm</span><span class="o">,</span>
</span><span class="line">    <span class="s">"org.reactivemongo"</span> <span class="o">%%</span> <span class="s">"play2-reactivemongo"</span> <span class="o">%</span> <span class="s">"0.9"</span><span class="o">,</span>
</span><span class="line">    <span class="s">"securesocial"</span> <span class="o">%%</span> <span class="s">"securesocial"</span> <span class="o">%</span> <span class="s">"2.1.1"</span>
</span><span class="line">  <span class="o">)</span>
</span>

<span class="line">  <span class="k">val</span> <span class="n">main</span> <span class="k">=</span> <span class="n">play</span><span class="o">.</span><span class="nc">Project</span><span class="o">(</span><span class="n">appName</span><span class="o">,</span> <span class="n">appVersion</span><span class="o">,</span> <span class="n">appDependencies</span><span class="o">).</span><span class="n">settings</span><span class="o">(</span>
</span><span class="line">    <span class="n">resolvers</span> <span class="o">+=</span> <span class="nc">Resolver</span><span class="o">.</span><span class="n">url</span><span class="o">(</span><span class="s">"sbt-plugin-snapshots"</span><span class="o">,</span> <span class="n">url</span><span class="o">(</span><span class="s">"http://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/"</span><span class="o">))(</span><span class="nc">Resolver</span><span class="o">.</span><span class="n">ivyStylePatterns</span><span class="o">)</span>
</span><span class="line">  <span class="o">)</span>
</span>
<span class="line"><span class="o">}</span>  
</span></code>

ReactiveMongo Configuration

Create a file in conf/play.plugins

conf/play.plugins
<span class="line-number">1</span>
<code class="scala"><span class="line"><span class="mi">400</span><span class="k">:</span><span class="kt">play.modules.reactivemongo.ReactiveMongoPlugin</span>
</span></code>

MongoDB configuration in conf/application.conf

conf/application.conf
<span class="line-number">1</span>
<span class="line-number">2</span>
<code class="scala"><span class="line"><span class="n">mongodb</span><span class="o">.</span><span class="n">servers</span> <span class="k">=</span> <span class="o">[</span><span class="err">"</span><span class="kt">localhost:</span><span class="err">27017"</span><span class="o">]</span>
</span><span class="line"><span class="n">mongodb</span><span class="o">.</span><span class="n">db</span> <span class="k">=</span> <span class="s">"crowdsource"</span>
</span></code>

Secure Social Configuration

Modifying routes

SecureSocial relys on theses routes to be available for the application.

conf/routes
<span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<code class="scala"><span class="line"><span class="k">#</span> <span class="nc">Login</span> <span class="n">page</span>
</span><span class="line"><span class="nc">GET</span>     <span class="o">/</span><span class="n">login</span>                      <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">LoginPage</span><span class="o">.</span><span class="n">login</span>
</span><span class="line"><span class="nc">GET</span>     <span class="o">/</span><span class="n">logout</span>                     <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">LoginPage</span><span class="o">.</span><span class="n">logout</span>
</span>
<span class="line"><span class="k">#</span> <span class="nc">User</span> <span class="nc">Registration</span> <span class="n">and</span> <span class="n">password</span> <span class="n">handling</span> <span class="o">(</span><span class="n">only</span> <span class="n">needed</span> <span class="k">if</span> <span class="n">you</span> <span class="n">are</span> <span class="n">using</span> <span class="nc">UsernamePasswordProvider</span><span class="o">)</span>
</span><span class="line"><span class="nc">GET</span>     <span class="o">/</span><span class="n">signup</span>                     <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">Registration</span><span class="o">.</span><span class="n">startSignUp</span>
</span><span class="line"><span class="nc">POST</span>    <span class="o">/</span><span class="n">signup</span>                     <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">Registration</span><span class="o">.</span><span class="n">handleStartSignUp</span>
</span><span class="line"><span class="nc">GET</span>     <span class="o">/</span><span class="n">signup</span><span class="o">/:</span><span class="n">token</span>              <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">Registration</span><span class="o">.</span><span class="n">signUp</span><span class="o">(</span><span class="n">token</span><span class="o">)</span>
</span><span class="line"><span class="nc">POST</span>    <span class="o">/</span><span class="n">signup</span><span class="o">/:</span><span class="n">token</span>              <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">Registration</span><span class="o">.</span><span class="n">handleSignUp</span><span class="o">(</span><span class="n">token</span><span class="o">)</span>
</span><span class="line"><span class="nc">GET</span>     <span class="o">/</span><span class="n">reset</span>                      <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">Registration</span><span class="o">.</span><span class="n">startResetPassword</span>
</span><span class="line"><span class="nc">POST</span>    <span class="o">/</span><span class="n">reset</span>                      <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">Registration</span><span class="o">.</span><span class="n">handleStartResetPassword</span>
</span><span class="line"><span class="nc">GET</span>     <span class="o">/</span><span class="n">reset</span><span class="o">/:</span><span class="n">token</span>               <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">Registration</span><span class="o">.</span><span class="n">resetPassword</span><span class="o">(</span><span class="n">token</span><span class="o">)</span>
</span><span class="line"><span class="nc">POST</span>    <span class="o">/</span><span class="n">reset</span><span class="o">/:</span><span class="n">token</span>               <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">Registration</span><span class="o">.</span><span class="n">handleResetPassword</span><span class="o">(</span><span class="n">token</span><span class="o">)</span>
</span><span class="line"><span class="nc">GET</span>     <span class="o">/</span><span class="n">password</span>                   <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">PasswordChange</span><span class="o">.</span><span class="n">page</span>
</span><span class="line"><span class="nc">POST</span>    <span class="o">/</span><span class="n">password</span>                   <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">PasswordChange</span><span class="o">.</span><span class="n">handlePasswordChange</span>
</span>

<span class="line"><span class="k">#</span> <span class="nc">Providers</span> <span class="n">entry</span> <span class="n">points</span>
</span><span class="line"><span class="nc">GET</span>     <span class="o">/</span><span class="n">authenticate</span><span class="o">/:</span><span class="n">provider</span>     <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">ProviderController</span><span class="o">.</span><span class="n">authenticate</span><span class="o">(</span><span class="n">provider</span><span class="o">)</span>
</span><span class="line"><span class="nc">POST</span>    <span class="o">/</span><span class="n">authenticate</span><span class="o">/:</span><span class="n">provider</span>     <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">ProviderController</span><span class="o">.</span><span class="n">authenticateByPost</span><span class="o">(</span><span class="n">provider</span><span class="o">)</span>
</span><span class="line"><span class="nc">GET</span>     <span class="o">/</span><span class="n">not</span><span class="o">-</span><span class="n">authorized</span>             <span class="n">securesocial</span><span class="o">.</span><span class="n">controllers</span><span class="o">.</span><span class="nc">ProviderController</span><span class="o">.</span><span class="n">notAuthorized</span>   
</span></code>

Append to the conf/play.plugins.

In this application we will see how to use the username and password based authentication provided by secure social hence we need to make sure those plugins are properly configured.

conf/play.plugins
<span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<code class="scala"><span class="line"><span class="mi">400</span><span class="k">:</span><span class="kt">play.modules.reactivemongo.ReactiveMongoPlugin</span>
</span><span class="line"><span class="mi">1500</span><span class="k">:</span><span class="kt">com.typesafe.plugin.CommonsMailerPlugin</span>
</span><span class="line"><span class="mi">9994</span><span class="k">:</span><span class="kt">securesocial.core.DefaultAuthenticatorStore</span>
</span><span class="line"><span class="mi">9995</span><span class="k">:</span><span class="kt">securesocial.core.DefaultIdGenerator</span>
</span><span class="line"><span class="mi">9996</span><span class="k">:</span><span class="kt">securesocial.core.providers.utils.DefaultPasswordValidator</span>
</span><span class="line"><span class="mi">9997</span><span class="k">:</span><span class="kt">controllers.plugin.MyViews</span>
</span><span class="line"><span class="mi">9998</span><span class="k">:</span><span class="kt">service.MongoUserService</span>
</span><span class="line"><span class="mi">9999</span><span class="k">:</span><span class="kt">securesocial.core.providers.utils.BCryptPasswordHasher</span>
</span><span class="line"><span class="mi">10004</span><span class="k">:</span><span class="kt">securesocial.core.providers.UsernamePasswordProvider</span> 
</span></code>

For secure social to work we need to make sure we implement the UserService in our case the service.MongoUserService entry for 9998. This is the component which will store the user data, tokens
in MongoDB and retrieve when required.

MongoUserService
<span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
<span class="line-number">34</span>
<span class="line-number">35</span>
<span class="line-number">36</span>
<span class="line-number">37</span>
<span class="line-number">38</span>
<span class="line-number">39</span>
<span class="line-number">40</span>
<span class="line-number">41</span>
<span class="line-number">42</span>
<span class="line-number">43</span>
<span class="line-number">44</span>
<span class="line-number">45</span>
<span class="line-number">46</span>
<span class="line-number">47</span>
<span class="line-number">48</span>
<span class="line-number">49</span>
<span class="line-number">50</span>
<span class="line-number">51</span>
<span class="line-number">52</span>
<span class="line-number">53</span>
<span class="line-number">54</span>
<span class="line-number">55</span>
<span class="line-number">56</span>
<span class="line-number">57</span>
<span class="line-number">58</span>
<span class="line-number">59</span>
<span class="line-number">60</span>
<span class="line-number">61</span>
<span class="line-number">62</span>
<span class="line-number">63</span>
<span class="line-number">64</span>
<span class="line-number">65</span>
<span class="line-number">66</span>
<span class="line-number">67</span>
<span class="line-number">68</span>
<span class="line-number">69</span>
<span class="line-number">70</span>
<span class="line-number">71</span>
<span class="line-number">72</span>
<span class="line-number">73</span>
<span class="line-number">74</span>
<span class="line-number">75</span>
<span class="line-number">76</span>
<span class="line-number">77</span>
<span class="line-number">78</span>
<span class="line-number">79</span>
<span class="line-number">80</span>
<span class="line-number">81</span>
<span class="line-number">82</span>
<span class="line-number">83</span>
<span class="line-number">84</span>
<span class="line-number">85</span>
<span class="line-number">86</span>
<span class="line-number">87</span>
<span class="line-number">88</span>
<span class="line-number">89</span>
<span class="line-number">90</span>
<span class="line-number">91</span>
<span class="line-number">92</span>
<span class="line-number">93</span>
<span class="line-number">94</span>
<span class="line-number">95</span>
<span class="line-number">96</span>
<span class="line-number">97</span>
<span class="line-number">98</span>
<span class="line-number">99</span>
<span class="line-number">100</span>
<span class="line-number">101</span>
<span class="line-number">102</span>
<span class="line-number">103</span>
<span class="line-number">104</span>
<span class="line-number">105</span>
<span class="line-number">106</span>
<span class="line-number">107</span>
<span class="line-number">108</span>
<span class="line-number">109</span>
<span class="line-number">110</span>
<span class="line-number">111</span>
<span class="line-number">112</span>
<span class="line-number">113</span>
<span class="line-number">114</span>
<span class="line-number">115</span>
<span class="line-number">116</span>
<span class="line-number">117</span>
<span class="line-number">118</span>
<span class="line-number">119</span>
<span class="line-number">120</span>
<span class="line-number">121</span>
<span class="line-number">122</span>
<span class="line-number">123</span>
<span class="line-number">124</span>
<span class="line-number">125</span>
<span class="line-number">126</span>
<span class="line-number">127</span>
<span class="line-number">128</span>
<span class="line-number">129</span>
<span class="line-number">130</span>
<span class="line-number">131</span>
<span class="line-number">132</span>
<span class="line-number">133</span>
<span class="line-number">134</span>
<code class="scala"><span class="line"><span class="k">package</span> <span class="nn">service</span>
</span>
<span class="line"><span class="k">import</span> <span class="nn">_root_.java.util.Date</span>
</span><span class="line"><span class="k">import</span> <span class="nn">securesocial.core._</span>
</span><span class="line"><span class="k">import</span> <span class="nn">play.api.</span><span class="o">{</span><span class="nc">Logger</span><span class="o">,</span><span class="nc">Application</span><span class="o">}</span>
</span><span class="line"><span class="k">import</span> <span class="nn">securesocial.core.providers.Token</span>
</span><span class="line"><span class="k">import</span> <span class="nn">play.api.libs.json._</span>
</span><span class="line"><span class="k">import</span> <span class="nn">play.api.libs.json.Reads._</span>
</span><span class="line"><span class="k">import</span> <span class="nn">play.api.libs.json.Writes._</span>
</span><span class="line"><span class="k">import</span> <span class="nn">securesocial.core.IdentityId</span>
</span><span class="line"><span class="k">import</span> <span class="nn">securesocial.core.providers.Token</span>
</span><span class="line"><span class="k">import</span> <span class="nn">play.modules.reactivemongo.MongoController</span>
</span><span class="line"><span class="k">import</span> <span class="nn">play.api.mvc.Controller</span>
</span><span class="line"><span class="k">import</span> <span class="nn">play.modules.reactivemongo.json.collection.JSONCollection</span>
</span><span class="line"><span class="k">import</span> <span class="nn">scala.concurrent.Await</span>
</span><span class="line"><span class="k">import</span> <span class="nn">scala.concurrent.duration._</span>
</span><span class="line"><span class="k">import</span> <span class="nn">reactivemongo.core.commands.GetLastError</span>
</span><span class="line"><span class="k">import</span> <span class="nn">scala.util.parsing.json.JSONObject</span>
</span><span class="line"><span class="k">import</span> <span class="nn">org.joda.time.DateTime</span>
</span><span class="line"><span class="k">import</span> <span class="nn">org.joda.time.format.</span><span class="o">{</span><span class="nc">DateTimeFormatter</span><span class="o">,</span> <span class="nc">DateTimeFormat</span><span class="o">}</span>
</span>
<span class="line"><span class="k">class</span> <span class="nc">MongoUserService</span><span class="o">(</span><span class="n">application</span><span class="k">:</span> <span class="kt">Application</span><span class="o">)</span> <span class="k">extends</span> <span class="nc">UserServicePlugin</span><span class="o">(</span><span class="n">application</span><span class="o">)</span> <span class="k">with</span> <span class="nc">Controller</span> <span class="k">with</span> <span class="nc">MongoController</span><span class="o">{</span>
</span><span class="line">  <span class="k">def</span> <span class="n">collection</span><span class="k">:</span> <span class="kt">JSONCollection</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">collection</span><span class="o">[</span><span class="kt">JSONCollection</span><span class="o">](</span><span class="s">"users"</span><span class="o">)</span>
</span><span class="line">  <span class="k">def</span> <span class="n">tokens</span><span class="k">:</span> <span class="kt">JSONCollection</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">collection</span><span class="o">[</span><span class="kt">JSONCollection</span><span class="o">](</span><span class="s">"tokens"</span><span class="o">)</span>
</span><span class="line">  <span class="k">val</span> <span class="n">outPutUser</span> <span class="k">=</span> <span class="o">(</span><span class="nc">__</span> <span class="o">\</span> <span class="s">"id"</span><span class="o">).</span><span class="n">json</span><span class="o">.</span><span class="n">prune</span>
</span>
<span class="line">  <span class="k">def</span> <span class="n">retIdentity</span><span class="o">(</span><span class="n">json</span> <span class="k">:</span> <span class="kt">JsObject</span><span class="o">)</span> <span class="k">:</span> <span class="kt">Identity</span> <span class="o">=</span> <span class="o">{</span>
</span><span class="line">    <span class="k">val</span> <span class="n">userid</span> <span class="k">=</span> <span class="o">(</span><span class="n">json</span> <span class="o">\</span> <span class="s">"userid"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span>
<span class="line">    <span class="k">val</span> <span class="n">provider</span> <span class="k">=</span> <span class="o">(</span><span class="n">json</span> <span class="o">\</span> <span class="s">"provider"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span><span class="line">    <span class="k">val</span> <span class="n">firstname</span> <span class="k">=</span> <span class="o">(</span><span class="n">json</span> <span class="o">\</span> <span class="s">"firstname"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span><span class="line">    <span class="k">val</span> <span class="n">lastname</span> <span class="k">=</span> <span class="o">(</span><span class="n">json</span> <span class="o">\</span> <span class="s">"lastname"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span><span class="line">    <span class="k">val</span> <span class="n">email</span> <span class="k">=</span> <span class="o">(</span><span class="n">json</span> <span class="o">\</span> <span class="s">"email"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span><span class="line">    <span class="k">val</span> <span class="n">avatar</span> <span class="k">=</span> <span class="o">(</span><span class="n">json</span> <span class="o">\</span> <span class="s">"avatar"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span><span class="line">    <span class="k">val</span> <span class="n">hash</span> <span class="k">=</span> <span class="o">(</span><span class="n">json</span> <span class="o">\</span> <span class="s">"password"</span> <span class="o">\</span> <span class="s">"hasher"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span><span class="line">    <span class="k">val</span> <span class="n">password</span> <span class="k">=</span> <span class="o">(</span> <span class="n">json</span> <span class="o">\</span> <span class="s">"password"</span> <span class="o">\</span> <span class="s">"password"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span><span class="line">    <span class="n">println</span><span class="o">(</span><span class="s">"password : "</span><span class="o">+</span> <span class="n">password</span><span class="o">)</span>
</span><span class="line">    <span class="k">val</span> <span class="n">salt</span> <span class="k">=</span> <span class="o">(</span><span class="n">json</span> <span class="o">\</span> <span class="s">"password"</span> <span class="o">\</span> <span class="s">"salt"</span><span class="o">).</span><span class="n">asOpt</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span><span class="line">    <span class="k">val</span> <span class="n">authmethod</span> <span class="k">=</span> <span class="o">(</span> <span class="n">json</span> <span class="o">\</span> <span class="s">"authmethod"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span>
<span class="line">    <span class="k">val</span> <span class="n">identity</span> <span class="k">:</span> <span class="kt">IdentityId</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">IdentityId</span><span class="o">(</span><span class="n">userid</span><span class="o">,</span><span class="n">authmethod</span><span class="o">)</span>
</span><span class="line">    <span class="k">val</span> <span class="n">authMethod</span> <span class="k">:</span> <span class="kt">AuthenticationMethod</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">AuthenticationMethod</span><span class="o">(</span><span class="n">authmethod</span><span class="o">)</span>
</span><span class="line">    <span class="k">val</span> <span class="n">pwdInfo</span><span class="k">:</span> <span class="kt">PasswordInfo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PasswordInfo</span><span class="o">(</span><span class="n">hash</span><span class="o">,</span><span class="n">password</span><span class="o">)</span>
</span><span class="line">    <span class="k">val</span> <span class="n">user</span> <span class="k">:</span> <span class="kt">SocialUser</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SocialUser</span><span class="o">(</span><span class="n">identity</span><span class="o">,</span><span class="n">firstname</span><span class="o">,</span><span class="n">lastname</span><span class="o">,</span><span class="n">firstname</span><span class="o">,</span><span class="nc">Some</span><span class="o">(</span><span class="n">email</span><span class="o">),</span><span class="nc">Some</span><span class="o">(</span><span class="n">avatar</span><span class="o">),</span><span class="n">authMethod</span><span class="o">,</span><span class="nc">None</span><span class="o">,</span><span class="nc">None</span><span class="o">,</span><span class="nc">Some</span><span class="o">(</span><span class="n">pwdInfo</span><span class="o">))</span>
</span><span class="line">    <span class="n">user</span>
</span><span class="line">  <span class="o">}</span>
</span>
<span class="line">  <span class="k">def</span> <span class="n">findByEmailAndProvider</span><span class="o">(</span><span class="n">email</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span> <span class="n">providerId</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span><span class="k">:</span> <span class="kt">Option</span><span class="o">[</span><span class="kt">Identity</span><span class="o">]</span> <span class="k">=</span> <span class="o">{</span>
</span><span class="line">    <span class="k">val</span> <span class="n">cursor</span>  <span class="k">=</span> <span class="n">collection</span><span class="o">.</span><span class="n">find</span><span class="o">(</span><span class="nc">Json</span><span class="o">.</span><span class="n">obj</span><span class="o">(</span><span class="s">"userid"</span><span class="o">-&gt;</span><span class="n">email</span><span class="o">,</span><span class="s">"provider"</span><span class="o">-&gt;</span><span class="n">providerId</span><span class="o">)).</span><span class="n">cursor</span><span class="o">[</span><span class="kt">JsObject</span><span class="o">]</span>
</span><span class="line">    <span class="k">val</span> <span class="n">futureuser</span> <span class="k">=</span> <span class="n">cursor</span><span class="o">.</span><span class="n">headOption</span><span class="o">.</span><span class="n">map</span><span class="o">{</span>
</span><span class="line">      <span class="k">case</span> <span class="nc">Some</span><span class="o">(</span><span class="n">user</span><span class="o">)</span> <span class="k">=&gt;</span> <span class="n">user</span>
</span><span class="line">      <span class="k">case</span> <span class="nc">None</span> <span class="k">=&gt;</span> <span class="kc">false</span>
</span><span class="line">    <span class="o">}</span>
</span><span class="line">    <span class="k">val</span> <span class="n">jobj</span> <span class="k">=</span> <span class="nc">Await</span><span class="o">.</span><span class="n">result</span><span class="o">(</span><span class="n">futureuser</span><span class="o">,</span> <span class="mi">5</span> <span class="n">seconds</span><span class="o">)</span>
</span><span class="line">    <span class="n">jobj</span> <span class="k">match</span> <span class="o">{</span>
</span><span class="line">      <span class="k">case</span> <span class="n">x</span> <span class="k">:</span> <span class="kt">Boolean</span> <span class="o">=&gt;</span> <span class="nc">None</span>
</span><span class="line">      <span class="k">case</span> <span class="k">_</span>  <span class="k">=&gt;</span> <span class="nc">Some</span><span class="o">(</span><span class="n">retIdentity</span><span class="o">(</span><span class="n">jobj</span><span class="o">.</span><span class="n">asInstanceOf</span><span class="o">[</span><span class="kt">JsObject</span><span class="o">]))</span>
</span>
<span class="line">    <span class="o">}</span>
</span><span class="line">  <span class="o">}</span>
</span>
<span class="line">  <span class="k">def</span> <span class="n">save</span><span class="o">(</span><span class="n">user</span><span class="k">:</span> <span class="kt">Identity</span><span class="o">)</span><span class="k">:</span> <span class="kt">Identity</span> <span class="o">=</span> <span class="o">{</span>
</span>
<span class="line">    <span class="k">val</span> <span class="n">email</span> <span class="k">=</span> <span class="n">user</span><span class="o">.</span><span class="n">email</span> <span class="k">match</span> <span class="o">{</span>
</span><span class="line">      <span class="k">case</span> <span class="nc">Some</span><span class="o">(</span><span class="n">email</span><span class="o">)</span> <span class="k">=&gt;</span> <span class="n">email</span>
</span><span class="line">      <span class="k">case</span> <span class="k">_</span> <span class="k">=&gt;</span> <span class="s">"N/A"</span>
</span><span class="line">    <span class="o">}</span>
</span>
<span class="line">    <span class="k">val</span> <span class="n">avatar</span> <span class="k">=</span> <span class="n">user</span><span class="o">.</span><span class="n">avatarUrl</span> <span class="k">match</span><span class="o">{</span>
</span><span class="line">      <span class="k">case</span> <span class="nc">Some</span><span class="o">(</span><span class="n">url</span><span class="o">)</span> <span class="k">=&gt;</span> <span class="n">url</span>
</span><span class="line">      <span class="k">case</span> <span class="k">_</span> <span class="k">=&gt;</span> <span class="s">"N/A"</span>
</span><span class="line">    <span class="o">}</span>
</span>
<span class="line">    <span class="k">val</span> <span class="n">savejson</span> <span class="k">=</span> <span class="nc">Json</span><span class="o">.</span><span class="n">obj</span><span class="o">(</span>
</span><span class="line">      <span class="s">"userid"</span> <span class="o">-&gt;</span> <span class="n">user</span><span class="o">.</span><span class="n">identityId</span><span class="o">.</span><span class="n">userId</span><span class="o">,</span>
</span><span class="line">      <span class="s">"provider"</span> <span class="o">-&gt;</span> <span class="n">user</span><span class="o">.</span><span class="n">identityId</span><span class="o">.</span><span class="n">providerId</span><span class="o">,</span>
</span><span class="line">      <span class="s">"firstname"</span> <span class="o">-&gt;</span> <span class="n">user</span><span class="o">.</span><span class="n">firstName</span><span class="o">,</span>
</span><span class="line">      <span class="s">"lastname"</span> <span class="o">-&gt;</span> <span class="n">user</span><span class="o">.</span><span class="n">lastName</span><span class="o">,</span>
</span><span class="line">      <span class="s">"email"</span> <span class="o">-&gt;</span> <span class="n">email</span><span class="o">,</span>
</span><span class="line">      <span class="s">"avatar"</span> <span class="o">-&gt;</span> <span class="n">avatar</span><span class="o">,</span>
</span><span class="line">      <span class="s">"authmethod"</span> <span class="o">-&gt;</span> <span class="n">user</span><span class="o">.</span><span class="n">authMethod</span><span class="o">.</span><span class="n">method</span><span class="o">,</span>
</span><span class="line">      <span class="s">"password"</span> <span class="o">-&gt;</span> <span class="nc">Json</span><span class="o">.</span><span class="n">obj</span><span class="o">(</span><span class="s">"hasher"</span> <span class="o">-&gt;</span> <span class="n">user</span><span class="o">.</span><span class="n">passwordInfo</span><span class="o">.</span><span class="n">get</span><span class="o">.</span><span class="n">hasher</span><span class="o">,</span> <span class="s">"password"</span> <span class="o">-&gt;</span> <span class="n">user</span><span class="o">.</span><span class="n">passwordInfo</span><span class="o">.</span><span class="n">get</span><span class="o">.</span><span class="n">password</span><span class="o">,</span> <span class="s">"salt"</span> <span class="o">-&gt;</span> <span class="n">user</span><span class="o">.</span><span class="n">passwordInfo</span><span class="o">.</span><span class="n">get</span><span class="o">.</span><span class="n">salt</span><span class="o">),</span>
</span><span class="line">      <span class="s">"created_at"</span> <span class="o">-&gt;</span> <span class="nc">Json</span><span class="o">.</span><span class="n">obj</span><span class="o">(</span><span class="s">"$date"</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nc">Date</span><span class="o">()),</span>
</span><span class="line">      <span class="s">"updated_at"</span> <span class="o">-&gt;</span> <span class="nc">Json</span><span class="o">.</span><span class="n">obj</span><span class="o">(</span><span class="s">"$date"</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nc">Date</span><span class="o">())</span>
</span><span class="line">    <span class="o">)</span>
</span><span class="line">    <span class="n">println</span><span class="o">(</span><span class="nc">Json</span><span class="o">.</span><span class="n">toJson</span><span class="o">(</span><span class="n">savejson</span><span class="o">))</span>
</span><span class="line">    <span class="n">collection</span><span class="o">.</span><span class="n">insert</span><span class="o">(</span><span class="n">savejson</span><span class="o">)</span>
</span><span class="line">    <span class="n">user</span>
</span><span class="line">  <span class="o">}</span>
</span>
<span class="line">  <span class="k">def</span> <span class="n">find</span><span class="o">(</span><span class="n">id</span><span class="k">:</span> <span class="kt">IdentityId</span><span class="o">)</span><span class="k">:</span> <span class="kt">Option</span><span class="o">[</span><span class="kt">Identity</span><span class="o">]</span> <span class="k">=</span> <span class="o">{</span>
</span><span class="line">   <span class="n">findByEmailAndProvider</span><span class="o">(</span><span class="n">id</span><span class="o">.</span><span class="n">userId</span><span class="o">,</span><span class="n">id</span><span class="o">.</span><span class="n">providerId</span><span class="o">)</span>
</span><span class="line">  <span class="o">}</span>
</span>
<span class="line">  <span class="k">def</span> <span class="n">save</span><span class="o">(</span><span class="n">token</span><span class="k">:</span> <span class="kt">Token</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line">    <span class="k">val</span> <span class="n">tokentosave</span> <span class="k">=</span> <span class="nc">Json</span><span class="o">.</span><span class="n">obj</span><span class="o">(</span>
</span><span class="line">      <span class="s">"uuid"</span> <span class="o">-&gt;</span> <span class="n">token</span><span class="o">.</span><span class="n">uuid</span><span class="o">,</span>
</span><span class="line">      <span class="s">"email"</span> <span class="o">-&gt;</span> <span class="n">token</span><span class="o">.</span><span class="n">email</span><span class="o">,</span>
</span><span class="line">      <span class="s">"creation_time"</span> <span class="o">-&gt;</span> <span class="nc">Json</span><span class="o">.</span><span class="n">obj</span><span class="o">(</span><span class="s">"$date"</span> <span class="o">-&gt;</span> <span class="n">token</span><span class="o">.</span><span class="n">creationTime</span><span class="o">),</span>
</span><span class="line">      <span class="s">"expiration_time"</span> <span class="o">-&gt;</span> <span class="nc">Json</span><span class="o">.</span><span class="n">obj</span><span class="o">(</span><span class="s">"$date"</span> <span class="o">-&gt;</span> <span class="n">token</span><span class="o">.</span><span class="n">expirationTime</span><span class="o">),</span>
</span><span class="line">      <span class="s">"isSignUp"</span> <span class="o">-&gt;</span> <span class="n">token</span><span class="o">.</span><span class="n">isSignUp</span>
</span><span class="line">    <span class="o">)</span>
</span><span class="line">    <span class="n">tokens</span><span class="o">.</span><span class="n">save</span><span class="o">(</span><span class="n">tokentosave</span><span class="o">)</span>
</span><span class="line">  <span class="o">}</span>
</span>


<span class="line">  <span class="k">def</span> <span class="n">findToken</span><span class="o">(</span><span class="n">token</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span><span class="k">:</span> <span class="kt">Option</span><span class="o">[</span><span class="kt">Token</span><span class="o">]</span> <span class="k">=</span> <span class="o">{</span>
</span>
<span class="line">     <span class="k">val</span> <span class="n">cursor</span>  <span class="k">=</span> <span class="n">tokens</span><span class="o">.</span><span class="n">find</span><span class="o">(</span><span class="nc">Json</span><span class="o">.</span><span class="n">obj</span><span class="o">(</span><span class="s">"uuid"</span><span class="o">-&gt;</span><span class="n">token</span><span class="o">)).</span><span class="n">cursor</span><span class="o">[</span><span class="kt">JsObject</span><span class="o">]</span>
</span><span class="line">      <span class="k">val</span> <span class="n">futureuser</span> <span class="k">=</span> <span class="n">cursor</span><span class="o">.</span><span class="n">headOption</span><span class="o">.</span><span class="n">map</span><span class="o">{</span>
</span><span class="line">        <span class="k">case</span> <span class="nc">Some</span><span class="o">(</span><span class="n">user</span><span class="o">)</span> <span class="k">=&gt;</span> <span class="n">user</span>
</span><span class="line">        <span class="k">case</span> <span class="nc">None</span> <span class="k">=&gt;</span> <span class="kc">false</span>
</span><span class="line">     <span class="o">}</span>
</span><span class="line">      <span class="k">val</span> <span class="n">jobj</span> <span class="k">=</span> <span class="nc">Await</span><span class="o">.</span><span class="n">result</span><span class="o">(</span><span class="n">futureuser</span><span class="o">,</span> <span class="mi">5</span> <span class="n">seconds</span><span class="o">)</span>
</span><span class="line">      <span class="n">jobj</span> <span class="k">match</span> <span class="o">{</span>
</span><span class="line">        <span class="k">case</span> <span class="n">x</span> <span class="k">:</span> <span class="kt">Boolean</span> <span class="o">=&gt;</span> <span class="nc">None</span>
</span><span class="line">        <span class="k">case</span> <span class="n">obj</span><span class="k">:</span><span class="kt">JsObject</span>  <span class="o">=&gt;{</span>
</span><span class="line">          <span class="n">println</span><span class="o">(</span><span class="n">obj</span><span class="o">)</span>
</span><span class="line">          <span class="k">val</span> <span class="n">uuid</span> <span class="k">=</span> <span class="o">(</span> <span class="n">obj</span> <span class="o">\</span> <span class="s">"uuid"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span><span class="line">          <span class="k">val</span> <span class="n">email</span> <span class="k">=</span> <span class="o">(</span><span class="n">obj</span> <span class="o">\</span> <span class="s">"email"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span>
</span><span class="line">          <span class="k">val</span> <span class="n">created</span> <span class="k">=</span> <span class="o">(</span><span class="n">obj</span> <span class="o">\</span> <span class="s">"creation_time"</span> <span class="o">\</span> <span class="s">"$date"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">Long</span><span class="o">]</span>
</span><span class="line">          <span class="k">val</span> <span class="n">expire</span> <span class="k">=</span> <span class="o">(</span><span class="n">obj</span> <span class="o">\</span> <span class="s">"expiration_time"</span> <span class="o">\</span> <span class="s">"$date"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">Long</span><span class="o">]</span>
</span><span class="line">          <span class="k">val</span> <span class="n">signup</span> <span class="k">=</span> <span class="o">(</span><span class="n">obj</span> <span class="o">\</span> <span class="s">"isSignUp"</span><span class="o">).</span><span class="n">as</span><span class="o">[</span><span class="kt">Boolean</span><span class="o">]</span>
</span><span class="line">          <span class="k">val</span> <span class="n">df</span> <span class="k">=</span> <span class="nc">DateTimeFormat</span><span class="o">.</span><span class="n">forPattern</span><span class="o">(</span><span class="s">"yyyy-MM-dd HH:mm:ss"</span><span class="o">)</span>
</span><span class="line">          <span class="nc">Some</span><span class="o">(</span><span class="k">new</span> <span class="nc">Token</span><span class="o">(</span><span class="n">uuid</span><span class="o">,</span><span class="n">email</span><span class="o">,</span><span class="k">new</span> <span class="nc">DateTime</span><span class="o">(</span><span class="n">created</span><span class="o">),</span><span class="k">new</span> <span class="nc">DateTime</span><span class="o">(</span><span class="n">expire</span><span class="o">),</span><span class="n">signup</span><span class="o">))</span>
</span><span class="line">        <span class="o">}</span>
</span><span class="line">      <span class="o">}</span>
</span><span class="line">  <span class="o">}</span>
</span>
<span class="line">  <span class="k">def</span> <span class="n">deleteToken</span><span class="o">(</span><span class="n">uuid</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="o">{}</span>
</span>
<span class="line">  <span class="k">def</span> <span class="n">deleteExpiredTokens</span><span class="o">()</span> <span class="o">{}</span>
</span><span class="line"><span class="o">}</span>  
</span></code>

The above code implements the MongoControllers which provides with helpers to interact with
MongoDB as Json Documents instead of BSONDocuments.

This would be our simple SecureSocial Application Controller where the index action need to be authenticated.

Application.scala
<span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<code class="scala"><span class="line"><span class="k">object</span> <span class="nc">Application</span> <span class="k">extends</span> <span class="nc">Controller</span>  <span class="k">with</span> <span class="nc">SecureSocial</span><span class="o">{</span>
</span><span class="line">  <span class="k">def</span> <span class="n">index</span> <span class="k">=</span> <span class="nc">SecuredAction</span> <span class="o">{</span> <span class="k">implicit</span>  <span class="n">request</span> <span class="k">=&gt;</span>
</span><span class="line">    <span class="nc">Ok</span><span class="o">(</span><span class="n">views</span><span class="o">.</span><span class="n">html</span><span class="o">.</span><span class="n">index</span><span class="o">(</span><span class="n">request</span><span class="o">.</span><span class="n">user</span><span class="o">))</span>
</span><span class="line">  <span class="o">}</span>
</span><span class="line"><span class="o">}</span>
</span></code>

All the necessary code can be found on Github

About the author

Shrikar

Backend/Infrastructure Engineer by Day. iOS Developer for the rest of the time.

  • Ahmad El-Melegy

    Thanks for the great tutorial but it seems that there is something wrong with the css of the site, that make me not able to read the codes. Please can you fix it ?

/* ]]> */