play2-oauth-client
A Play2 module implementing a small extension to the silhouette authorization library. Using the modules developers are able to connect to an OAuth2 provider that has been implemented to fit the needs of Viva con Agua.
Implements an OAuth2 client for Play2 apps. It allows to use Drops as social provider and tailors the OAuth2 handshake to specific organizational support. First, a user has to be logged out if and only if, a user has been logged out from Drops. Thus play2-oauth-client implements an additional Object-Event-System (OES) using the nats message broker.
Usage
Resolve the library from Sonatype in your build.sbt
:
resolvers += "Sonatype OSS Releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2"
libraryDependencies += "org.vivaconagua" %% "play2-oauth-client" % "0.4.1"
You have to use the lib in a controller. You can simply implement the DropsLoginController
trait:
package controllers
import javax.inject.Inject
import com.mohiva.play.silhouette.api.Silhouette
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.impl.providers.SocialProviderRegistry
import org.vivaconagua.play2OauthClient.silhouette.CookieEnv
import org.vivaconagua.play2OauthClient.controller.DropsLoginController
import org.vivaconagua.play2OauthClient.silhouette.UserService
import concurrent.ExecutionContext.Implicits.global
import play.api.mvc._
import play.api.libs.ws._
import play.api._
import play.api.cache.CacheApi
class DropsController @Inject()(
ws: WSClient,
override val conf : Configuration,
cc: ControllerComponents,
override val silhouette: Silhouette[CookieEnv],
override val userService: UserService,
override val authInfoRepository: AuthInfoRepository,
override val socialProviderRegistry: SocialProviderRegistry,
cache: CacheApi
) extends AbstractController(cc) with DropsLoginController {
override val defaultRedirectUrl = routes.HomeController.index.url // defines the default page a user sees after login
}
Now you have to add the following routes to your conf/routes
file. These routes are needed to redirect the users client in order to fulfill the OAuth2 handshake with the social provider Drops:
GET /authenticate/:provider controllers.DropsController.authenticate(provider, route: Option[String], ajax: Option[Boolean])
POST /authenticate/:provider controllers.DropsController.authenticate(provider, route: Option[String], ajax: Option[Boolean])
WebApps
Furthermore, if you implement a JavaScript WebApp, you can add the following route to your routes
file:
GET /identity controllers.DropsController.frontendLogin
If your user has a valid session with Drops, you will receive:
{
"uuid": "<your-users-uuid>"
}
Otherwise, you will receive a JSON encoded error message using the following format:
{
"http_error_code": 401,
"internal_error_code": "401.OAuth2Server",
"msg": "Currently, there is no authenticated user.",
"msg_i18n": "error.oauth2.not.authenticated",
"additional_information": {
"oauth2_client": "<a microservice identifier>"
}
}
Auth OES
Since play2-oauth-client has to communicate with your nats message broker and Drops you have to add the following lines to your conf/application.conf
:
nats.endpoint="nats://<nats_ip>:<nats_port>" // default port is 4222
ms.name="<your_ms_name>" // example: BLOOB
ms.host="<your_ms_domain>" // example: http://localhost:9000
ms.entrypoint="<your_ms_route>" // the route that you have configured before, example: /authenticate/drops
drops.url.base="<drops_domain>" // example: http://localhost:9100 or https://pool.vivaconagua.org/drops
drops.client_id="<your_ms_id>" // the id that has been configured in drops to identify your microservice
drops.client_secret="<your_ms_secret>" // the secret that has been configured in drops to identify your microservice
play.filters.enabled += org.vivaconagua.play2OauthClient.drops.AuthOESFilter
Example implementation
An example controller using the implemented authentification:
import javax.inject.Inject
import play.api.mvc._
import com.mohiva.play.silhouette.api.Silhouette
import org.vivaconagua.play2OauthClient.silhouette.CookieEnv
import org.vivaconagua.play2OauthClient.silhouette.UserService
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.mvc.AnyContent
import play.api.Logger
/**
* A very small controller that renders a home page.
*/
class HomeController @Inject()(
cc: ControllerComponents,
silhouette: Silhouette[CookieEnv],
userService: UserService
) extends AbstractController(cc) {
val logger: Logger = Logger(this.getClass())
def userTest = silhouette.SecuredAction.async { implicit request => {
Future.successful(Ok("User: " + request.identity))
}}
}
How it works
Todo