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 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)
akkie on 7.0.0
akkie on master
Release version 7.0.0 (compare)
akkie on 7.0.0-RC1
@akkie : From Play documentation it follows that CSRF check arise when executing a POST method with an authorization header, both conditions set on the current JWT authentication issue.
Postman 403 Forbidden messages might be explained because no Cookie is provided in the request.
Disabling the CSRF filter adding nocsrf before the route, makes Postman to reply a 200 Ok message.
Enabling the logger level to TRACE in the logback file, provide the following:
[trace] p.a.m.PlayBodyParsers - Parsing AnyContent as json
[trace] p.a.m.ActionBuilder
KaTeX parse error: Can't use function '$' in math mode at position 5: anon$̲9 - Invoking ac…: anon$9 - Invoking action with request: POST /paymentToken
User not authenticated!
[trace] p.filters.CSRF - [CSRF] No check necessary
[trace] p.a.m.ActionBuilder
anon$9 - Invoking action with request: GET /signInStuck here!
Hello everybody,
I'm trying to implement some incredibly basic JWT authentication for site admins (there are no users). I've followed along with the most recent example projects I can find, but even doing this still results in some errors. Play is not able to instantiate my SilhouetteModule
because it cannot find valid constructors for it? Solutions say to add environment and configuration to the constructor but this doesn't work either. Does anyone have any ideas?
Module [modules.SilhouetteModule] cannot be instantiated.
, which is pretty vague already. My module looks more or less like this
play.api.PlayException: No valid constructors[Module [modules.SilhouetteModule] cannot be instantiated.]
at play.api.inject.Modules$.$anonfun$constructModule$5(Module.scala:173)
at scala.Option.getOrElse(Option.scala:201)
at play.api.inject.Modules$.constructModule(Module.scala:173)
at play.api.inject.Modules$.$anonfun$locate$4(Module.scala:138)
at scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:99)
at scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:86)
at scala.collection.immutable.HashSet.map(HashSet.scala:34)
at play.api.inject.Modules$.locate(Module.scala:133)
at play.api.inject.guice.GuiceableModule$.loadModules(GuiceInjectorBuilder.scala:299)
at play.api.inject.guice.GuiceApplicationBuilder$.$anonfun$$lessinit$greater$default$9$1(GuiceApplicatio
nBuilder.scala:36)
at play.api.inject.guice.GuiceApplicationBuilder.applicationModule(GuiceApplicationBuilder.scala:114)
at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:200)
at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:155)
at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
at play.core.server.DevServerStart$$anon$1.$anonfun$reload$3(DevServerStart.scala:190)
at play.utils.Threads$.withContextClassLoader(Threads.scala:22)
at play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:182)
at play.core.server.DevServerStart$$anon$1.get(DevServerStart.scala:142)
at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:301)
at play.core.server.AkkaHttpServer.$anonfun$createServerBinding$1(AkkaHttpServer.scala:191)
at akka.stream.impl.fusing.MapAsync$$anon$30.onPush(Ops.scala:1285)
at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:541)
at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:423)
at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:625)
at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:502)
at akka.stream.impl.fusing.GraphInterpreterShell.processEvent(ActorGraphInterpreter.scala:600)
at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processE
vent(ActorGraphInterpreter.scala:769)
at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.sc
ala:784)
at akka.actor.Actor.aroundReceive(Actor.scala:535)
at akka.actor.Actor.aroundReceive$(Actor.scala:533)
at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:691)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:575)
at akka.actor.ActorCell.invoke(ActorCell.scala:545)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:270)
at akka.dispatch.Mailbox.run(Mailbox.scala:231)
at akka.dispatch.Mailbox.exec(Mailbox.scala:243)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
RequestHandlerBuilder
protected def handleAuthentication[B](implicit request: Request[B]): Future[(Option[Either[E#A, E#A]], Option[E#I])] = {
environment.authenticatorService.retrieve.flatMap {
// A valid authenticator was found so we retrieve also the identity
case Some(a) if a.isValid => environment.identityService.retrieve(a.loginInfo).map(i => Some(Left(a)) -> i)
@AndreyLadniy I see what you mean.
Maybe other people here can help better, but here are my thoughts.
One idea you could use is to create a custom action that extends SecuredAction and does not require login info... by changing this part in SecuredAction#invokeBlock:
// An authenticator but no user was found. The request will ask for authentication and the authenticator will be discarded
case (Some(authenticator), None, _) =>
In a previous job I used two different setups. Sharing in case it helps.
In one setup, I used Silohuette as a "login/auth server" and then other microservices just validated the JWT tokens using a shared key with the login server. The other servers didn't have sillohuette - they used a scala jwt library to decode and validate the tokens using a custom Play action I created.
In another setup, I wasn't expecting high traffic, so I implemented the "login/auth service" as a REST api and had a sort of proxy that validated every external request against the auth server before redirecting to the destination microservice.
I try implement Bearer token
(as refresh) and JWT
(as access token). So I implement two Environments
. Problem with disabling
I solve = :
IdentityService
override def retrieve(loginInfo: LoginInfo): Future[Option[String]] = {
Future.successful(Some(loginInfo.providerKey))
}
but when I try store JWT in httpOnly secured cookie, I understand something going wrong, so JWTbyCookieAuthenticationService
needed and so on.
I'm already leaning towards the number one solution like yours. The resource server does not need a large Silhouette library.
@akkie the second snippet (without using the type parameter [T]) does compile but it gives an Error. The same error is thrown when using the type parameter [T].
[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)
I have run to the very exact same problem. How did you end up solving it? Do you mind sending a code snippet, please?
class PersistedAuthInfoDAO @Inject() (db: Database)
(implicit executionContext: DatabaseExecutionContext,
implicit val classTag: ClassTag[PasswordInfo])
extends DelegableAuthInfoDAO[PasswordInfo] {
@Provides
def providesAuthInfoDAO(authInfoDAO: PersistedAuthInfoDAO, classTag: ClassTag[PasswordInfo])(
implicit
ex: ExecutionContext): DelegableAuthInfoDAO[PasswordInfo] = {
authInfoDAO
}