/triggers/service/auth/src/test/scala/com/daml/oauth/server/Client.scala

https://github.com/digital-asset/daml · Scala · 105 lines · 86 code · 10 blank · 9 comment · 1 complexity · 7728058fe71de1a946130cb974ed5b6a MD5 · raw file

  1. // Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package com.daml.oauth.server
  4. import akka.actor.ActorSystem
  5. import akka.http.scaladsl.Http
  6. import akka.http.scaladsl.Http.ServerBinding
  7. import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
  8. import akka.http.scaladsl.model.Uri.Path
  9. import akka.http.scaladsl.model._
  10. import akka.http.scaladsl.server.Directives._
  11. import akka.http.scaladsl.unmarshalling.Unmarshal
  12. import com.daml.ports.Port
  13. import spray.json._
  14. import scala.concurrent.{ExecutionContext, Future}
  15. import scala.language.postfixOps
  16. // This is a test client (using terminology from oauth).
  17. // The trigger service would also take the role of a client.
  18. object Client {
  19. import com.daml.oauth.server.JsonProtocol._
  20. case class Config(
  21. port: Port,
  22. authServerUrl: Uri,
  23. clientId: String,
  24. clientSecret: String
  25. )
  26. object JsonProtocol extends DefaultJsonProtocol {
  27. implicit val accessParamsFormat: RootJsonFormat[AccessParams] = jsonFormat1(AccessParams)
  28. implicit val accessResponseFormat: RootJsonFormat[AccessResponse] = jsonFormat1(AccessResponse)
  29. }
  30. case class AccessParams(parties: Seq[String])
  31. case class AccessResponse(token: String)
  32. def toRedirectUri(uri: Uri): Uri = uri.withPath(Path./("cb"))
  33. def start(
  34. config: Config)(implicit asys: ActorSystem, ec: ExecutionContext): Future[ServerBinding] = {
  35. import JsonProtocol._
  36. val route = concat(
  37. // Some parameter that requires authorization for some parties. This will in the end return the token
  38. // produced by the authorization server.
  39. path("access") {
  40. post {
  41. entity(as[AccessParams]) {
  42. params =>
  43. extractRequest {
  44. request =>
  45. val redirectUri = toRedirectUri(request.uri)
  46. val authParams = Request.Authorize(
  47. responseType = "code",
  48. clientId = config.clientId,
  49. redirectUri = redirectUri,
  50. scope = Some(params.parties.map(p => "actAs:" + p).mkString(" ")),
  51. state = None)
  52. redirect(
  53. config.authServerUrl
  54. .withQuery(authParams.toQuery)
  55. .withPath(Path./("authorize")),
  56. StatusCodes.Found)
  57. }
  58. }
  59. }
  60. },
  61. path("cb") {
  62. get {
  63. parameters(('code, 'state ?)).as[Response.Authorize](Response.Authorize) {
  64. resp =>
  65. extractRequest {
  66. request =>
  67. // We got the code, now request a token
  68. val body = Request.Token(
  69. grantType = "authorization_code",
  70. code = resp.code,
  71. redirectUri = toRedirectUri(request.uri),
  72. clientId = config.clientId,
  73. clientSecret = config.clientSecret)
  74. val req = HttpRequest(
  75. uri = config.authServerUrl.withPath(Path./("token")),
  76. entity = HttpEntity(MediaTypes.`application/json`, body.toJson.compactPrint),
  77. method = HttpMethods.POST,
  78. )
  79. val f = for {
  80. resp <- Http().singleRequest(req)
  81. tokenResp <- Unmarshal(resp).to[Response.Token]
  82. } yield tokenResp
  83. onSuccess(f) { tokenResp =>
  84. // Now we have the access_token and potentially the refresh token. At this point,
  85. // we would start the trigger.
  86. complete(AccessResponse(tokenResp.accessToken))
  87. }
  88. }
  89. }
  90. }
  91. }
  92. )
  93. Http().bindAndHandle(route, "localhost", config.port.value)
  94. }
  95. }