Silhouette is an authentication library for Play Framework applications that supports several authentication methods, including OAuth1, OAuth2, OpenID, Credentials or custom authentication schemes.
akkie on master
Update README.md (compare)
akkie on master
Update README.md (compare)
akkie on gh-pages
updated site (compare)
akkie on gh-pages
updated site (compare)
akkie on gh-pages
updated site (compare)
akkie on master
Fixed Auth0ProfileParser to get… (compare)
akkie on gh-pages
updated site (compare)
akkie on gh-pages
updated site (compare)
https://github.com/CollegeBoreal/play-silhouette-slick-mysql.g8
I am upgrading this g8 project to Play 2.7.3 supports Scala 2.13.0 but I am having classTag
issue with the new DelegableAuthInfoDAO trait
play-silhouette-slick-mysql/app/daos/password/PasswordDAO.scala:16:7: class PasswordDAO needs to be abstract. Missing implementation for:
[error] val classTag: scala.reflect.ClassTag[com.mohiva.play.silhouette.api.util.PasswordInfo] // inherited from trait DelegableAuthInfoDAO
A follow up to my question, I instantiate the Password DAO using the below Injection scheme in Silhouette 5.0.3
@Singleton
class PasswordDAO @Inject()(
protected val dbConfigProvider: DatabaseConfigProvider,
loginDao: LoginDAO)(implicit executionContext: ExecutionContext)
extends DelegableAuthInfoDAO[PasswordInfo]
with PasswordDTO
with HasDatabaseConfigProvider[JdbcProfile] {
...
The Silhouette Module Binding follows the below snippet
class SilhouetteModule extends AbstractModule with ScalaModule {
override def configure(): Unit = {
...
// @provides provideAuthInfoRepository
bind[DelegableAuthInfoDAO[PasswordInfo]].to[PasswordDAO]
}
Unfortunately, the new DelegableAuthInfoDAO trait doesn't seem to allow the same instantiation.
val silhouetteVersion = "6.0.1"
trait DelegableAuthInfoDAO[T <: AuthInfo] extends AuthInfoDAO[T] {
/**
* The class tag for the type parameter.
*/
val classTag: ClassTag[T]
}
The previous DelegableAuthInfoDAO implementation used an abstract class.
val silhouetteVersion = "5.0.3"
abstract class DelegableAuthInfoDAO[T <: AuthInfo](implicit val classTag: ClassTag[T]) extends AuthInfoDAO[T]
What would be the new way to instantiate PasswordDAO?
I looked into the Change Log and couldn't find any new explanation regarding the new trait implementation.
Let me know if the chat is not the place to talk about this item, I will move it to the forum. Thanks, and please help
@akkie yes, I do get a compile Error
play-silhouette-slick-mysql/app/daos/password/PasswordDAO.scala:16:7: class PasswordDAO needs to be abstract. Missing implementation for:
[error] val classTag: scala.reflect.ClassTag[com.mohiva.play.silhouette.api.util.PasswordInfo] // inherited from trait DelegableAuthInfoDAO
I then tried to mimic InMemoryAuthInfoDAO
override def configure(): Unit = {
...
bind[DelegableAuthInfoDAO[PasswordInfo]]
.toInstance(new PasswordDAO[PasswordInfo])
}
But it looks like I need to use .toInstance to create a new DelegableAuthInfoDAO
That doesn't sit well with the Injected dbConfig
class PasswordDAO[T <: AuthInfo] @Inject()(
protected val dbConfigProvider: DatabaseConfigProvider,
loginDao: LoginDAO)(implicit val classTag: ClassTag[T])
extends DelegableAuthInfoDAO[T]
with PasswordDTO
with HasDatabaseConfigProvider[JdbcProfile] {
...
any workaround?
@akkie Thanks, I will look into the Provider solution from the seed.
A DAO's snippet below but you can find the entire gitter8 template here
https://github.com/CollegeBoreal/play-silhouette-slick-mysql.g8
@Singleton
class PasswordDAO @Inject()(
protected val dbConfigProvider: DatabaseConfigProvider,
loginDao: LoginDAO)(implicit executionContext: ExecutionContext)
extends DelegableAuthInfoDAO[PasswordInfo]
with PasswordDTO
with HasDatabaseConfigProvider[JdbcProfile] {
import profile.api._
val passwords = lifted.TableQuery[PasswordTable]
def getAll: Future[Seq[Password]] = db.run(passwords.result)
override def find(loginInfo: LoginInfo): Future[Option[PasswordInfo]] =
db.run {
for {
Some(fields) <- passwords
.filter(_.password === loginInfo.providerKey)
.result
.map(_.headOption)
} yield
Some(
PasswordInfo(hasher = fields.hasher,
password = fields.secret,
salt = fields.salt))
}
...
To start a new project: (using play-2.7, scala 2.13 and latest Silhouette) not working
$ sbt new CollegeBoreal/play-silhouette-slick-mysql.g8
The previous SIlhouette 5.03 version
$ sbt new CollegeBoreal/play-silhouette-slick-mysql.g8 --branch play-2.6
class PasswordDAO[T <: AuthInfo] @Inject() (
protected val dbConfigProvider: DatabaseConfigProvider,
loginDao: LoginDAO
)(
implicit
val classTag: ClassTag[T],
executionContext: ExecutionContext
) extends DelegableAuthInfoDAO[T]
with PasswordDTO
with HasDatabaseConfigProvider[JdbcProfile] {
Doesn't work if you use:bind[DelegableAuthInfoDAO[PasswordInfo]].to[PasswordDAO]
T
isn't really needed here:class PasswordDAO @Inject() (
protected val dbConfigProvider: DatabaseConfigProvider,
loginDao: LoginDAO
)(
implicit
val classTag: ClassTag[PasswordInfo],
executionContext: ExecutionContext
) extends DelegableAuthInfoDAO[PasswordInfo]
with PasswordDTO
with HasDatabaseConfigProvider[JdbcProfile] {
[error] application -
! @7cm23k6mg - Internal server error, for (GET) [/] ->
play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:
1) No implementation for scala.reflect.ClassTag<com.mohiva.play.silhouette.api.util.PasswordInfo> was bound.
while locating scala.reflect.ClassTag<com.mohiva.play.silhouette.api.util.PasswordInfo>
for the 3rd parameter of daos.password.PasswordDAO.<init>(PasswordDAO.scala:18)
at modules.SilhouetteModule.configure(SilhouetteModule.scala:78) (via modules: com.google.inject.util.Modules$OverrideModule -> modules.SilhouetteModule)
Hi, now I’m implementing a play-silhouette OAuth2 and a Vue.js project.
I’m trying to redirect from the playframework project to the Vue.js project after successing authentication.
But, I cannot handle JWT of the play project on the Vue.js project.
Is there any good way to get X-Auth-Token
on Vue.js project.
If I can, I want to use OAuth2 without redirect
.
@akkie
Thank you, I want to like the above.
authenticate
method.
@akkie
Thank you!
I tried the above way,
However, when the provider redirects to the silhouette endpoint,
silhouette module showed the following errors.
[/authenticate/google] ->
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[CryptoException: [Silhouette][JcaSigner] Invalid message format; Expected [VERSION]-[SIGNATURE]-[DATA]]]
@akkie
My silhouette.conf
settings is below.
Should we change from secureCookie
false to true (even if I use JWT..) ?
# CSRF state item handler settings
csrfStateItemHandler.cookieName="OAuth2State"
csrfStateItemHandler.cookiePath="/"
csrfStateItemHandler.secureCookie=false // Disabled for testing on localhost without SSL, otherwise cookie couldn't be set
csrfStateItemHandler.httpOnlyCookie=true
csrfStateItemHandler.expirationTime=5 minutes
This will not work with your scenario!
Oh.. I only want to get code
from the provider and publish login event on silhouette middleware..
If Silhouette initiates the OAuth2 flow, then it sends a token in the OAuth2 state param. And in the second step it validates the token.
Thank you.
So, should I change like the following way.
# CSRF state item handler settings
csrfStateItemHandler.cookieName="OAuth2State"
csrfStateItemHandler.cookiePath="/"
csrfStateItemHandler.secureCookie=false // Disabled for testing on localhost without SSL, otherwise cookie couldn't be set
csrfStateItemHandler.httpOnlyCookie=false
csrfStateItemHandler.expirationTime=5 minutes
SilhouetteModule.scala
like below. @Provides
def provideSocialStateHandler(
@Named("social-state-signer") signer: Signer,
csrfStateItemHandler: CsrfStateItemHandler): SocialStateHandler = {
// new DefaultSocialStateHandler(Set(csrfStateItemHandler), signer)
new DefaultSocialStateHandler(Set(), signer)
}
const code = this.$route.query.code
const scope = this.$route.query.scope
const targetUrl = `http://localhost:9000/authenticate/google`
const params = {
code: code,
scope: scope
}
axios.post(targetUrl, params, (response) => {
console.log(response)
}, (error) => {
console.error(error)
})
com.mohiva.play.silhouette.impl.exceptions.UnexpectedResponseException: [Silhouette][google] Got unexpected response `{
"error": "invalid_grant",
"error_description": "Bad Request"
}`; status code: 400
Thank you, I succeeded sign in,
from vue.js https://accounts.google.com/o/oauth2/auth?response_type=code
and redirect to localhost:9000/authenticate/google
from the provider.
and I can go to the Vue.js project like the following way, but how can I pass the token…? currently I do by queryString
like ?token=……
.
result <- silhouette.env.authenticatorService.embed(
token,
Redirect(s"http://localhost:3000?token=${token}")
Redirect
is a Play Result implementation. You should have the same API to send cookies, headers, ...
Hi @akkie ,
I followed the migration guide but running into another issue.
I removed the bind and added the provider
override def configure(): Unit = {
...
// set your own Environment [Type]
bind[Silhouette[DefaultEnv]].to[SilhouetteProvider[DefaultEnv]]
// @provides provideEnvironment [Implementation]
bind[IdentityService[User]].to[UserDAO]
// @provides provideAuthenticatorService
bind[AuthenticatorRepository[JWTAuthenticator]].to[AuthenticatorDAO]
}
@Provides
def providePasswordDAO(dbConfigProvider: DatabaseConfigProvider,
loginDao: LoginDAO): PasswordDAO =
new PasswordDAO(dbConfigProvider, loginDao)
The project compiles but the AuthInfoRepository
provider doesn't seem to find the DelegableAuthInfoDAO[PasswordInfo]
provider
/**
* Provides the auth info repository.
*
* @param passwordInfoDAO The implementation of the delegable password auth info DAO.
* @return The auth info repository instance.
*/
@Provides
def provideAuthInfoRepository(
passwordInfoDAO: DelegableAuthInfoDAO[PasswordInfo]): AuthInfoRepository =
new DelegableAuthInfoRepository(passwordInfoDAO)
It throws the below error
Unexpected exception
CreationException: Unable to create injector, see the following errors:
1) No implementation for com.mohiva.play.silhouette.persistence.daos.DelegableAuthInfoDAO<com.mohiva.play.silhouette.api.util.PasswordInfo> was bound.
while locating com.mohiva.play.silhouette.persistence.daos.DelegableAuthInfoDAO<com.mohiva.play.silhouette.api.util.PasswordInfo>
for the 1st parameter of modules.SilhouetteModule.provideAuthInfoRepository(SilhouetteModule.scala:182)
at modules.SilhouetteModule.provideAuthInfoRepository(SilhouetteModule.scala:182) (via modules: com.google.inject.util.Modules$OverrideModule -> modules.SilhouetteModule)
I tried to force the connection using a @Named
decorator
@Provides
@Named("password-repository")
def providePasswordDAO(dbConfigProvider: DatabaseConfigProvider,
loginDao: LoginDAO): PasswordDAO =
new PasswordDAO(dbConfigProvider, loginDao)
against the AuthInfoRepository
provider but it's the same issue
@Provides
def provideAuthInfoRepository(
@Named("password-repository")
passwordInfoDAO: DelegableAuthInfoDAO[PasswordInfo]): AuthInfoRepository =
new DelegableAuthInfoRepository(passwordInfoDAO)
please see the project at the below location, sorry, I am not familiar with Guice
https://github.com/CollegeBoreal/play-silhouette-slick-mysql
Thanks
play-silhouette-seed
and managed to get JWT sent back to the client in a Response Header called X-Auth-Token
, however when I'm trying to visit other pages on the site, those pages don't send the token back to the server, so the user always gets redirected to log in again. I've found this problem in the archive and implemented it to save the token as a cookie, but still doesn't work: https://gitter.im/mohiva/play-silhouette/archives/2015/05/30