Identity

Silhouette defines a user through its Identity trait. This trait doesn’t define any defaults expect the Login information which contains the data about the provider that authenticated that identity. This login information must be stored with the identity. 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 login information gets stored separately. Later you can see how this can be implemented.

Implement an identity

As pointed out in the introduction of this chapter a user is an representation of an Identity. So to define a user you must create a class that extends the Identity trait. Your user can contain any information. There are no restrictions how a user must be constructed.

Below we define a simple user with a unique ID, the login information for the provider which authenticates that user and some basic information like name and email.

case class User(,
  userID: Long,
  loginInfo: LoginInfo,
  name: String,
  email: Option[String]) extends Identity

The identity service

Silhouette relies on an implementation of IdentityService to handle all the operations related to retrieving identities. Using this delegation model you are not forced to use a particular model object or a persistence mechanism but rather provide a service that translates back and forth between your models and what Silhouette understands.

The IdentityService defines a raw type which must be derived from Identity. This has the advantage that your service implementation returns always your implemented Identity.

Let’s illustrate how a user defined implementation can look like:

/**
 * A custom user service which relies on the previous defined `User`.
 */
class UserService(userDAO: UserDAO) extends IdentityService[User] {

  /**
   * Retrieves a user that matches the specified login info.
   *
   * @param loginInfo The login info to retrieve a user.
   * @return The retrieved user or None if no user could be retrieved for the given login info.
   */
  def retrieve(loginInfo: LoginInfo): Future[Option[User]] = userDAO.findByLoginInfo(loginInfo)
}