diff --git a/README.md b/README.md index a6150ca07..b1755ff2d 100644 --- a/README.md +++ b/README.md @@ -464,8 +464,24 @@ There are 3 API's endpoint related to webhooks: 2. `PUT ../banks/BANK_ID/account-web-hooks` - Enable/Disable an Account Webhook 3. `GET ../management/banks/BANK_ID/account-web-hooks` - Get Account Webhooks --- -## OAuth 2.0 -In order to enable an OAuth2 workflow at an instance of OBP-API backend app you need to setup next props: + +## OpenID Connect +In order to enable an OIDC workflow at an instance of OBP-API portal app(login functionality) you need to set-up the following props: +```props +# Google as an identity provider +# openid_connect_1.client_secret=OYdWujJl******_NXzPlDI4T +# openid_connect_1.client_id=883**3244***-s4hi72j0rble0iiivq1gn09k7***tdci.apps.googleusercontent.com +# openid_connect_1.callback_url=http://127.0.0.1:8080/auth/openid-connect/callback +# openid_connect_1.endpoint.authorization=https://accounts.google.com/o/oauth2/v2/auth +# openid_connect_1.endpoint.userinfo=https://openidconnect.googleapis.com/v1/userinfo +# openid_connect_1.endpoint.token=https://oauth2.googleapis.com/token +# openid_connect_1.endpoint.jwks_uri=https://www.googleapis.com/oauth2/v3/certs +# openid_connect_1.access_type_offline=false +``` +Please note in the example above you MUST run OBP-API portal at the URL: http://127.0.0.1:8080 + +## OAuth 2.0 Authentication +In order to enable an OAuth2 workflow at an instance of OBP-API backend app you need to set-up the following props: ``` # -- OAuth 2 --------------------------------------------------------------------------------- # Enable/Disable OAuth 2 workflow at a server instance diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 40cd066f6..d75fc082e 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -546,6 +546,7 @@ super_admin_user_ids=USER_ID1,USER_ID2, ## registered on OBP localy. # openid_connect.enabled=true # First identity provider +# openid_connect_1.button_text = Google # openid_connect_1.client_secret=OYdWujJlU7fFOW_NXzPlDI4T # openid_connect_1.client_id=883773244832-s4hi72j0rble0iiivq1gn09k7vvptdci.apps.googleusercontent.com # openid_connect_1.callback_url=http://127.0.0.1:8080/auth/openid-connect/callback @@ -555,6 +556,7 @@ super_admin_user_ids=USER_ID1,USER_ID2, # openid_connect_1.endpoint.jwks_uri=https://www.googleapis.com/oauth2/v3/certs # openid_connect_1.access_type_offline=true ## Second identity provder +# openid_connect_2.button_text = name of 2nd provider # openid_connect_2.client_secret=OYdWujJlU7fFOW_NXzPlDI4T # openid_connect_2.client_id=883773244832-s4hi72j0rble0iiivq1gn09k7vvptdci.apps.googleusercontent.com # openid_connect_2.callback_url=http://127.0.0.1:8080/auth/openid-connect/callback @@ -673,7 +675,7 @@ featured_apis=elasticSearchWarehouseV300 # Enable/Disable execution of migration scripts. # In case isn't defined default value is "false" # Note: migration_scripts.execute MUST be true for the other two props values (list_of_migration_scripts_to_execute and migration_scripts) to have any effect. -# migration_scripts.execute=false +# migration_scripts.enabled=false # Define list of migration scripts to execute. # List is not ordered. # list_of_migration_scripts_to_execute=dummyScript diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 43e2ca7cc..ff90ec144 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -1766,7 +1766,7 @@ Returns a string showed to the developer ) def requireScopes(role: ApiRole) = { - ApiProperty.requireScopesForAllRoles match { + ApiPropsWithAlias.requireScopesForAllRoles match { case false => getPropsValue("enable_scopes_for_roles").toList.map(_.split(",")).flatten.exists(_ == role.toString()) case true => diff --git a/obp-api/src/main/scala/code/api/util/ApiProperty.scala b/obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala similarity index 83% rename from obp-api/src/main/scala/code/api/util/ApiProperty.scala rename to obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala index 62db3ea72..6b5724f75 100644 --- a/obp-api/src/main/scala/code/api/util/ApiProperty.scala +++ b/obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala @@ -11,11 +11,19 @@ import net.liftweb.common.Full * 2. We introduce a new name "require_scopes_for_all_roles" * 3. We have to support all instances with old name in order to allow smooth transition from the old to the new name. */ -object ApiProperty extends MdcLoggable { - - val requireScopesForAllRoles = getValueByNameOrAliasAsBoolean("require_scopes_for_all_roles", "require_scopes", "false") - +object ApiPropsWithAlias { + import HelperFunctions._ + val requireScopesForAllRoles = getValueByNameOrAliasAsBoolean( + name="require_scopes_for_all_roles", + alias="require_scopes", + defaultValue="false") + val migrationScriptsEnabled = getValueByNameOrAliasAsBoolean( + name="migration_scripts.enabled", + alias="migration_scripts.execute", + defaultValue="false") +} +object HelperFunctions extends MdcLoggable { /** * Workflow of get property with boolean value * @@ -39,13 +47,13 @@ object ApiProperty extends MdcLoggable { * @param alias The alias of a property * @return true/false */ - private def getValueByNameOrAliasAsBoolean(name: String, alias: String, defaultValue: String): Boolean = { + private[util] def getValueByNameOrAliasAsBoolean(name: String, alias: String, defaultValue: String): Boolean = { getValueByNameOrAlias(name, alias, defaultValue).toBoolean } /** * Workflow of get property with string value * - 1st try 2nd try + 1st try 2nd try get +---------------+ +---------------+ property | | no match | | no match +----------->+ Name +------------------->+ Alias +----------+ @@ -65,17 +73,18 @@ object ApiProperty extends MdcLoggable { * @param alias The alias of a property * @return value/default value */ - private def getValueByNameOrAlias(name: String, alias: String, defaultValue: String): String = { + private[util] def getValueByNameOrAlias(name: String, alias: String, defaultValue: String): String = { (getPropsValue(name), getPropsValue(alias)) match { case (Full(actual), Full(deprecated)) => // Both properties are defined. Use actual one and log warning. {true/false} - logger.warn(s"The props file has defined actual property name $name as well as deprecated $alias. The deprecated one is ignored!") + logger.warn(s"The props file has defined actual property $name as well as deprecated $alias. The deprecated one is ignored!") actual case (Full(actual), _) => // Only actual name of the property is defined. {true/false} actual case (_, Full(deprecated)) => // Only deprecated name of the property is defined. {true/false} + logger.warn(s"The props file uses deprecated property $alias. Please use $name instead of it") deprecated case _ => // Not defined. {false} defaultValue } } -} +} \ No newline at end of file diff --git a/obp-api/src/main/scala/code/api/util/migration/Migration.scala b/obp-api/src/main/scala/code/api/util/migration/Migration.scala index 0a80f1b14..022287b20 100644 --- a/obp-api/src/main/scala/code/api/util/migration/Migration.scala +++ b/obp-api/src/main/scala/code/api/util/migration/Migration.scala @@ -4,7 +4,7 @@ import java.sql.{ResultSet, SQLException} import java.text.SimpleDateFormat import java.util.Date -import code.api.util.APIUtil +import code.api.util.{APIUtil, ApiPropsWithAlias} import code.api.util.APIUtil.{getPropsAsBoolValue, getPropsValue} import code.consumer.Consumers import code.customer.CustomerX @@ -18,13 +18,12 @@ import scala.collection.immutable import scala.collection.mutable.HashMap object Migration extends MdcLoggable { - + private val migrationScriptsEnabled = ApiPropsWithAlias.migrationScriptsEnabled private val executeAll = getPropsAsBoolValue("migration_scripts.execute_all", false) - private val execute = getPropsAsBoolValue("migration_scripts.execute", false) private val scriptsToExecute: immutable.Seq[String] = getPropsValue("list_of_migration_scripts_to_execute").toList.map(_.split(",")).flatten private def executeScript(blockOfCode: => Boolean): Boolean = { - if(execute) blockOfCode else execute + if(migrationScriptsEnabled) blockOfCode else migrationScriptsEnabled } private def runOnce(name: String)(blockOfCode: => Boolean): Boolean = { diff --git a/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala b/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala index 65f30df8f..35ede1ef7 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala @@ -31,7 +31,7 @@ import java.util.Date import java.util.regex.Pattern import code.actorsystem.ObpActorConfig -import code.api.util.{APIUtil, ApiProperty, CustomJsonFormats} +import code.api.util.{APIUtil, ApiPropsWithAlias, CustomJsonFormats} import code.api.util.APIUtil.{MessageDoc, getPropsValue} import code.api.v1_2_1.BankRoutingJsonV121 import com.openbankproject.commons.model.{AccountRoutingJsonV121, AmountOfMoneyJsonV121} @@ -808,7 +808,7 @@ object JSONFactory220 extends CustomJsonFormats { val scopes = ScopesJSON( - ApiProperty.requireScopesForAllRoles, + ApiPropsWithAlias.requireScopesForAllRoles, getPropsValue("enable_scopes_for_roles").toList.map(_.split(",")).flatten ) diff --git a/obp-api/src/main/scala/code/snippet/OpenIDConnectSnippet.scala b/obp-api/src/main/scala/code/snippet/OpenIDConnectSnippet.scala new file mode 100644 index 000000000..fc38cf7fb --- /dev/null +++ b/obp-api/src/main/scala/code/snippet/OpenIDConnectSnippet.scala @@ -0,0 +1,35 @@ +package code.snippet + +import code.api.util.APIUtil +import code.util.Helper.MdcLoggable +import net.liftweb.util.{CssSel, PassThru} +import net.liftweb.util.Helpers._ + +import scala.xml.NodeSeq + +class OpenIDConnectSnippet extends MdcLoggable{ + + @transient protected val log = logger + + def getFirstButtonText: CssSel = { + val text = APIUtil.getPropsValue("openid_connect_1.button_text", "OIDC 1") + "#open-id-connect-button-1 *" #> scala.xml.Unparsed(text) + } + def getSecondButtonText: CssSel = { + val text = APIUtil.getPropsValue("openid_connect_2.button_text", "OIDC 2") + "#open-id-connect-button-1 *" #> scala.xml.Unparsed(text) + } + + def showFirstButton = + if (APIUtil.getPropsValue("openid_connect_1.client_id").isEmpty) + "*" #> NodeSeq.Empty + else + PassThru + + def showSecondButton = + if (APIUtil.getPropsValue("openid_connect_2.client_id").isEmpty) + "*" #> NodeSeq.Empty + else + PassThru + +} diff --git a/obp-api/src/main/webapp/templates-hidden/_login.html b/obp-api/src/main/webapp/templates-hidden/_login.html index 52327f8db..287ee80e5 100644 --- a/obp-api/src/main/webapp/templates-hidden/_login.html +++ b/obp-api/src/main/webapp/templates-hidden/_login.html @@ -35,19 +35,19 @@ Recover password -