Securing
Microservices
using Play and Akka HTTP
Rafal Gancarz
@RafalGancarz
1
About me
• Lead Consultant at
OpenCredo
• Helping companies transform
their IT platforms and the ways
their do business
• Technologist, architect,
developer
• Agile practitioner & evangelist
• Scala <- Java <- PHP
2
(Micro)services
• SOA reloaded
• Lightweight, open standards
• Loosely coupled, self-contained
• Independent and scalable
• Bounded context (part of business domain)
3
Securing the monolith
DB
authentication
Pros
• single entry point
• limited attack surface
• centralised authentication &
authorisation
Cons
• totally exposed when
compromised
4
Securing the monolith -
considerations
• Combined presentation and business logic tier
• End user login
• Session based authentication
• Single sign-on (usually with SAML)
5
Securing microservices
(first take)
DB
Pros
• siloed data
Cons
• large attack surface
• multiple auth enforcement
points
• shared auth data storeDB DB
6
• Who is the consumer (the end user vs the third-party system)?
• Is user context relevant?
• access control granularity
• act on behalf
• What are the security related requirements?
• highly sensitive data
• integration over public internet
• social login
• single sign-on (SSO)
Securing microservices - considerations
7
• What are commercial requirements for your project?
• time to market
• availability of skills / expertise
• buy vs build
• What about the legacy?
• existing security implementation
• interoperability with the legacy platform
Securing microservices - considerations
8
API gateway
DB DB DB
API gateway
Pros
• single point of entry
• limited surface attack
• configurable authentication
protocols and backends
• faster time to market
• gateway availability/scalability
Cons
• additional cost
• services unsecured internally
• HTTP level access control
• limited auth context
9
HTTP basic auth + client id&secret
DB DB DB
Pros
• easy
• good for third-party integration
• stateless
Cons
• requires TLS
• doesn’t expire
• difficult to enforce at scale
(unless used with API gateway)
client_id
client_secret
10
Play Framework
• Basic HTTP auth with HTTP filter
• Basic HTTP auth with Action builder
• Play2.x Authentication and Authorization module
(https://github.com/t2v/play2-auth)
• Pac4j module (https://github.com/leleuj/play-pac4j)
• Secure Social module (http://securesocial.ws/)
• Silhouette module (http://silhouette.mohiva.com/)
11
Akka HTTP
• authenticateBasicX directives
• http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0-M2/scala/http/routing-dsl/directives/
security-directives/authenticateBasic.html#authenticatebasic
def myUserPassAuthenticator(credentials: Credentials): Future[Option[String]] =
credentials match {
case p @ Credentials.Provided(id) =>
Future {
// potentially
if (p.verify("s3cr3t")) Some(id)
else None
}
case _ => Future.successful(None)
}
val route =
Route.seal {
path("secured") {
authenticateBasicAsync(realm = "secure site", myUserPassAuthenticator)
{ userName =>
complete(s"The user is '$userName'")
}
}
}
12
OAuth2+OpenID Connect
DB DB DB
Auth Server
Pros
• standard based
• popular for social login & delegated
authorisation
• caters for browser, mobile and
server-to-server use cases
• token expiry
Cons
• requires TLS
• requires Authorisation Server
• developed initially as authorisation
framework
• numerous flavours used
• non-trivial to get right
• authentication impl out of scope
13
Play Framework
• Pac4j module (https://github.com/leleuj/play-pac4j)
- supports OAuth2, OAuth2 and OpenID
• Secure Social module (http://securesocial.ws/) -
supports OAuth1 and OAuth2
• Silhouette module (http://silhouette.mohiva.com/) -
supports OAuth1, OAuth2 and OpenID
14
Akka HTTP
• authenticateOAuth2X directives
• http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0-M2/scala/http/
routing-dsl/directives/security-directives/
authenticateOAuth2.html#authenticateoauth2
def authenticateOAuth2[T](realm: String,
authenticator: Authenticator[T]):
AuthenticationDirective[T]
Usage the same as HTTP basic but requires validating access
token retrieved from the header (not supported natively).
15
OpenID Connect
• Nimbus (https://bitbucket.org/connect2id/
oauth-2.0-sdk-with-openid-connect-extensions)
• Apache Oltu (https://oltu.apache.org/)
https://openid.net/developers/specs/ 16
JSON Web Token
DB DB DB
Auth Server
Pros
• auth claims can be signed
(HMAC or RSA)
• compact (suitable for URLs,
headers, query params)
• self-contained, stateless
• excellent SAML alternative for
SSO
Cons
• requires TLS or encryption
• authentication impl out of scope
http://jwt.io/
17
JSON Web Token
• No built-in support in Play or Akka HTTP
• authentikat-jwt (https://github.com/jasongoodwin/
authentikat-jwt) - Scala
• iain-logan/jwt (https://github.com/iain-logan/jwt) - Scala
• jose4j (https://bitbucket.org/b_c/jose4j/wiki/Home) -
Java
• jjwt (https://github.com/jwtk/jjwt) - Java
18
Mutually authenticated TLS
DB DB DB
Pros
• strong point to point security
Cons
• requires PKI
• key management and
distribution challenging
• difficult to implement and
troubleshoot
• no user context
mTLS
19
Play Framework - server-side
• https://www.playframework.com/documentation/2.4.x/ConfiguringHttps
class CustomSSLEngineProvider(appProvider: ApplicationProvider) extends SSLEngineProvider {
def createSSLContext(applicationProvider: ApplicationProvider): SSLContext = {

val keyManagers = readKeyManagers()

val trustManagers = readTrustManagers()



val sslContext = SSLContext.getInstance("TLS")

sslContext.init(keyManagers, trustManagers, null)

sslContext

}
override def createSSLEngine(): SSLEngine = {
val sslContext = createSSLContext(appProvider)
val sslParameters = sslContext.getDefaultSSLParameters
sslParameters.setUseCipherSuitesOrder(true)
sslParameters.setNeedClientAuth(true)
val engine = sslContext.createSSLEngine

engine.setSSLParameters(sslParameters)
engine
}
}
20
Akka HTTP - server-side
• http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0-
M2/scala/http/low-level-server-side-api.html#serversidehttps
def createSSLContext(): SSLContext = {

val keyManagers = readKeyManagers()

val trustManagers = readTrustManagers()



val sslContext = SSLContext.getInstance("TLS")

sslContext.init(keyManagers, trustManagers, null)

sslContext

}



def run() = {



implicit val system = ActorSystem("server")

implicit val materializer = ActorMaterializer()



val sslContext = createSSLContext()



val serverSource = Http().bind(interface = "localhost", port = 8200, ServerSettings(system),
Some(HttpsContext(sslContext, Some(immutable.Seq("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384")),
Some(immutable.Seq("TLSv1.2")), Some(Need), Some(sslContext.getDefaultSSLParameters))))



…



}
21
Authorisation
• At the perimeter or within the business logic?
• Where user roles/permissions are coming from
(each bounded context might have different
access control considerations)?
• How is the user context passed into the service?
22
Play Framework
• Authorisation with HTTP filter
• Authorisation with Action builder
• Deadbolt (http://deadbolt.ws/#/home) - works with
Silhouette and SecureSocial for authentication
23
Akka HTTP
• authorize directive
• http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0-M2/scala/http/routing-dsl/
directives/security-directives/authorize.html#authorize
case class User(name: String)
val admins = Set("Peter")
def hasAdminPermissions(user: User): Boolean =
admins.contains(user.name)
val route =
Route.seal {
authenticateBasic(realm = "secure site", myUserPassAuthenticator) { user
=>
path("peters-lair") {
authorize(hasAdminPermissions(user)) {
complete(s"'${user.name}' visited Peter's lair")
}
}
}
}
24
Key takeaways
• Securing microservice based architectures is
challenging
• The technology landscape changes all the time
• One size (solution) doesn’t fit all
• Consider your requirements before committing to a
technical solution
25
Questions?
• Email: rafal.gancarz@opencredo.com
• Twitter: @RafalGancarz
• See me tomorrow at lunchtime for a Q&A session on
Securing Microservices using Play and Akka HTTP
• Visit OpenCredo’s booth tomorrow and enter a draw to
win Apple Watch!
• See you at the Scala Exchange party later :)
• Thank you!
26

Securing Microservices using Play and Akka HTTP

  • 1.
    Securing Microservices using Play andAkka HTTP Rafal Gancarz @RafalGancarz 1
  • 2.
    About me • LeadConsultant at OpenCredo • Helping companies transform their IT platforms and the ways their do business • Technologist, architect, developer • Agile practitioner & evangelist • Scala <- Java <- PHP 2
  • 3.
    (Micro)services • SOA reloaded •Lightweight, open standards • Loosely coupled, self-contained • Independent and scalable • Bounded context (part of business domain) 3
  • 4.
    Securing the monolith DB authentication Pros •single entry point • limited attack surface • centralised authentication & authorisation Cons • totally exposed when compromised 4
  • 5.
    Securing the monolith- considerations • Combined presentation and business logic tier • End user login • Session based authentication • Single sign-on (usually with SAML) 5
  • 6.
    Securing microservices (first take) DB Pros •siloed data Cons • large attack surface • multiple auth enforcement points • shared auth data storeDB DB 6
  • 7.
    • Who isthe consumer (the end user vs the third-party system)? • Is user context relevant? • access control granularity • act on behalf • What are the security related requirements? • highly sensitive data • integration over public internet • social login • single sign-on (SSO) Securing microservices - considerations 7
  • 8.
    • What arecommercial requirements for your project? • time to market • availability of skills / expertise • buy vs build • What about the legacy? • existing security implementation • interoperability with the legacy platform Securing microservices - considerations 8
  • 9.
    API gateway DB DBDB API gateway Pros • single point of entry • limited surface attack • configurable authentication protocols and backends • faster time to market • gateway availability/scalability Cons • additional cost • services unsecured internally • HTTP level access control • limited auth context 9
  • 10.
    HTTP basic auth+ client id&secret DB DB DB Pros • easy • good for third-party integration • stateless Cons • requires TLS • doesn’t expire • difficult to enforce at scale (unless used with API gateway) client_id client_secret 10
  • 11.
    Play Framework • BasicHTTP auth with HTTP filter • Basic HTTP auth with Action builder • Play2.x Authentication and Authorization module (https://github.com/t2v/play2-auth) • Pac4j module (https://github.com/leleuj/play-pac4j) • Secure Social module (http://securesocial.ws/) • Silhouette module (http://silhouette.mohiva.com/) 11
  • 12.
    Akka HTTP • authenticateBasicXdirectives • http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0-M2/scala/http/routing-dsl/directives/ security-directives/authenticateBasic.html#authenticatebasic def myUserPassAuthenticator(credentials: Credentials): Future[Option[String]] = credentials match { case p @ Credentials.Provided(id) => Future { // potentially if (p.verify("s3cr3t")) Some(id) else None } case _ => Future.successful(None) } val route = Route.seal { path("secured") { authenticateBasicAsync(realm = "secure site", myUserPassAuthenticator) { userName => complete(s"The user is '$userName'") } } } 12
  • 13.
    OAuth2+OpenID Connect DB DBDB Auth Server Pros • standard based • popular for social login & delegated authorisation • caters for browser, mobile and server-to-server use cases • token expiry Cons • requires TLS • requires Authorisation Server • developed initially as authorisation framework • numerous flavours used • non-trivial to get right • authentication impl out of scope 13
  • 14.
    Play Framework • Pac4jmodule (https://github.com/leleuj/play-pac4j) - supports OAuth2, OAuth2 and OpenID • Secure Social module (http://securesocial.ws/) - supports OAuth1 and OAuth2 • Silhouette module (http://silhouette.mohiva.com/) - supports OAuth1, OAuth2 and OpenID 14
  • 15.
    Akka HTTP • authenticateOAuth2Xdirectives • http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0-M2/scala/http/ routing-dsl/directives/security-directives/ authenticateOAuth2.html#authenticateoauth2 def authenticateOAuth2[T](realm: String, authenticator: Authenticator[T]): AuthenticationDirective[T] Usage the same as HTTP basic but requires validating access token retrieved from the header (not supported natively). 15
  • 16.
    OpenID Connect • Nimbus(https://bitbucket.org/connect2id/ oauth-2.0-sdk-with-openid-connect-extensions) • Apache Oltu (https://oltu.apache.org/) https://openid.net/developers/specs/ 16
  • 17.
    JSON Web Token DBDB DB Auth Server Pros • auth claims can be signed (HMAC or RSA) • compact (suitable for URLs, headers, query params) • self-contained, stateless • excellent SAML alternative for SSO Cons • requires TLS or encryption • authentication impl out of scope http://jwt.io/ 17
  • 18.
    JSON Web Token •No built-in support in Play or Akka HTTP • authentikat-jwt (https://github.com/jasongoodwin/ authentikat-jwt) - Scala • iain-logan/jwt (https://github.com/iain-logan/jwt) - Scala • jose4j (https://bitbucket.org/b_c/jose4j/wiki/Home) - Java • jjwt (https://github.com/jwtk/jjwt) - Java 18
  • 19.
    Mutually authenticated TLS DBDB DB Pros • strong point to point security Cons • requires PKI • key management and distribution challenging • difficult to implement and troubleshoot • no user context mTLS 19
  • 20.
    Play Framework -server-side • https://www.playframework.com/documentation/2.4.x/ConfiguringHttps class CustomSSLEngineProvider(appProvider: ApplicationProvider) extends SSLEngineProvider { def createSSLContext(applicationProvider: ApplicationProvider): SSLContext = {
 val keyManagers = readKeyManagers()
 val trustManagers = readTrustManagers()
 
 val sslContext = SSLContext.getInstance("TLS")
 sslContext.init(keyManagers, trustManagers, null)
 sslContext
 } override def createSSLEngine(): SSLEngine = { val sslContext = createSSLContext(appProvider) val sslParameters = sslContext.getDefaultSSLParameters sslParameters.setUseCipherSuitesOrder(true) sslParameters.setNeedClientAuth(true) val engine = sslContext.createSSLEngine
 engine.setSSLParameters(sslParameters) engine } } 20
  • 21.
    Akka HTTP -server-side • http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0- M2/scala/http/low-level-server-side-api.html#serversidehttps def createSSLContext(): SSLContext = {
 val keyManagers = readKeyManagers()
 val trustManagers = readTrustManagers()
 
 val sslContext = SSLContext.getInstance("TLS")
 sslContext.init(keyManagers, trustManagers, null)
 sslContext
 }
 
 def run() = {
 
 implicit val system = ActorSystem("server")
 implicit val materializer = ActorMaterializer()
 
 val sslContext = createSSLContext()
 
 val serverSource = Http().bind(interface = "localhost", port = 8200, ServerSettings(system), Some(HttpsContext(sslContext, Some(immutable.Seq("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384")), Some(immutable.Seq("TLSv1.2")), Some(Need), Some(sslContext.getDefaultSSLParameters))))
 
 …
 
 } 21
  • 22.
    Authorisation • At theperimeter or within the business logic? • Where user roles/permissions are coming from (each bounded context might have different access control considerations)? • How is the user context passed into the service? 22
  • 23.
    Play Framework • Authorisationwith HTTP filter • Authorisation with Action builder • Deadbolt (http://deadbolt.ws/#/home) - works with Silhouette and SecureSocial for authentication 23
  • 24.
    Akka HTTP • authorizedirective • http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0-M2/scala/http/routing-dsl/ directives/security-directives/authorize.html#authorize case class User(name: String) val admins = Set("Peter") def hasAdminPermissions(user: User): Boolean = admins.contains(user.name) val route = Route.seal { authenticateBasic(realm = "secure site", myUserPassAuthenticator) { user => path("peters-lair") { authorize(hasAdminPermissions(user)) { complete(s"'${user.name}' visited Peter's lair") } } } } 24
  • 25.
    Key takeaways • Securingmicroservice based architectures is challenging • The technology landscape changes all the time • One size (solution) doesn’t fit all • Consider your requirements before committing to a technical solution 25
  • 26.
    Questions? • Email: rafal.gancarz@opencredo.com •Twitter: @RafalGancarz • See me tomorrow at lunchtime for a Q&A session on Securing Microservices using Play and Akka HTTP • Visit OpenCredo’s booth tomorrow and enter a draw to win Apple Watch! • See you at the Scala Exchange party later :) • Thank you! 26