Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GG-6854 - Restrict test dependencies to test scope (Security issue) #89

Merged
merged 15 commits into from
May 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
version = 3.7.2
runner.dialect = scala213
maxColumn = 150
lineEndings = unix
importSelectors = singleLine
rewriteTokens = {
"⇒": "=>"
"→": "->"
"←": "<-"
}

project {
git = true
}

align {
preset = more
tokens = [
":",
"extends",
Copy link

@ModisR ModisR May 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add ":" to these tokens to maintain alignment of type annotations in parameter lists. The Scalariform config had something to align parameter type annotations so continuing the tradition with Scalafmt will make the diff a little quieter.

{code = "=", owner = "Term.Assign"},
{code = "=>", owner = "Case|Type.Arg.ByName"},
"<-", "->", "%", "%%",
"should", "shouldBe", "shouldEqual", "shouldNot", "must"
]
arrowEnumeratorGenerator = true
openParenCallSite = true
openParenDefnSite = true
closeParenSite = true
}
danglingParentheses.callSite = true

binPack {
parentConstructors = false
}

continuationIndent {
callSite = 2
defnSite = 2
}

newlines {
penalizeSingleSelectMultiArgList = false
sometimesBeforeColonInMethodReturnType = true
afterCurlyLambdaParams = keep
}

rewrite {
rules = [RedundantBraces, RedundantParens, AsciiSortImports]
redundantBraces {
maxLines = 100
methodBodies = false
stringInterpolation = true
generalExpressions = false
}
}

spaces {
inImportCurlyBraces = false
beforeContextBoundColon = Never
}
14 changes: 4 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,13 @@ User details data structures follow the OpenId Connect UserInfo specification (s
You can dive deeper into the documentation in the [API Developer Hub](https://developer.service.hmrc.gov.uk/api-documentation/docs/api#openid-connect-userinfo).

## Running Locally
Run the service `sbt run -Drun.mode=Dev`

Install [Service Manager](https://github.com/hmrc/service-manager), if you want live endpoints, then start dependencies:
Run the tests & test coverage report `sbt clean compile coverage test it:test coverageReport`

sm --start AUTH -f
sm --start DATASTREAM -f
Run the service in service manager; if you want live endpoints, then start dependencies thus: `sm --start AUTH DATASTREAM -r`

Start the app:

sbt run -Drun.mode=Dev

Now you can test sandbox:

curl -v http://localhost:9000/sandbox/userinfo -H 'Accept: application/vnd.hmrc.1.0+json'
Now you can test the sandbox `curl -v http://localhost:9000/sandbox/userinfo -H 'Accept: application/vnd.hmrc.1.0+json'`

### License

Expand Down
7 changes: 4 additions & 3 deletions app/config/APIAccessConfig.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 HM Revenue & Customs
* Copyright 2023 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,7 +18,7 @@ package config

import com.typesafe.config.{Config, ConfigObject}

import collection.JavaConverters._
import scala.jdk.CollectionConverters._

case class APIAccessConfig(version: String, status: String, accessType: String, endpointsEnabled: Boolean, whiteListedApplicationIds: List[String])

Expand All @@ -29,7 +29,8 @@ case class APIAccessVersions(versionConfigs: Option[ConfigObject]) {

val accessType = if (value.hasPath("type")) value.getString("type") else "PRIVATE"
val status = if (value.hasPath("status")) value.getString("status") else throw new IllegalArgumentException("Status missing")
val allowListedApplicationIds = if (value.hasPath("allow-list.applicationIds")) Some(value.getStringList("allow-list.applicationIds").asScala.toList) else None
val allowListedApplicationIds =
if (value.hasPath("allow-list.applicationIds")) Some(value.getStringList("allow-list.applicationIds").asScala.toList) else None
val endpointsEnabled = if (value.hasPath("endpointsEnabled")) value.getBoolean("endpointsEnabled") else false
val versionNumber = version.replace('_', '.')

Expand Down
16 changes: 8 additions & 8 deletions app/config/AppContext.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 HM Revenue & Customs
* Copyright 2023 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -25,12 +25,12 @@ import uk.gov.hmrc.play.bootstrap.config.ServicesConfig
class AppContext @Inject() (val runModeConfiguration: Configuration, environment: Environment) extends ServicesConfig(runModeConfiguration) {
protected def mode: Mode = environment.mode

lazy val appName: String = runModeConfiguration.get[String]("appName")
lazy val appUrl: String = runModeConfiguration.get[String]("appUrl")
lazy val authUrl: String = baseUrl("auth")
lazy val appName: String = runModeConfiguration.get[String]("appName")
lazy val appUrl: String = runModeConfiguration.get[String]("appUrl")
lazy val authUrl: String = baseUrl("auth")
lazy val thirdPartyDelegatedAuthorityUrl: String = baseUrl("third-party-delegated-authority")
lazy val access: Option[ConfigObject] = runModeConfiguration.getOptional[ConfigObject]("api.access.version")
lazy val desEnvironment: String = runModeConfiguration.get[String](s"microservice.services.des.environment")
lazy val desBearerToken: String = runModeConfiguration.get[String](s"microservice.services.des.bearer-token")
lazy val logUserInfoResponsePayload: Boolean = runModeConfiguration.underlying.getBoolean("log-user-info-response-payload")
lazy val access: Option[ConfigObject] = runModeConfiguration.getOptional[ConfigObject]("api.access.version")
lazy val desEnvironment: String = runModeConfiguration.get[String](s"microservice.services.des.environment")
lazy val desBearerToken: String = runModeConfiguration.get[String](s"microservice.services.des.bearer-token")
lazy val logUserInfoResponsePayload: Boolean = runModeConfiguration.underlying.getBoolean("log-user-info-response-payload")
}
2 changes: 1 addition & 1 deletion app/config/FeatureSwitch.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 HM Revenue & Customs
* Copyright 2023 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion app/config/GuiceModule.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 HM Revenue & Customs
* Copyright 2023 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
54 changes: 32 additions & 22 deletions app/connectors/AuthConnector.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 HM Revenue & Customs
* Copyright 2023 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,44 +31,54 @@ import scala.concurrent.{ExecutionContext, Future}
self: UserDetailsFetcher =>

val appContext: AppContext
val http: CorePost
val http: CorePost
val serviceUrl: String = appContext.authUrl

override def authConnector: AuthConnector = this

def fetchEnrolments()(implicit headerCarrier: HeaderCarrier, ec: ExecutionContext): Future[Option[Enrolments]] = {
authorised().retrieve(Retrievals.allEnrolments) {
enrolments => Future.successful(Some(enrolments))
}.recover {
case e: NotFoundException => None
}
authorised()
.retrieve(Retrievals.allEnrolments) { enrolments =>
Future.successful(Some(enrolments))
}
.recover { case e: NotFoundException =>
None
}
}

def fetchAuthority()(implicit headerCarrier: HeaderCarrier, ec: ExecutionContext): Future[Option[Authority]] = {
authorised().retrieve(Retrievals.credentials and Retrievals.nino) {
case credentials ~ nino => Future.successful(Some(Authority(credentials.providerId, nino)))
case _ => Future.successful(None)
}.recover {
case e: NotFoundException => None
}
authorised()
.retrieve(Retrievals.credentials and Retrievals.nino) {
case credentials ~ nino => Future.successful(Some(Authority(credentials.providerId, nino)))
case _ => Future.successful(None)
}
.recover { case e: NotFoundException =>
None
}
}

def fetchUserDetails()(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Option[UserDetails]] = self.fetchDetails()(hc, ec)

def fetchDesUserInfo()(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Option[DesUserInfo]] = {
val nothing = Future.successful(None)
authorised().retrieve(Retrievals.allItmpUserDetails) {
case name ~ dateOfBirth ~ address =>
Future.successful(Some(DesUserInfo(name, dateOfBirth, address)))
case _ => nothing
}.recoverWith {
case ex: NotFoundException => nothing
}
authorised()
.retrieve(Retrievals.allItmpUserDetails) {
case name ~ dateOfBirth ~ address =>
Future.successful(Some(DesUserInfo(name, dateOfBirth, address)))
case _ => nothing
}
.recoverWith { case ex: NotFoundException =>
nothing
}
}
}

@Singleton
class AuthConnectorV1 @Inject() (val appContext: AppContext, val http: CorePost)(implicit val executionContext: ExecutionContext) extends AuthConnector with AuthV1UserDetailsFetcher
class AuthConnectorV1 @Inject() (val appContext: AppContext, val http: CorePost)(implicit val executionContext: ExecutionContext)
extends AuthConnector
with AuthV1UserDetailsFetcher

@Singleton
class AuthConnectorV2 @Inject() (val appContext: AppContext, val http: CorePost)(implicit val executionContext: ExecutionContext) extends AuthConnector with AuthV2UserDetailsFetcher
class AuthConnectorV2 @Inject() (val appContext: AppContext, val http: CorePost)(implicit val executionContext: ExecutionContext)
extends AuthConnector
with AuthV2UserDetailsFetcher
60 changes: 34 additions & 26 deletions app/connectors/AuthV1UserDetailsFetcher.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 HM Revenue & Customs
* Copyright 2023 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,30 +28,38 @@ import scala.concurrent.{ExecutionContext, Future}
self: AuthorisedFunctions =>

def fetchDetails()(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Option[UserDetails]] = {
authorised().retrieve(Retrievals.allUserDetails and Retrievals.mdtpInformation and Retrievals.gatewayInformation) {
case credentials ~ name ~ birthDate ~ postCode ~ email ~ affinityGroup ~ agentCode ~ agentInformation ~
credentialRole ~ description ~ groupId ~ mdtp ~ gatewayInformation =>
Future.successful(Some(UserDetails(authProviderId = Some(credentials.providerId),
authProviderType = Some(credentials.providerType),
name = name.name,
lastName = name.lastName,
dateOfBirth = birthDate,
postCode = postCode,
email = email,
affinityGroup = affinityGroup.map(_.toString()),
agentCode = agentCode,
agentFriendlyName = agentInformation.agentFriendlyName,
credentialRole = credentialRole.map(_.toString),
description = description,
groupIdentifier = groupId,
agentId = agentInformation.agentId,
gatewayInformation = gatewayInformation,
mdtpInformation = mdtp,
None,
None)))
case _ => Future.successful(None)
}.recover {
case e: NotFoundException => None
}
authorised()
.retrieve(Retrievals.allUserDetails and Retrievals.mdtpInformation and Retrievals.gatewayInformation) {
case credentials ~ name ~ birthDate ~ postCode ~ email ~ affinityGroup ~ agentCode ~ agentInformation ~
credentialRole ~ description ~ groupId ~ mdtp ~ gatewayInformation =>
Future.successful(
Some(
UserDetails(
authProviderId = Some(credentials.providerId),
authProviderType = Some(credentials.providerType),
name = name.name,
lastName = name.lastName,
dateOfBirth = birthDate,
postCode = postCode,
email = email,
affinityGroup = affinityGroup.map(_.toString()),
agentCode = agentCode,
agentFriendlyName = agentInformation.agentFriendlyName,
credentialRole = credentialRole.map(_.toString),
description = description,
groupIdentifier = groupId,
agentId = agentInformation.agentId,
gatewayInformation = gatewayInformation,
mdtpInformation = mdtp,
None,
None
)
)
)
case _ => Future.successful(None)
}
.recover { case e: NotFoundException =>
None
}
}
}
62 changes: 36 additions & 26 deletions app/connectors/AuthV2UserDetailsFetcher.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 HM Revenue & Customs
* Copyright 2023 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,31 +28,41 @@ trait AuthV2UserDetailsFetcher extends UserDetailsFetcher {
self: AuthorisedFunctions =>

def fetchDetails()(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Option[UserDetails]] = {
authorised().retrieve(Retrievals.allUserDetails and Retrievals.mdtpInformation and Retrievals.gatewayInformation and Retrievals.profile and Retrievals.groupProfile) {
case credentials ~ maybeName ~ birthDate ~ postCode ~ email ~ affinityGroup ~ agentCode ~ agentInformation ~
credentialRole ~ description ~ groupId ~ mdtp ~ gatewayInformation ~ profile ~ groupProfile =>
Future.successful(Some(UserDetails(authProviderId = credentials.map(_.providerId),
authProviderType = credentials.map(_.providerType),
name = maybeName.flatMap(_.name),
lastName = maybeName.flatMap(_.lastName),
dateOfBirth = birthDate,
postCode = postCode,
email = email,
affinityGroup = affinityGroup.map(_.toString()),
agentCode = agentCode,
agentFriendlyName = agentInformation.agentFriendlyName,
credentialRole = credentialRole.map(_.toString),
description = description,
groupIdentifier = groupId,
agentId = agentInformation.agentId,
gatewayInformation = gatewayInformation,
mdtpInformation = mdtp,
profile = profile,
groupProfile = groupProfile)))
case _ => Future.successful(None)
}.recover {
case e: NotFoundException => None
}
authorised()
.retrieve(
Retrievals.allUserDetails and Retrievals.mdtpInformation and Retrievals.gatewayInformation and Retrievals.profile and Retrievals.groupProfile
) {
case credentials ~ maybeName ~ birthDate ~ postCode ~ email ~ affinityGroup ~ agentCode ~ agentInformation ~
credentialRole ~ description ~ groupId ~ mdtp ~ gatewayInformation ~ profile ~ groupProfile =>
Future.successful(
Some(
UserDetails(
authProviderId = credentials.map(_.providerId),
authProviderType = credentials.map(_.providerType),
name = maybeName.flatMap(_.name),
lastName = maybeName.flatMap(_.lastName),
dateOfBirth = birthDate,
postCode = postCode,
email = email,
affinityGroup = affinityGroup.map(_.toString()),
agentCode = agentCode,
agentFriendlyName = agentInformation.agentFriendlyName,
credentialRole = credentialRole.map(_.toString),
description = description,
groupIdentifier = groupId,
agentId = agentInformation.agentId,
gatewayInformation = gatewayInformation,
mdtpInformation = mdtp,
profile = profile,
groupProfile = groupProfile
)
)
)
case _ => Future.successful(None)
}
.recover { case e: NotFoundException =>
None
}
}

}
2 changes: 1 addition & 1 deletion app/connectors/ThirdPartyDelegatedAuthorityConnector.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 HM Revenue & Customs
* Copyright 2023 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion app/connectors/UserDetailsFetcher.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 HM Revenue & Customs
* Copyright 2023 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Loading