Skip to content
This repository has been archived by the owner on Sep 12, 2021. It is now read-only.

Commit

Permalink
Merge pull request #104 from akkie/master
Browse files Browse the repository at this point in the history
Add marker trait for AuthInfo
  • Loading branch information
fernandoacorreia committed Feb 12, 2014
2 parents 0976f65 + 5f16014 commit 189f061
Show file tree
Hide file tree
Showing 15 changed files with 478 additions and 21 deletions.
43 changes: 43 additions & 0 deletions app/com/mohiva/play/silhouette/contrib/daos/OAuth1InfoDAO.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright 2014 Mohiva Organisation (license at mohiva dot com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mohiva.play.silhouette.contrib.daos

import com.mohiva.play.silhouette.core.LoginInfo
import com.mohiva.play.silhouette.core.providers.OAuth1Info
import scala.concurrent.Future

/**
* The DAO to store the OAuth1 information.
*/
trait OAuth1InfoDAO {

/**
* Saves the OAuth1 info.
*
* @param loginInfo The login info for which the auth info should be saved.
* @param authInfo The OAuth1 info to save.
* @return The saved OAuth1 info or None if the OAuth1 info couldn't be saved.
*/
def save(loginInfo: LoginInfo, authInfo: OAuth1Info): Future[Option[OAuth1Info]]

/**
* Finds the OAuth1 info which is linked with the specified login info.
*
* @param loginInfo The linked login info.
* @return The retrieved OAuth1 info or None if no OAuth1 info could be retrieved for the given login info.
*/
def find(loginInfo: LoginInfo): Future[Option[OAuth1Info]]
}
43 changes: 43 additions & 0 deletions app/com/mohiva/play/silhouette/contrib/daos/OAuth2InfoDAO.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright 2014 Mohiva Organisation (license at mohiva dot com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mohiva.play.silhouette.contrib.daos

import com.mohiva.play.silhouette.core.LoginInfo
import com.mohiva.play.silhouette.core.providers.OAuth2Info
import scala.concurrent.Future

/**
* The DAO to store the OAuth2 information.
*/
trait OAuth2InfoDAO {

/**
* Saves the OAuth2 info.
*
* @param loginInfo The login info for which the auth info should be saved.
* @param authInfo The OAuth2 info to save.
* @return The saved OAuth2 info or None if the OAuth2 info couldn't be saved.
*/
def save(loginInfo: LoginInfo, authInfo: OAuth2Info): Future[Option[OAuth2Info]]

/**
* Finds the OAuth2 info which is linked with the specified login info.
*
* @param loginInfo The linked login info.
* @return The retrieved OAuth2 info or None if no OAuth2 info could be retrieved for the given login info.
*/
def find(loginInfo: LoginInfo): Future[Option[OAuth2Info]]
}
43 changes: 43 additions & 0 deletions app/com/mohiva/play/silhouette/contrib/daos/PasswordInfoDAO.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright 2014 Mohiva Organisation (license at mohiva dot com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mohiva.play.silhouette.contrib.daos

import com.mohiva.play.silhouette.core.LoginInfo
import com.mohiva.play.silhouette.core.providers.PasswordInfo
import scala.concurrent.Future

/**
* The DAO to store the password information.
*/
trait PasswordInfoDAO {

/**
* Saves the password info.
*
* @param loginInfo The login info for which the auth info should be saved.
* @param authInfo The password info to save.
* @return The saved password info or None if the password info couldn't be saved.
*/
def save(loginInfo: LoginInfo, authInfo: PasswordInfo): Future[Option[PasswordInfo]]

/**
* Finds the password info which is linked with the specified login info.
*
* @param loginInfo The linked login info.
* @return The retrieved password info or None if no password info could be retrieved for the given login info.
*/
def find(loginInfo: LoginInfo): Future[Option[PasswordInfo]]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* Copyright 2014 Mohiva Organisation (license at mohiva dot com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mohiva.play.silhouette.contrib.services

import javax.inject.Inject
import scala.reflect.ClassTag
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import com.mohiva.play.silhouette.core.LoginInfo
import com.mohiva.play.silhouette.core.services.{ AuthInfo, AuthInfoService }
import com.mohiva.play.silhouette.core.providers.{ OAuth2Info, OAuth1Info, PasswordInfo }
import com.mohiva.play.silhouette.contrib.daos.{ OAuth2InfoDAO, OAuth1InfoDAO, PasswordInfoDAO }
import DefaultAuthInfoService._

/**
* An implementation of the auth info service which stores the different auth info instances with the help of
* different DAOs.
*
* Due the nature of the different auth information it is hard to persist the data in a single data structure,
* expect the data gets stored in a serialized format. With this implementation it is possible to store the
* different auth info in different backing stores. If we speak of a relational database, then the auth info
* can be stored in different tables. And the tables represents the internal data structure of each auth info
* object.
*
* @param passwordInfoDAO The password info DAO implementation.
* @param oauth1InfoDAO The OAuth1 info DAO implementation.
* @param oauth2InfoDAO The OAuth2 info DAO implementation.
*/
class DefaultAuthInfoService @Inject() (
passwordInfoDAO: PasswordInfoDAO,
oauth1InfoDAO: OAuth1InfoDAO,
oauth2InfoDAO: OAuth2InfoDAO) extends AuthInfoService {

/**
* Saves auth info.
*
* This method gets called when a user logs in(social auth) or registers. This is the change
* to persist the auth info for a provider in the backing store. If the application supports
* the concept of "merged identities", i.e., the same user being able to authenticate through
* different providers, then make sure that the auth info for every linked login info gets
* stored separately.
*
* @param loginInfo The login info for which the auth info should be saved.
* @param authInfo The auth info to save.
* @return The saved auth info or None if the auth info couldn't be saved.
*/
def save[T <: AuthInfo](loginInfo: LoginInfo, authInfo: T): Future[Option[T]] = authInfo match {
case a: PasswordInfo => passwordInfoDAO.save(loginInfo, a).map(_.map(_.asInstanceOf[T]))
case a: OAuth1Info => oauth1InfoDAO.save(loginInfo, a).map(_.map(_.asInstanceOf[T]))
case a: OAuth2Info => oauth2InfoDAO.save(loginInfo, a).map(_.map(_.asInstanceOf[T]))
case a => throw new Exception(SaveError.format(a.getClass))
}

/**
* Retrieves the auth info which is linked with the specified login info.
*
* @param loginInfo The linked login info.
* @param tag The class tag of the auth info.
* @return The retrieved auth info or None if no auth info could be retrieved for the given login info.
*/
def retrieve[T <: AuthInfo](loginInfo: LoginInfo)(implicit tag: ClassTag[T]): Future[Option[T]] = tag match {
case a if a.runtimeClass == classOf[PasswordInfo] => passwordInfoDAO.find(loginInfo).map(_.map(_.asInstanceOf[T]))
case a if a.runtimeClass == classOf[OAuth1Info] => oauth1InfoDAO.find(loginInfo).map(_.map(_.asInstanceOf[T]))
case a if a.runtimeClass == classOf[OAuth2Info] => oauth2InfoDAO.find(loginInfo).map(_.map(_.asInstanceOf[T]))
case a => throw new Exception(RetrieveError.format(a.runtimeClass))
}
}

/**
* The companion object.
*/
object DefaultAuthInfoService {

/**
* The error messages.
*/
val SaveError = "Cannot save auth info of type: %s"
val RetrieveError = "Cannot search for auth info of type: %s"
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
*/
package com.mohiva.play.silhouette.contrib.utils

import com.mohiva.play.silhouette.core.utils.{ PasswordInfo, PasswordHasher }
import com.mohiva.play.silhouette.core.utils.PasswordHasher
import com.mohiva.play.silhouette.core.providers.PasswordInfo
import org.mindrot.jbcrypt.BCrypt
import BCryptPasswordHasher._

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ package com.mohiva.play.silhouette.core.providers
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import com.mohiva.play.silhouette.core._
import com.mohiva.play.silhouette.core.services.AuthInfoService
import com.mohiva.play.silhouette.core.utils.{ PasswordHasher, PasswordInfo }
import com.mohiva.play.silhouette.core.services.{ AuthInfo, AuthInfoService }
import com.mohiva.play.silhouette.core.utils.PasswordHasher

/**
* A provider for authenticating with credentials.
Expand Down Expand Up @@ -86,3 +86,12 @@ object CredentialsProvider {
* @param password The password to authenticate with.
*/
case class Credentials(identifier: String, password: String)

/**
* The password details.
*
* @param hasher The ID of the hasher used to hash this password.
* @param password The hashed password.
* @param salt The optional salt used when hashing.
*/
case class PasswordInfo(hasher: String, password: String, salt: Option[String] = None) extends AuthInfo
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{ Success, Failure, Try }
import com.mohiva.play.silhouette.core._
import com.mohiva.play.silhouette.core.utils.{ HTTPLayer, CacheLayer }
import com.mohiva.play.silhouette.core.services.AuthInfo
import OAuth1Provider._

/**
Expand Down Expand Up @@ -193,4 +194,4 @@ case class OAuth1Settings(
* @param token The consumer token.
* @param secret The consumer secret.
*/
case class OAuth1Info(token: String, secret: String)
case class OAuth1Info(token: String, secret: String) extends AuthInfo
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import play.api.libs.functional.syntax._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import com.mohiva.play.silhouette.core.utils.{ HTTPLayer, CacheLayer }
import com.mohiva.play.silhouette.core.services.AuthInfo
import com.mohiva.play.silhouette.core._
import OAuth2Provider._

Expand Down Expand Up @@ -236,4 +237,4 @@ case class OAuth2Info(
accessToken: String,
tokenType: Option[String] = None,
expiresIn: Option[Int] = None,
refreshToken: Option[String] = None)
refreshToken: Option[String] = None) extends AuthInfo
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@
*/
package com.mohiva.play.silhouette.core.providers

import play.api.mvc.{ SimpleResult, RequestHeader }
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.mvc.{ SimpleResult, RequestHeader }
import com.mohiva.play.silhouette.core.{ LoginInfo, Provider }
import com.mohiva.play.silhouette.core.services.AuthInfoService
import com.mohiva.play.silhouette.core.services.{ AuthInfo, AuthInfoService }

/**
* The base interface for all social providers.
*
* @tparam A The type of the auth info.
*/
trait SocialProvider[A] extends Provider {
trait SocialProvider[A <: AuthInfo] extends Provider {

/**
* Authenticates the user and fills the profile information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/
package com.mohiva.play.silhouette.core.services

import scala.reflect.ClassTag
import scala.concurrent.Future
import com.mohiva.play.silhouette.core.LoginInfo

Expand All @@ -41,13 +42,19 @@ trait AuthInfoService {
* @param authInfo The auth info to save.
* @return The saved auth info or None if the auth info couldn't be saved.
*/
def save[T](loginInfo: LoginInfo, authInfo: T): Future[Option[T]]
def save[T <: AuthInfo](loginInfo: LoginInfo, authInfo: T): Future[Option[T]]

/**
* Retrieves the auth info which is linked with the specified login info.
*
* @param loginInfo The linked login info.
* @param tag The class tag of the auth info.
* @return The retrieved auth info or None if no auth info could be retrieved for the given login info.
*/
def retrieve[T](loginInfo: LoginInfo): Future[Option[T]]
def retrieve[T <: AuthInfo](loginInfo: LoginInfo)(implicit tag: ClassTag[T]): Future[Option[T]]
}

/**
* A marker trait for authentication information.
*/
trait AuthInfo
11 changes: 2 additions & 9 deletions app/com/mohiva/play/silhouette/core/utils/PasswordHasher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
*/
package com.mohiva.play.silhouette.core.utils

import com.mohiva.play.silhouette.core.providers.PasswordInfo

/**
* A trait that defines the password hasher interface.
*/
Expand Down Expand Up @@ -48,12 +50,3 @@ trait PasswordHasher {
*/
def matches(passwordInfo: PasswordInfo, suppliedPassword: String): Boolean
}

/**
* The password details.
*
* @param hasher The ID of the hasher used to hash this password.
* @param password The hashed password.
* @param salt The optional salt used when hashing.
*/
case class PasswordInfo(hasher: String, password: String, salt: Option[String] = None)
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ licenses := Seq("Apache License" -> url("https://github.com/mohiva/play-silhouet
libraryDependencies ++= Seq(
cache,
"org.mindrot" % "jbcrypt" % "0.3m",
"javax.inject" % "javax.inject" % "1",
"org.mockito" % "mockito-core" % "1.9.5" % "test"
)

Expand Down

0 comments on commit 189f061

Please sign in to comment.