Checking for multiple identities while user is signing up?


#1

Is multiple identifiers for a single user like username and email id possible?


#2

Hi,

yes this is possible. You can override the CredentialsProvider.loginInfo method to fetch the LoginInfo based on the entered credentials.

Best regards,
Christian


#3

@akkie Can you provide me a sample code for this.


#4

Silhouette uses the LoginInfo do identify users among different authentication providers. The LoginInfo consists of the provider that has authenticated the user and a unique identifier for that user. In the seed templates we use the email address as identifier. In your case you must use the user ID as identifier.

import com.mohiva.play.silhouette.api.LoginInfo
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.util.{ Credentials, PasswordHasherRegistry }
import com.mohiva.play.silhouette.impl.exceptions.IdentityNotFoundException
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import core.models.User
import javax.inject.Inject

import scala.concurrent.{ ExecutionContext, Future }

class CustomCredentialsProvider @Inject() (
  override val authInfoRepository: AuthInfoRepository,
  override val passwordHasherRegistry: PasswordHasherRegistry,
  val identityFetcher: String => Future[Option[User]]
)(
  implicit
  override val executionContext: ExecutionContext
) extends CredentialsProvider(authInfoRepository, passwordHasherRegistry) {

  override def loginInfo(credentials: Credentials): Future[LoginInfo] = {
    val emailOrUsername = credentials.identifier
    identityFetcher(emailOrUsername).map {
      // Couldn't determine a user for the given data, so we throw an IdentityNotFoundException
      case None => throw new IdentityNotFoundException(
        s"Couldn't found identity for entered value: $emailOrUsername"
      )
      // If a user was found, then we use the user ID as identifier
      case Some(user) => LoginInfo(id, user.id.stringify)
    }
  }
}

You can then use this provider instead of the CredentialsProvider.

Hope that helps.

Best regards,
Christian


#5

Thanks @akkie, for your answer, but i wanted to ask like in login info we are using email or username as identfiier, can we use both email and username ss identfiier.


#6

Sure, the identifier is freely selectable. But it isn’t needed in your case. With the code I’ve posted you can login with a username or email. But the unique value for a user is the ID, so you should pass this around instead of using a concatenated string consisting of the username and email. Also, If you use the email in the login info, then you must update the email address in the login info, after a user has changed its email address. If you use the user ID then you don’t have this additional step.