diff --git a/app/connectors/ThirdPartyDelegatedAuthorityConnector.scala b/app/connectors/ThirdPartyDelegatedAuthorityConnector.scala index f164479..eebf7e7 100644 --- a/app/connectors/ThirdPartyDelegatedAuthorityConnector.scala +++ b/app/connectors/ThirdPartyDelegatedAuthorityConnector.scala @@ -30,8 +30,8 @@ import scala.util.control.NonFatal class ThirdPartyDelegatedAuthorityConnector @Inject() (appContext: AppContext, http: HttpGet) { val serviceUrl: String = appContext.thirdPartyDelegatedAuthorityUrl - def fetchScopes(authorizationTokens: String)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Set[String]] = { - http.GET(s"$serviceUrl/delegated-authority", Nil, Seq("internal-auth-header" -> authorizationTokens))(readRaw, hc, ec) map { response => + def fetchScopes(accessToken: String)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Set[String]] = { + http.GET(s"$serviceUrl/delegated-authority", Nil, Seq("access-token" -> accessToken))(readRaw, hc, ec) map { response => if (response.status == Status.NOT_FOUND) { Set[String]() } else { diff --git a/app/controllers/UserInfoController.scala b/app/controllers/UserInfoController.scala index 89e8e68..a205fe4 100644 --- a/app/controllers/UserInfoController.scala +++ b/app/controllers/UserInfoController.scala @@ -25,7 +25,7 @@ import play.api.libs.json.Json import play.api.mvc.{AnyContent, BodyParser, ControllerComponents} import services.UserInfoService import uk.gov.hmrc.api.controllers.HeaderValidator -import uk.gov.hmrc.http.{BadRequestException, UpstreamErrorResponse => UER} +import uk.gov.hmrc.http.{BadRequestException, UnauthorizedException, UpstreamErrorResponse => UER} import uk.gov.hmrc.http.UpstreamErrorResponse.{Upstream4xxResponse, Upstream5xxResponse} import uk.gov.hmrc.play.bootstrap.backend.controller.BackendBaseController @@ -70,7 +70,8 @@ trait UserInfoController extends BackendBaseController with HeaderValidator { case Upstream4xxResponse(UER(_, 401, _, _)) => Unauthorized(Json.toJson(ErrorUnauthorized())) case Upstream4xxResponse(UER(msg4xx, _, _, _)) => BadGateway(Json.toJson(ErrorBadGateway(msg4xx))) case Upstream5xxResponse(UER(msg5xx, _, _, _)) => BadGateway(Json.toJson(ErrorBadGateway(msg5xx))) - case bex: BadRequestException => BadRequest(Json.toJson(ErrorBadRequest(bex.getMessage))) + case bex: BadRequestException => BadRequest(Json.toJson(ErrorBadRequest(bex.getMessage))) + case uex: UnauthorizedException => Unauthorized(Json.toJson(ErrorUnauthorized(uex.getMessage))) } } } diff --git a/app/services/UserInfoService.scala b/app/services/UserInfoService.scala index 1ed69ba..3ee3716 100644 --- a/app/services/UserInfoService.scala +++ b/app/services/UserInfoService.scala @@ -40,9 +40,12 @@ class LiveUserInfoService @Inject() ( override def fetchUserInfo(version: Version)(implicit hc: HeaderCarrier): Future[UserInfo] = { - val scopes = hc.authorization match { - case Some(authorisationTokens) => thirdPartyDelegatedAuthorityConnector.fetchScopes(authorisationTokens.value) - case None => Future.failed(new UnauthorizedException("Authorization token is required")) + val accessTokenHeaderName = "X-Client-Authorization-Token" + val accessTokenHeader = hc.otherHeaders.find(x => x._1 == accessTokenHeaderName) + + val scopes = accessTokenHeader match { + case Some(accessTokenHeader) => thirdPartyDelegatedAuthorityConnector.fetchScopes(accessTokenHeader._2) + case None => Future.failed(new UnauthorizedException(s"$accessTokenHeaderName header is missing")) } scopes.flatMap { scopes => diff --git a/it/UserInfoServiceISpec.scala b/it/UserInfoServiceISpec.scala index 6667610..bb1127e 100644 --- a/it/UserInfoServiceISpec.scala +++ b/it/UserInfoServiceISpec.scala @@ -49,6 +49,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart val serviceUrl: String = resource("") val authorizationTokens = "AUTHORIZATION_TOKENS" + val accessToken = "ACCESS_TOKEN" val nino = "AB123456A" val ukCountryCode = 1 val desUserInfo = DesUserInfo( @@ -201,7 +202,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart "'email' and 'openid:government-gateway' scopes" ) willReturnScopesForAuthTokens( - authorizationTokens, + accessToken, Set( "openid", "profile", @@ -238,7 +239,14 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart When("We request the user information") val result = Http(s"$serviceUrl") - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json", "token" -> "ggToken")) + .headers( + Seq( + "Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "token" -> "ggToken", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString val validator = JsonSchemaFactory.byDefault().getValidator @@ -265,7 +273,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart "'email' and 'openid:government-gateway' scopes" ) willReturnScopesForAuthTokens( - authorizationTokens, + accessToken, Set( "openid", "profile", @@ -302,7 +310,14 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart When("We request the user information") val result = Http(s"$serviceUrl") - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.2.0+json", "token" -> "ggToken")) + .headers( + Seq( + "Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.2.0+json", + "token" -> "ggToken", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("return Not Acceptable http response") @@ -316,7 +331,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart "'email' and 'openid:government-gateway' scopes" ) willReturnScopesForAuthTokens( - authorizationTokens, + accessToken, Set( "openid", "profile", @@ -355,8 +370,9 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart val result = Http(s"$serviceUrl") .headers( Seq( - "Authorization" -> s"Bearer $authorizationTokens", - "token" -> "ggToken", + "Authorization" -> s"Bearer $authorizationTokens", + "token" -> "ggToken", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN", "Accept" -> "" // "" is needed to pretend it is missing as test http libraries (such as scalaj.http and play.api.http) inject default Accept header if this is absent ) ) @@ -382,7 +398,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart Scenario("fetch user profile without family name") { Given("A Auth token with 'openid', 'profile', 'address', 'openid:gov-uk-identifiers' and 'openid:hmrc-enrolments' scopes") - willReturnScopesForAuthTokens(authorizationTokens, Set("openid", "profile", "address", "openid:gov-uk-identifiers", "openid:hmrc-enrolments")) + willReturnScopesForAuthTokens(accessToken, Set("openid", "profile", "address", "openid:gov-uk-identifiers", "openid:hmrc-enrolments")) willAuthoriseWith(200) And("The Auth token has a NINO") @@ -396,7 +412,12 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart When("We request the user information") val result = Http(s"$serviceUrl") - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json")) + .headers( + Seq("Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("The user information is returned") @@ -410,7 +431,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart "A Auth token with 'openid', 'profile', 'address', 'openid:gov-uk-identifiers', 'email', 'openid:government-gateway' and 'openid:hmrc-enrolments' scopes" ) willReturnScopesForAuthTokens( - authorizationTokens, + accessToken, Set("openid", "profile", "address", @@ -442,7 +463,14 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart When("We request the user information") val result = Http(s"$serviceUrl") - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json", "token" -> "ggToken")) + .headers( + Seq( + "Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "token" -> "ggToken", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("The user information is returned") @@ -453,7 +481,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart Scenario("fetch user data without address and user details when there are no address and user details") { Given("A Auth token with 'openid', 'profile', 'address', 'openid:gov-uk-identifiers' and 'openid:hmrc-enrolments' scopes") - willReturnScopesForAuthTokens(authorizationTokens, Set("openid", "profile", "address", "openid:gov-uk-identifiers", "openid:hmrc-enrolments")) + willReturnScopesForAuthTokens(accessToken, Set("openid", "profile", "address", "openid:gov-uk-identifiers", "openid:hmrc-enrolments")) willAuthoriseWith(200) And("The Auth token has a NINO") @@ -467,7 +495,12 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart When("We request the user information") val result = Http(s"$serviceUrl") - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json")) + .headers( + Seq("Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("The user information is returned") @@ -487,7 +520,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart Scenario("fetch enrolments only when scope contains 'openid:hmrc-enrolments'") { Given("A Auth token with 'openid:hmrc-enrolments' scopes") - willReturnScopesForAuthTokens(authorizationTokens, Set("openid:hmrc-enrolments")) + willReturnScopesForAuthTokens(accessToken, Set("openid:hmrc-enrolments")) willAuthoriseWith(200) And("The Auth token has a NINO") @@ -498,7 +531,12 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart When("We request the user information") val result = Http(s"$serviceUrl") - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json")) + .headers( + Seq("Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("The user information is returned") @@ -519,7 +557,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart Scenario("fetch government gateway details only when scope contains 'openid:government-gateway'") { Given("A Auth token with 'openid:government-gateway' scopes") - willReturnScopesForAuthTokens(authorizationTokens, Set("openid:government-gateway")) + willReturnScopesForAuthTokens(accessToken, Set("openid:government-gateway")) willAuthoriseWith(200) And("The Auth token has a NINO") @@ -544,7 +582,14 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart When("We request the user information") val result = Http(s"$serviceUrl") - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json", "token" -> "ggToken")) + .headers( + Seq( + "Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "token" -> "ggToken", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("The user information is returned") @@ -567,14 +612,19 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart Scenario("return 401 when Auth returns Unauthorized") { Given("A Auth token with openid:government-gateway, openid:hmrc-enrolments, address scopes") - willReturnScopesForAuthTokens(authorizationTokens, Set("openid:government-gateway", "openid:hmrc-enrolments", "address")) + willReturnScopesForAuthTokens(accessToken, Set("openid:government-gateway", "openid:hmrc-enrolments", "address")) And("Auth returns unauthorized") willAuthoriseWith(401) When("We request the user information") val result = Http(s"$serviceUrl") - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json")) + .headers( + Seq("Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("Unauthorized status is returned") @@ -589,14 +639,19 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart val expectedErrorMessage = s"""{"code":"BAD_GATEWAY","message":"POST of 'http://localhost:$stubPort/auth/authorise' returned 503. Response body: '$errorMsg'"}""" Given("A Auth token with openid:government-gateway, openid:hmrc-enrolments, address scopes") - willReturnScopesForAuthTokens(authorizationTokens, Set("openid:government-gateway", "openid:hmrc-enrolments", "address")) + willReturnScopesForAuthTokens(accessToken, Set("openid:government-gateway", "openid:hmrc-enrolments", "address")) And("Auth returns unauthorized") willAuthoriseWith(503, errorMsg) When("We request the user information") val result = Http(s"$serviceUrl") - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json")) + .headers( + Seq("Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("Bad gateway status is returned") @@ -609,14 +664,19 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart val expectedErrorMessage = s"""{"code":"BAD_GATEWAY","message":"POST of 'http://localhost:$stubPort/auth/authorise' returned 404 (Not Found). Response body: '$errorMsg'"}""" Given("A Auth token with openid:government-gateway, openid:hmrc-enrolments, address scopes") - willReturnScopesForAuthTokens(authorizationTokens, Set("openid:government-gateway", "openid:hmrc-enrolments", "address")) + willReturnScopesForAuthTokens(accessToken, Set("openid:government-gateway", "openid:hmrc-enrolments", "address")) And("Auth returns not found") willAuthoriseWith(404, errorMsg) When("We request the user information") val result = Http(s"$serviceUrl") - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json")) + .headers( + Seq("Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("Bad gateway status is returned") @@ -631,7 +691,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart "'email' and 'openid:government-gateway' scopes" ) willReturnScopesForAuthTokens( - authorizationTokens, + accessToken, Set( "openid", "profile", @@ -658,7 +718,14 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart When("We request the user information") val result = Http(s"$serviceUrl") .options(HttpOptions.readTimeout(1000000), HttpOptions.connTimeout(1000000)) - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json", "token" -> "ggToken")) + .headers( + Seq( + "Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "token" -> "ggToken", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("The user information is returned") @@ -673,7 +740,7 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart "'email' and 'openid:government-gateway' scopes" ) willReturnScopesForAuthTokens( - authorizationTokens, + accessToken, Set( "openid", "profile", @@ -700,7 +767,14 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart When("We request the user information") val result = Http(s"$serviceUrl") .options(HttpOptions.readTimeout(1000000), HttpOptions.connTimeout(1000000)) - .headers(Seq("Authorization" -> s"Bearer $authorizationTokens", "Accept" -> "application/vnd.hmrc.1.0+json", "token" -> "ggToken")) + .headers( + Seq( + "Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "token" -> "ggToken", + "X-Client-Authorization-Token" -> "ACCESS_TOKEN" + ) + ) .asString Then("The user information is returned") @@ -708,6 +782,54 @@ class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPart } + Scenario("fetching user info returns 401 then we return 401 when X-Client-Authorization-Token header missing") { + + Given( + "A Auth token with 'openid', 'profile', 'address', 'openid:gov-uk-identifiers', 'openid:hmrc-enrolments', 'openid:mdtp'," + + "'email' and 'openid:government-gateway' scopes" + ) + willReturnScopesForAuthTokens( + accessToken, + Set( + "openid", + "profile", + "address", + "openid:gov-uk-identifiers", + "openid:hmrc-enrolments", + "openid:government-gateway", + "email", + "agentInformation", + "openid:mdtp" + ) + ) + willAuthoriseWith(200) + + And("The Auth token has a NINO") + willReturnAuthorityWith(Nino(nino)) + + And("The authority has enrolments") + willReturnEnrolmentsWith() + + And("The auth will user details call will fail with 400") + willFindUserFailed(409) + + When("We request the user information without the X-Client-Authorization-Token header") + val result = Http(s"$serviceUrl") + .options(HttpOptions.readTimeout(1000000), HttpOptions.connTimeout(1000000)) + .headers( + Seq( + "Authorization" -> s"Bearer $authorizationTokens", + "Accept" -> "application/vnd.hmrc.1.0+json", + "token" -> "ggToken" + ) + ) + .asString + + Then("The user information is not returned") + result.code shouldBe 401 + + } + } } diff --git a/it/stubs/ThirdPartyDelegatedAuthorityStub.scala b/it/stubs/ThirdPartyDelegatedAuthorityStub.scala index 324730b..22ea01f 100644 --- a/it/stubs/ThirdPartyDelegatedAuthorityStub.scala +++ b/it/stubs/ThirdPartyDelegatedAuthorityStub.scala @@ -21,10 +21,10 @@ import com.github.tomakehurst.wiremock.stubbing.StubMapping import play.api.libs.json.Json trait ThirdPartyDelegatedAuthorityStub { - def willReturnScopesForAuthTokens(authorizationTokens: String, scopes: Set[String]): StubMapping = { + def willReturnScopesForAuthTokens(accessToken: String, scopes: Set[String]): StubMapping = { stubFor( get(urlPathEqualTo(s"/delegated-authority")) - .withHeader("internal-auth-header", equalTo(s"Bearer $authorizationTokens")) + .withHeader("access-token", equalTo(accessToken)) .willReturn(aResponse().withBody(s""" |{"token": | { diff --git a/test/connectors/ThirdPartyDelegatedAuthorityConnectorSpec.scala b/test/connectors/ThirdPartyDelegatedAuthorityConnectorSpec.scala index b7cd9c1..079ddc9 100644 --- a/test/connectors/ThirdPartyDelegatedAuthorityConnectorSpec.scala +++ b/test/connectors/ThirdPartyDelegatedAuthorityConnectorSpec.scala @@ -39,6 +39,8 @@ class ThirdPartyDelegatedAuthorityConnectorSpec extends UnitSpec with MockitoSug trait Setup { implicit val hc: HeaderCarrier = HeaderCarrier() + val accessToken = "ACCESS_TOKEN" + val mockAppContext: AppContext = mock[AppContext] when(mockAppContext.thirdPartyDelegatedAuthorityUrl).thenReturn(wireMockUrl) @@ -60,11 +62,10 @@ class ThirdPartyDelegatedAuthorityConnectorSpec extends UnitSpec with MockitoSug "fetchScopes" should { "return the scopes of the delegated authority" in new Setup { - val authorizationTokens = "AUTH_TOKENs" stubFor( get(urlPathMatching(s"/delegated-authority")) - .withHeader("internal-auth-header", equalTo(authorizationTokens)) + .withHeader("access-token", equalTo(accessToken)) .willReturn( aResponse() .withStatus(200) @@ -78,21 +79,20 @@ class ThirdPartyDelegatedAuthorityConnectorSpec extends UnitSpec with MockitoSug ) ) - val scopes: Set[String] = await(connector.fetchScopes(authorizationTokens)) + val scopes: Set[String] = await(connector.fetchScopes(accessToken)) scopes shouldBe Set("scope1", "scope2") } "return an empty set when delegated authority is not found" in new Setup { - val authorizationTokens = "AUTH_TOKENS" stubFor( get(urlPathMatching(s"/delegated-authority")) - .withHeader("internal-auth-header", equalTo(authorizationTokens)) + .withHeader("access-token", equalTo(accessToken)) .willReturn(aResponse().withStatus(404)) ) - val scopes: Set[String] = await(connector.fetchScopes(authorizationTokens)) + val scopes: Set[String] = await(connector.fetchScopes(accessToken)) scopes shouldBe Set() } diff --git a/test/services/UserInfoServiceSpec.scala b/test/services/UserInfoServiceSpec.scala index 8be1cc3..f2343d4 100644 --- a/test/services/UserInfoServiceSpec.scala +++ b/test/services/UserInfoServiceSpec.scala @@ -27,8 +27,7 @@ import testSupport.UnitSpec import uk.gov.hmrc.auth.core.retrieve.{ItmpAddress, ItmpName} import uk.gov.hmrc.auth.core.{Enrolment, EnrolmentIdentifier, Enrolments} import uk.gov.hmrc.domain.Nino -import uk.gov.hmrc.http.Authorization -import uk.gov.hmrc.http.{BadRequestException, HeaderCarrier} +import uk.gov.hmrc.http.{Authorization, BadRequestException, HeaderCarrier, UnauthorizedException} import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.{ExecutionContext, Future} @@ -37,6 +36,8 @@ class UserInfoServiceSpec extends UnitSpec with MockitoSugar with ScalaFutures { val nino = Nino("AB123456A") val authorizationTokens = "Bearer AUTH_TOKENS" + val accessToken = "ACCESS_TOKEN" + val otherHeaders = Seq(("X-Client-Authorization-Token", accessToken)) val desUserInfo = DesUserInfo(ItmpName(Some("John"), None, Some("Smith")), None, ItmpAddress(Some("1 Station Road"), Some("Town Centre"), None, None, None, None, None, None) @@ -76,7 +77,7 @@ class UserInfoServiceSpec extends UnitSpec with MockitoSugar with ScalaFutures { ) trait Setup { - implicit val headers = HeaderCarrier().copy(authorization = Some(Authorization(authorizationTokens))) + implicit val headers = HeaderCarrier().copy(authorization = Some(Authorization(authorizationTokens)), otherHeaders = otherHeaders) val mockAuthConnector: AuthConnector = mock[AuthConnectorV1] val mockUserInfoGenerator: UserInfoGenerator = mock[UserInfoGenerator] @@ -90,10 +91,10 @@ class UserInfoServiceSpec extends UnitSpec with MockitoSugar with ScalaFutures { "LiveUserInfoService" should { - "requests all available data" in new Setup { + "requests all available data when access token in otherHeaders" in new Setup { val scopes = Set("openid", "address", "profile", "openid:gov-uk-identifiers", "openid:hmrc-enrolments", "email", "openid:government-gateway") - given(mockThirdPartyDelegatedAuthorityConnector.fetchScopes(eqTo(authorizationTokens))(eqTo(headers), any[ExecutionContext])).willReturn(scopes) + given(mockThirdPartyDelegatedAuthorityConnector.fetchScopes(eqTo(accessToken))(eqTo(headers), any[ExecutionContext])).willReturn(scopes) given(mockAuthConnector.fetchAuthority()(eqTo(headers), any[ExecutionContext])).willReturn(Some(authority)) given(mockAuthConnector.fetchEnrolments()(eqTo(headers), any[ExecutionContext])).willReturn(Some(enrolments)) given(mockAuthConnector.fetchDesUserInfo()(eqTo(headers), any[ExecutionContext])).willReturn(Some(desUserInfo)) @@ -116,9 +117,14 @@ class UserInfoServiceSpec extends UnitSpec with MockitoSugar with ScalaFutures { verify(mockAuthConnector).fetchUserDetails()(any[HeaderCarrier], any[ExecutionContext]) } + "should fail with UnauthorizedException when access token is not in the headers" in new Setup { + val headersWithoutAccessToken = headers.copy(otherHeaders = Seq.empty) + a[UnauthorizedException] should be thrownBy await(liveInfoService.fetchUserInfo(Version_1_0)(headersWithoutAccessToken)) + } + "should fail with BadRequestException when the NINO is not in the authority and a scope that requires a NINO is requested UNICORN" in new Setup { val scopes = Set("address", "profile", "openid:gov-uk-identifiers", "openid:hmrc-enrolments") - given(mockThirdPartyDelegatedAuthorityConnector.fetchScopes(eqTo(authorizationTokens))(eqTo(headers), any[ExecutionContext])).willReturn(scopes) + given(mockThirdPartyDelegatedAuthorityConnector.fetchScopes(eqTo(accessToken))(eqTo(headers), any[ExecutionContext])).willReturn(scopes) given(mockAuthConnector.fetchAuthority()(eqTo(headers), any[ExecutionContext])).willReturn(Future(Some(authority.copy(nino = None)))) given(mockAuthConnector.fetchEnrolments()(eqTo(headers), any[ExecutionContext])).willReturn(Future(None)) @@ -128,7 +134,7 @@ class UserInfoServiceSpec extends UnitSpec with MockitoSugar with ScalaFutures { "does not request DES::fetchUserInfo when the scopes does not contain 'address' nor 'profile'" in new Setup { val scopes = Set("openid:gov-uk-identifiers", "openid:hmrc-enrolments") - given(mockThirdPartyDelegatedAuthorityConnector.fetchScopes(eqTo(authorizationTokens))(eqTo(headers), any[ExecutionContext])).willReturn(scopes) + given(mockThirdPartyDelegatedAuthorityConnector.fetchScopes(eqTo(accessToken))(eqTo(headers), any[ExecutionContext])).willReturn(scopes) given(mockAuthConnector.fetchAuthority()(eqTo(headers), any[ExecutionContext])).willReturn(Some(authority)) given(mockAuthConnector.fetchEnrolments()(eqTo(headers), any[ExecutionContext])).willReturn(Future(Some(enrolments))) given(mockUserInfoTransformer.transform(eqTo(scopes), eqTo(Some(authority)), eqTo(None), eqTo(Some(enrolments)), eqTo(None))) @@ -144,7 +150,7 @@ class UserInfoServiceSpec extends UnitSpec with MockitoSugar with ScalaFutures { "does not request AUTH::fetchNino nor DES::fetchUserInfo when the scopes does not contain 'address' nor 'profile' nor 'openid:gov-uk-identifiers'" in new Setup { val scopes = Set("openid:hmrc-enrolments") - given(mockThirdPartyDelegatedAuthorityConnector.fetchScopes(eqTo(authorizationTokens))(eqTo(headers), any[ExecutionContext])).willReturn(scopes) + given(mockThirdPartyDelegatedAuthorityConnector.fetchScopes(eqTo(accessToken))(eqTo(headers), any[ExecutionContext])).willReturn(scopes) given(mockAuthConnector.fetchAuthority()(eqTo(headers), any[ExecutionContext])).willReturn(Some(authority)) given(mockAuthConnector.fetchEnrolments()(eqTo(headers), any[ExecutionContext])).willReturn(Some(enrolments)) @@ -161,7 +167,7 @@ class UserInfoServiceSpec extends UnitSpec with MockitoSugar with ScalaFutures { "does not request AUTH::fetchEnrolments when the scopes does not contain 'openid:hmrc-enrolments'" in new Setup { val scopes = Set("address", "profile", "openid:gov-uk-identifiers") - given(mockThirdPartyDelegatedAuthorityConnector.fetchScopes(eqTo(authorizationTokens))(eqTo(headers), any[ExecutionContext])).willReturn(scopes) + given(mockThirdPartyDelegatedAuthorityConnector.fetchScopes(eqTo(accessToken))(eqTo(headers), any[ExecutionContext])).willReturn(scopes) given(mockAuthConnector.fetchAuthority()(eqTo(headers), any[ExecutionContext])).willReturn(Some(authority)) given(mockAuthConnector.fetchDesUserInfo()(eqTo(headers), any[ExecutionContext])).willReturn(None)