Skip to content

Commit 5cce2b1

Browse files
author
Johannes Duesing
committed
Introducing JWT based authentication for communication with registry
1 parent 4dbb9df commit 5cce2b1

File tree

5 files changed

+84
-5
lines changed

5 files changed

+84
-5
lines changed

build.sbt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ libraryDependencies ++= Seq(
2424
"com.sksamuel.elastic4s" %% "elastic4s-http-streams" % elastic4sVersion,
2525
)
2626

27+
libraryDependencies += "com.pauldijou" %% "jwt-core" % "1.0.0"
28+
2729
libraryDependencies += "org.parboiled" %% "parboiled" % "2.1.4"
2830
libraryDependencies += "io.spray" %% "spray-json" % "1.3.3"
2931
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.4"

src/main/scala/de/upb/cs/swt/delphi/instancemanagement/InstanceRegistry.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ import java.net.InetAddress
2020

2121
import akka.http.scaladsl.Http
2222
import akka.http.scaladsl.model._
23+
import akka.http.scaladsl.model.headers.RawHeader
2324
import akka.http.scaladsl.unmarshalling.Unmarshal
2425
import akka.util.ByteString
2526
import de.upb.cs.swt.delphi.instancemanagement.InstanceEnums.{ComponentType, InstanceState}
27+
import de.upb.cs.swt.delphi.webapi.authorization.AuthProvider
2628
import de.upb.cs.swt.delphi.webapi.{AppLogging, Configuration, _}
2729
import spray.json._
2830

@@ -92,7 +94,7 @@ object InstanceRegistry extends InstanceJsonSupport with AppLogging {
9294
method = HttpMethods.POST,
9395
configuration.instanceRegistryUri + ReportOperationType.toOperationUriString(operationType, id))
9496

95-
Await.result(Http(system).singleRequest(request) map { response =>
97+
Await.result(Http(system).singleRequest(request.withHeaders(RawHeader("Authorization",s"Bearer ${AuthProvider.generateJwt()}"))) map { response =>
9698
if (response.status == StatusCodes.OK) {
9799
log.info(s"Successfully reported ${operationType.toString} to Instance Registry.")
98100
Success()
@@ -146,7 +148,7 @@ object InstanceRegistry extends InstanceJsonSupport with AppLogging {
146148
configuration.instanceRegistryUri +
147149
s"/matchingInstance?Id=${configuration.assignedID.getOrElse(-1)}&ComponentType=ElasticSearch")
148150

149-
Await.result(Http(system).singleRequest(request) map { response =>
151+
Await.result(Http(system).singleRequest(request.withHeaders(RawHeader("Authorization",s"Bearer ${AuthProvider.generateJwt()}"))) map { response =>
150152
response.status match {
151153
case StatusCodes.OK =>
152154
try {
@@ -189,7 +191,7 @@ object InstanceRegistry extends InstanceJsonSupport with AppLogging {
189191
configuration.instanceRegistryUri +
190192
s"/matchingResult?CallerId=${configuration.assignedID.getOrElse(-1)}&MatchedInstanceId=$idToPost&MatchingSuccessful=$isElasticSearchReachable")
191193

192-
Await.result(Http(system).singleRequest(request) map { response =>
194+
Await.result(Http(system).singleRequest(request.withHeaders(RawHeader("Authorization",s"Bearer ${AuthProvider.generateJwt()}"))) map { response =>
193195
if (response.status == StatusCodes.OK) {
194196
log.info(s"Successfully posted matching result to Instance Registry.")
195197
Success()
@@ -216,7 +218,7 @@ object InstanceRegistry extends InstanceJsonSupport with AppLogging {
216218

217219
val request = HttpRequest(method = HttpMethods.POST, configuration.instanceRegistryUri + s"/deregister?Id=$id")
218220

219-
Await.result(Http(system).singleRequest(request) map { response =>
221+
Await.result(Http(system).singleRequest(request.withHeaders(RawHeader("Authorization",s"Bearer ${AuthProvider.generateJwt()}"))) map { response =>
220222
if (response.status == StatusCodes.OK) {
221223
log.info("Successfully deregistered from Instance Registry.")
222224
Success()
@@ -237,7 +239,7 @@ object InstanceRegistry extends InstanceJsonSupport with AppLogging {
237239
def postInstance(instance: Instance, uri: String)(): Future[HttpResponse] = {
238240
try {
239241
val request = HttpRequest(method = HttpMethods.POST, uri = uri, entity = instance.toJson(instanceFormat).toString())
240-
Http(system).singleRequest(request)
242+
Http(system).singleRequest(request.withHeaders(RawHeader("Authorization",s"Bearer ${AuthProvider.generateJwt()}")))
241243
} catch {
242244
case dx: DeserializationException =>
243245
log.warning(s"Failed to deregister to Instance Registry, exception: $dx")

src/main/scala/de/upb/cs/swt/delphi/webapi/Configuration.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ class Configuration( //Server and Elasticsearch configuration
8888
}
8989
lazy val instanceId: Option[Long] = InstanceRegistry.handleInstanceStart(configuration = this)
9090

91+
val jwtSecretKey: String = sys.env.getOrElse("DELPHI_JWT_SECRET","changeme")
92+
9193
}
9294

9395

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (C) 2018 The Delphi Team.
2+
// See the LICENCE file distributed with this work for additional
3+
// information regarding copyright ownership.
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
package de.upb.cs.swt.delphi.webapi.authorization
17+
18+
import akka.http.scaladsl.model.DateTime
19+
import de.upb.cs.swt.delphi.webapi.authorization.AccessTokenEnums.UserType
20+
21+
final case class AccessToken(userId: String,
22+
userType: UserType,
23+
expiresAt: DateTime,
24+
issuedAt: DateTime,
25+
notBefore: DateTime,
26+
scope: List[String])
27+
28+
object AccessTokenEnums {
29+
30+
type UserType = UserType.Value
31+
32+
object UserType extends Enumeration {
33+
val User : Value = Value("User")
34+
val Admin: Value = Value("Admin")
35+
val Component: Value = Value("Component")
36+
}
37+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (C) 2018 The Delphi Team.
2+
// See the LICENCE file distributed with this work for additional
3+
// information regarding copyright ownership.
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
package de.upb.cs.swt.delphi.webapi.authorization
17+
18+
import de.upb.cs.swt.delphi.webapi
19+
import pdi.jwt.{Jwt, JwtAlgorithm, JwtClaim}
20+
import spray.json.{JsArray, JsString}
21+
22+
object AuthProvider {
23+
24+
def generateJwt(validFor: Long = 3): String = {
25+
val claim = JwtClaim()
26+
.issuedNow
27+
.expiresIn(validFor)
28+
.startsNow
29+
.+("user_id", webapi.configuration.instanceName)
30+
.+("user_type", "Component")
31+
32+
33+
Jwt.encode(claim, webapi.configuration.jwtSecretKey, JwtAlgorithm.HS256)
34+
}
35+
36+
}

0 commit comments

Comments
 (0)