From 99b6dda3e59f38b5894725035def0868ebbd6ab5 Mon Sep 17 00:00:00 2001 From: scott Date: Mon, 16 Apr 2018 17:28:42 +0100 Subject: [PATCH] Add individual auth check functionality --- .../{contexts => auth}/AuthContext.scala | 27 +- .../gov/hmrc/vatapi/config/AppContext.scala | 2 +- .../hmrc/vatapi/resources/BaseResource.scala | 2 +- .../services/AuthorisationService.scala | 12 +- .../gov/hmrc/support/BaseFunctionalSpec.scala | 302 ------------------ .../auth/MockAPIAuthorisedFunctions.scala | 8 +- .../services/AuthorisationServiceSpec.scala | 17 +- 7 files changed, 51 insertions(+), 319 deletions(-) rename app/uk/gov/hmrc/vatapi/{contexts => auth}/AuthContext.scala (63%) diff --git a/app/uk/gov/hmrc/vatapi/contexts/AuthContext.scala b/app/uk/gov/hmrc/vatapi/auth/AuthContext.scala similarity index 63% rename from app/uk/gov/hmrc/vatapi/contexts/AuthContext.scala rename to app/uk/gov/hmrc/vatapi/auth/AuthContext.scala index 60b0bfec..d154ba41 100644 --- a/app/uk/gov/hmrc/vatapi/contexts/AuthContext.scala +++ b/app/uk/gov/hmrc/vatapi/auth/AuthContext.scala @@ -14,7 +14,9 @@ * limitations under the License. */ -package uk.gov.hmrc.vatapi.contexts +package uk.gov.hmrc.vatapi.auth +import uk.gov.hmrc.auth.core.AffinityGroup +import AuthConstants._ sealed trait AuthContext { val affinityGroup: String @@ -24,12 +26,19 @@ sealed trait AuthContext { } case object Organisation extends AuthContext { - override val affinityGroup: String = "organisation" + override val affinityGroup: String = ORGANISATION override val agentCode: Option[String] = None override val agentReference: Option[String] = None override val userType = "OrgVatPayer" } +case object Individual extends AuthContext { + override val affinityGroup: String = INDIVIDUAL + override val agentCode: Option[String] = None + override val agentReference: Option[String] = None + override val userType = "IndVatPayer" +} + case class Agent(override val agentCode: Option[String], override val agentReference: Option[String]) extends AuthContext { override val affinityGroup: String = "agent" override val userType = "Agent" @@ -37,3 +46,17 @@ case class Agent(override val agentCode: Option[String], override val agentRefer case class VATAuthEnrolments(enrolmentToken: String, identifier: String, authRule: Option[String] = None) +object AffinityGroupToAuthContext { + def authContext(affinityGroup: AffinityGroup) = { + affinityGroup.getClass.getSimpleName.dropRight(1) match { + case ORGANISATION => Organisation + case INDIVIDUAL => Individual + } + } +} + +object AuthConstants { + val ORGANISATION = "Organisation" + val INDIVIDUAL = "Individual" +} + diff --git a/app/uk/gov/hmrc/vatapi/config/AppContext.scala b/app/uk/gov/hmrc/vatapi/config/AppContext.scala index b9ed9fad..239b0048 100644 --- a/app/uk/gov/hmrc/vatapi/config/AppContext.scala +++ b/app/uk/gov/hmrc/vatapi/config/AppContext.scala @@ -19,7 +19,7 @@ package uk.gov.hmrc.vatapi.config import play.api.Configuration import play.api.Play._ import uk.gov.hmrc.play.config.ServicesConfig -import uk.gov.hmrc.vatapi.contexts.VATAuthEnrolments +import uk.gov.hmrc.vatapi.auth.VATAuthEnrolments object AppContext extends ServicesConfig { private lazy val config = current.configuration diff --git a/app/uk/gov/hmrc/vatapi/resources/BaseResource.scala b/app/uk/gov/hmrc/vatapi/resources/BaseResource.scala index bb6a92bb..a2fd6cfe 100644 --- a/app/uk/gov/hmrc/vatapi/resources/BaseResource.scala +++ b/app/uk/gov/hmrc/vatapi/resources/BaseResource.scala @@ -22,8 +22,8 @@ import play.api.libs.concurrent.Execution.Implicits._ import play.api.mvc.{ActionBuilder, _} import uk.gov.hmrc.domain.Vrn import uk.gov.hmrc.play.microservice.controller.BaseController +import uk.gov.hmrc.vatapi.auth.{AuthContext, Organisation} import uk.gov.hmrc.vatapi.config.{AppContext, FeatureSwitch} -import uk.gov.hmrc.vatapi.contexts.{AuthContext, Organisation} import uk.gov.hmrc.vatapi.services.AuthorisationService import scala.concurrent.Future diff --git a/app/uk/gov/hmrc/vatapi/services/AuthorisationService.scala b/app/uk/gov/hmrc/vatapi/services/AuthorisationService.scala index 8fa9839f..c44c149e 100644 --- a/app/uk/gov/hmrc/vatapi/services/AuthorisationService.scala +++ b/app/uk/gov/hmrc/vatapi/services/AuthorisationService.scala @@ -26,9 +26,9 @@ import uk.gov.hmrc.auth.core.retrieve.{Retrievals, ~} import uk.gov.hmrc.auth.core.{Enrolment, Enrolments, _} import uk.gov.hmrc.domain.Vrn import uk.gov.hmrc.http.HeaderCarrier -import uk.gov.hmrc.vatapi.auth.APIAuthorisedFunctions +import uk.gov.hmrc.vatapi.auth.AffinityGroupToAuthContext._ +import uk.gov.hmrc.vatapi.auth.{APIAuthorisedFunctions, AffinityGroupToAuthContext, AuthContext} import uk.gov.hmrc.vatapi.config.AppContext -import uk.gov.hmrc.vatapi.contexts.{AuthContext, Organisation} import uk.gov.hmrc.vatapi.models.Errors import uk.gov.hmrc.vatapi.models.Errors.ClientOrAgentNotAuthorized @@ -62,10 +62,11 @@ trait AuthorisationService { aPIAuthorisedFunctions.authorised( RawJsonPredicate(JsArray.apply(Seq(Json.toJson(Enrolment(vatAuthEnrolments.enrolmentToken).withIdentifier(vatAuthEnrolments.identifier, vrn.vrn)))))) .retrieve(Retrievals.affinityGroup and Retrievals.authorisedEnrolments) { - case Some(AffinityGroup.Organisation) ~ enrolments => - logger.debug(s"[AuthorisationService] [authoriseAsClient] Authorisation succeeded as fully-authorised organisation " + + case retrieval@Some(AffinityGroup.Organisation|AffinityGroup.Individual) ~ enrolments => + val authAffinityGroup = retrieval.a.get + logger.debug(s"[AuthorisationService] [authoriseAsClient] Authorisation succeeded as fully-authorised ${authContext(authAffinityGroup).affinityGroup} " + s"for VRN ${getClientReference(enrolments).getOrElse("")}.") - Future.successful(Right(Organisation)) + Future.successful(Right(authContext(authAffinityGroup))) case _ => logger.error(s"[AuthorisationService] [authoriseAsClient] Authorisation failed due to unsupported affinity group.") Future.successful(Left(Forbidden(toJson(ClientOrAgentNotAuthorized)))) } recoverWith unauthorisedError @@ -83,5 +84,4 @@ trait AuthorisationService { Future.successful(Left(InternalServerError(toJson( Errors.InternalServerError("An internal server error occurred"))))) } - } diff --git a/func/uk/gov/hmrc/support/BaseFunctionalSpec.scala b/func/uk/gov/hmrc/support/BaseFunctionalSpec.scala index 46b03b55..730eb320 100644 --- a/func/uk/gov/hmrc/support/BaseFunctionalSpec.scala +++ b/func/uk/gov/hmrc/support/BaseFunctionalSpec.scala @@ -494,308 +494,6 @@ trait BaseFunctionalSpec extends TestApplication { this } - def userWithInsufficientConfidenceLevel: Givens = { - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .willReturn( - aResponse() - .withStatus(401) - .withHeader("Content-Length", "0") - .withHeader("WWW-Authenticate", - "MDTP detail=\"InsufficientConfidenceLevel\""))) - this - } - - def userIsPartiallyAuthorisedForTheResource: Givens = { - - // First call to auth to check if fully authorised should fail. - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .withRequestBody(containing("HMRC-MTD-IT")) - .willReturn( - aResponse() - .withStatus(401) - .withHeader("Content-Length", "0") - .withHeader("WWW-Authenticate", - "MDTP detail=\"InsufficientEnrolments\""))) - - // Second call to auth to check affinity is equal to 'Agent' should succeed. - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .withRequestBody(containing("Agent")) - .willReturn(aResponse() - .withStatus(200) - .withBody(""" - |{ - | "internalId": "some-id", - | "affinityGroup": "Agent", - | "agentCode": "some-agent-code", - | "loginTimes": { - | "currentLogin": "2016-11-27T09:00:00.000Z", - | "previousLogin": "2016-11-01T12:00:00.000Z" - | }, - | "authorisedEnrolments": [ - | { - | "key":"HMRC-AS-AGENT", - | "identifiers":[ - | { - | "key":"AgentReferenceNumber", - | "value":"1000051409" - | } - | ], - | "state":"Activated" - | } - | ] - |} - """.stripMargin))) - - // Third call to auth to check FOA subscription status should succeed. - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .withRequestBody(containing("HMRC-AS-AGENT")) - .willReturn(aResponse() - .withStatus(200) - .withBody(""" - |{ - | "internalId": "some-id", - | "affinityGroup": "Agent", - | "agentCode": "some-agent-code", - | "loginTimes": { - | "currentLogin": "2016-11-27T09:00:00.000Z", - | "previousLogin": "2016-11-01T12:00:00.000Z" - | }, - | "authorisedEnrolments": [ - | { - | "key":"HMRC-AS-AGENT", - | "identifiers":[ - | { - | "key":"AgentReferenceNumber", - | "value":"1000051409" - | } - | ], - | "state":"Activated" - | } - | ] - |} - """.stripMargin))) - - this - } - - def userIsNotPartiallyAuthorisedForTheResource: Givens = { - // First call to auth to check if fully authorised should fail. - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .withRequestBody(containing("HMRC-MTD-IT")) - .willReturn( - aResponse() - .withStatus(401) - .withHeader("Content-Length", "0") - .withHeader("WWW-Authenticate", - "MDTP detail=\"InsufficientEnrolments\""))) - - // Second call to auth to check affinity is equal to 'Agent' should succeed. - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .withRequestBody(containing("Agent")) - .willReturn(aResponse() - .withStatus(200) - .withBody(""" - |{ - | "internalId": "some-id", - | "affinityGroup": "Agent", - | "loginTimes": { - | "currentLogin": "2016-11-27T09:00:00.000Z", - | "previousLogin": "2016-11-01T12:00:00.000Z" - | } - |} - """.stripMargin))) - - // Third call to auth to check FOA subscription status should fail. - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .withRequestBody(containing("HMRC-AS-AGENT")) - .willReturn( - aResponse() - .withStatus(401) - .withHeader("Content-Length", "0") - .withHeader("WWW-Authenticate", - "MDTP detail=\"InsufficientEnrolments\""))) - - this - } - - def userIsPartiallyAuthorisedForTheResourceNoAgentCode: Givens = { - - // First call to auth to check if fully authorised should fail. - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .withRequestBody(containing("HMRC-MTD-IT")) - .willReturn( - aResponse() - .withStatus(401) - .withHeader("Content-Length", "0") - .withHeader("WWW-Authenticate", - "MDTP detail=\"InsufficientEnrolments\""))) - - // Second call to auth to check affinity is equal to 'Agent' should succeed. - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .withRequestBody(containing("Agent")) - .willReturn(aResponse() - .withStatus(200) - .withBody(""" - |{ - | "internalId": "some-id", - | "affinityGroup": "Agent", - | "loginTimes": { - | "currentLogin": "2016-11-27T09:00:00.000Z", - | "previousLogin": "2016-11-01T12:00:00.000Z" - | }, - | "authorisedEnrolments": [ - | { - | "key":"HMRC-AS-AGENT", - | "identifiers":[ - | { - | "key":"AgentReferenceNumber", - | "value":"1000051409" - | } - | ], - | "state":"Activated" - | } - | ] - |} - """.stripMargin))) - - // Third call to auth to check FOA subscription status should succeed. - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .withRequestBody(containing("HMRC-AS-AGENT")) - .willReturn(aResponse() - .withStatus(200) - .withBody(""" - |{ - | "internalId": "some-id", - | "affinityGroup": "Agent", - | "loginTimes": { - | "currentLogin": "2016-11-27T09:00:00.000Z", - | "previousLogin": "2016-11-01T12:00:00.000Z" - | }, - | "authorisedEnrolments": [ - | { - | "key":"HMRC-AS-AGENT", - | "identifiers":[ - | { - | "key":"AgentReferenceNumber", - | "value":"1000051409" - | } - | ], - | "state":"Activated" - | } - | ] - |} - """.stripMargin))) - - this - } - - def clientIsFullyAuthorisedForTheResource: Givens = { - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .willReturn( - aResponse() - .withStatus(200) - .withBody(""" - |{ - | "internalId": "some-id", - | "affinityGroup": "Individual", - | "loginTimes": { - | "currentLogin": "2016-11-27T09:00:00.000Z", - | "previousLogin": "2016-11-01T12:00:00.000Z" - | }, - | "authorisedEnrolments": [ - | { - | "key":"HMRC-AS-AGENT", - | "identifiers":[ - | { - | "key":"AgentReferenceNumber", - | "value":"1000051409" - | } - | ], - | "state":"Activated" - | } - | ] - |} - """.stripMargin))) - - this - } - - def agentIsFullyAuthorisedForTheResource: Givens = { - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .willReturn( - aResponse() - .withStatus(200) - .withBody(""" - |{ - | "internalId": "some-id", - | "affinityGroup": "Agent", - | "agentCode": "some-agent-code", - | "loginTimes": { - | "currentLogin": "2016-11-27T09:00:00.000Z", - | "previousLogin": "2016-11-01T12:00:00.000Z" - | }, - | "authorisedEnrolments": [ - | { - | "key":"HMRC-AS-AGENT", - | "identifiers":[ - | { - | "key":"AgentReferenceNumber", - | "value":"1000051409" - | } - | ], - | "state":"Activated" - | } - | ] - |} - """.stripMargin))) - - this - } - - def agentIsFullyAuthorisedForTheResourceNoAgentCode: Givens = { - stubFor( - post(urlPathEqualTo(s"/auth/authorise")) - .willReturn( - aResponse() - .withStatus(200) - .withBody(""" - |{ - | "internalId": "some-id", - | "affinityGroup": "Agent", - | "loginTimes": { - | "currentLogin": "2016-11-27T09:00:00.000Z", - | "previousLogin": "2016-11-01T12:00:00.000Z" - | }, - | "authorisedEnrolments": [ - | { - | "key":"HMRC-AS-AGENT", - | "identifiers":[ - | { - | "key":"AgentReferenceNumber", - | "value":"1000051409" - | } - | ], - | "state":"Activated" - | } - | ] - |} - """.stripMargin))) - - this - } - def userIsFullyAuthorisedForTheResource: Givens = { stubFor( post(urlPathEqualTo(s"/auth/authorise")) diff --git a/test/uk/gov/hmrc/vatapi/mocks/auth/MockAPIAuthorisedFunctions.scala b/test/uk/gov/hmrc/vatapi/mocks/auth/MockAPIAuthorisedFunctions.scala index e2443d11..ea8179dc 100644 --- a/test/uk/gov/hmrc/vatapi/mocks/auth/MockAPIAuthorisedFunctions.scala +++ b/test/uk/gov/hmrc/vatapi/mocks/auth/MockAPIAuthorisedFunctions.scala @@ -39,10 +39,14 @@ trait MockAPIAuthorisedFunctions extends UnitSpec with MockitoSugar with BeforeA override def beforeEach(): Unit = { super.beforeEach() reset(mockAPIAuthorisedFunctions) - setupMockAuthRetrievalSuccess(testAuthSuccessResponse) + setupMockAuthRetrievalSuccess(testAuthOrganisationSuccessResponse) } - val testAuthSuccessResponse = new ~(Option(AffinityGroup.Organisation), Enrolments(Set( + val testAuthOrganisationSuccessResponse = new ~(Option(AffinityGroup.Organisation), Enrolments(Set( + Enrolment("HMRC-MTD-VAT", Seq(EnrolmentIdentifier("VRN", "134567890")), "activated") + ))) + + val testAuthIndividualSuccessResponse = new ~(Option(AffinityGroup.Individual), Enrolments(Set( Enrolment("HMRC-MTD-VAT", Seq(EnrolmentIdentifier("VRN", "123456789")), "activated") ))) diff --git a/test/uk/gov/hmrc/vatapi/services/AuthorisationServiceSpec.scala b/test/uk/gov/hmrc/vatapi/services/AuthorisationServiceSpec.scala index b75ec1f2..c0f1bfac 100644 --- a/test/uk/gov/hmrc/vatapi/services/AuthorisationServiceSpec.scala +++ b/test/uk/gov/hmrc/vatapi/services/AuthorisationServiceSpec.scala @@ -29,7 +29,7 @@ import uk.gov.hmrc.auth.core.{InsufficientConfidenceLevel, UnsupportedAuthProvid import uk.gov.hmrc.domain.Vrn import uk.gov.hmrc.http.{HeaderCarrier, SessionKeys} import uk.gov.hmrc.vatapi.UnitSpec -import uk.gov.hmrc.vatapi.contexts.Organisation +import uk.gov.hmrc.vatapi.auth.{Individual, Organisation} import uk.gov.hmrc.vatapi.mocks.auth.MockAPIAuthorisedFunctions import uk.gov.hmrc.vatapi.models.Errors @@ -57,16 +57,23 @@ class AuthorisationServiceSpec extends UnitSpec with OneAppPerSuite with Mockito "TestAuthorisationService.authCheck" when { - lazy val testVrn: Vrn = Vrn("123456789") - lazy val invalidVrn: Vrn = Vrn("111111111") + val testVrn: Vrn = Vrn("123456789") + val invalidVrn: Vrn = Vrn("111111111") - "verify the auth with valid client details" should { + "verify the auth with valid organisation client details" should { "should return valid auth enrolments " in { - setupMockAuthRetrievalSuccess(testAuthSuccessResponse) + setupMockAuthRetrievalSuccess(testAuthOrganisationSuccessResponse) extractAwait(TestAuthorisationService.authCheck(testVrn)(hc, fakeRequestWithActiveSession, ec)) shouldBe Right(Organisation) } } + "verify the auth with valid individual client details" should { + "should return valid auth enrolments" in { + setupMockAuthRetrievalSuccess(testAuthIndividualSuccessResponse) + extractAwait(TestAuthorisationService.authCheck(testVrn)(hc, fakeRequestWithActiveSession, ec)) shouldBe Right(Individual) + } + } + "verify the auth with invalid client details" should { "should reject the client " in { setupMockAuthorisationException()