finagle-oauth2 travis-ci

OAuth2 Server-Side Provider for Finagle

3 years after

Build Status Maven Central

OAuth2 Provider for Finagle

This is a finagled OAuth2 server-side provider based on the source code from a scala-oauth2-provider library. Since scala-oauth2-provider it involves:

  • an asynchronous version of a DataHandler trait
  • asynchronous versions of both TokenEndpoint and ProtectedResource handlers
  • an asynchronous version of unit tests
  • four new finagled entities: OAuth2, OAuth2Request, OAuth2Filter, OAuth2Endpoint

This makes the usage of this library very sleek from a finagled environment. The brief usage instruction looks as follows:

  • define an implementation of a DataHandler interface
  • define a service that emits access tokens using either
    • simple http service with OAuth2 trait mixed or
    • configurable OAuth2Endpoint instantiated
  • define a protected service using either
    • simple http service with OAuth2 trait mixed or
    • type-safe service Service[OAuth2Request[U], Response] and OAuth2Filter applied

Finagle OAuth2 is build on top of finagle-http and tt compiles with both Scala 2.11 and 2.10.

SBT Artifacts

libraryDependencies ++= Seq(
  "com.github.finagle" %% "finagle-oauth2" % "0.1.6"
)

User Guide

There are two possible ways of using finagle-oauth2 provider:

  • via OAuth2 trait mixed to finagled service
  • via predefined type-safe classes OAuth2Request, OAuth2Filter, OAuth2Endpoint (a preferred way)
Using OAuth2 trait

OAuth2 trait provides two asynchronous methods: issueAccessToken and authorize.

A token service that emits OAuth2 access tokens.

import com.twitter.finagle.OAuth2
import com.twitter.finagle.oauth2._

object TokenService extends Service[Request, Response] with OAuth2 {
  def apply(req: Request) = 
    issueAccessToken(req, dataHandler) flatMap { token =>
      val rep = Response(Version.Http11, Status.Ok)
      rep.setContentString(token.accessToken)
      Future.value(rep)
    } handle {
      case e: OAuthError => e.toHttpResponse
    }
}

A protected service that checks whether the request authorized or not.

import com.twitter.finagle.OAuth2
import com.twitter.finagle.oauth2._

object ProtectedService extends Service[Request, Response] with OAuth2 {
  def apply(req: Request) =
    authorize(req, dataHandler) flatMap { authInfo =>
      val rep = Response(Version.Http11, Status.Ok)
      rep.setContentString(s"Hello ${authInfo.user}")
      Future.value(rep)
    } handle {
      case e: OAuthError => e.toHttpResponse
    }
}
Using type-safe OAuth2Filter and OAuth2Request

It's preferred to use the power of Finagle filters along with type-safe services. The code below shows how to use new building blocks OAuth2Filter and OAuth2Request in order to build robust type-safe services.

import com.twitter.finagle.oauth2._
import com.twitter.finagle.{OAuth2Request, OAuth2Filter, OAuth2Endpoint}

// accessing a protected resource via finagled filter
val auth = new OAuth2Filter(dataHandler) with OAuthErrorInJson

// a protected resource example
val hello = new Service[OAuth2Request[User], Response] {
  def apply(req: OAuth2Request[User]) = {
    println(s"Hello, ${req.authInfo.user}!")
    Future.value(Response())
  }
}

// combines the things together
val backend = RoutingService.byPathObject {
  case Root / "hello" => auth andThen hello
}
Using OAuth2Endpoint

It doesn't make sense to write an http service that emits access tokens in every new project. A finagle-oauth2 provider contains a configurable version of OAuth2Endpoint.

import com.twitter.finagle.oauth2._
import com.twitter.finagle.{OAuth2Request, OAuth2Filter, OAuth2Endpoint}

// emitting access tokens via finagled service
val tokens = new OAuth2Endpoint(dataHandler) with OAuthErrorInJson with OAuthTokenInJson

// combines the things together
val backend = RoutingService.byPathObject {
  case Root / "auth" => tokens
}
OAuthErrorHandler and OAuthTokenConverter

Both classes OAuth2Filter and OAuth2Endpoint uses trait-mixing in order to override the behaviour on handling errors and serializing tokens. The traits defines such behaviour look as following:

trait OAuthErrorHandler {
  def handleError(e: OAuthError): Response
}

trait OAuthTokenConverter {
  def convertToken(token: GrantHandlerResult): Response
}

So you can define your own error handler or token converter and mix it into a concrete instance like this:

trait MyErrorHandler extends OAuthErrorHandler {
  // we don't care at all
  def handleError(e: OAuthError) = Response(Status.Ok)
}

val tokens = new OAuth2Endpoint with MyErrorHandler

By default errors are serialized in WWW-Authenticate header while access tokens are serialized as simple string in the response body.

There are also two predefined traits: OAuthErrorInJson and OAuthTokenInJson which serializes everything into JSON objects.

Related Repositories

awesome-java

awesome-java

A curated list of awesome frameworks, libraries and software for the Java progra ...

awesome-scala

awesome-scala

A community driven list of useful Scala libraries, frameworks and software. ...

awesome-microservices

awesome-microservices

A curated list of Microservice Architecture related principles and technologies. ...

finch

finch

Scala combinator library for building Finagle HTTP services ...

awesome-scala

awesome-scala

A curated list of awesome Scala frameworks, libraries and software. ...


Top Contributors

vkostyukov clhodapp hughfdjackson

Releases

-   0.1.7 zip tar
-   0.1.5 zip tar
-   0.1.4 zip tar
-   0.1.3 zip tar