Skip to content

Commit e2643f5

Browse files
authored
feat: support provider:client for IAS app-to-app (#986)
1 parent 9323423 commit e2643f5

File tree

3 files changed

+132
-7
lines changed

3 files changed

+132
-7
lines changed

cloudplatform/cloudplatform-connectivity/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/BtpServiceOptions.java

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -211,21 +211,73 @@ public static OptionsEnhancer<?> withoutTokenForTechnicalProviderUser()
211211
}
212212

213213
/**
214-
* Creates an {@link OptionsEnhancer} that instructs an IAS-based destination to use the given application
215-
* provider name when performing token retrievals. This is needed in <b>App-To-App</b> communication scenarios.
214+
* Creates an {@link OptionsEnhancer} that instructs an IAS-based destination to use the given "Dependency Name"
215+
* when performing token retrievals. This is needed in <b>App-To-App</b> communication scenarios.
216216
* <p>
217217
* <b>Hint:</b> This option is <b>mutually exclusive</b> with {@link #withConsumerClient(String)}.
218218
*
219219
* @param applicationName
220-
* The name of the application provider to be used. This is the name that was used to register the
221-
* to-be-called application within the IAS tenant.
220+
* The name of the "Dependency Name" to be used. This is the name that was used to register the
221+
* dependency to an API of a provider application within the IAS tenant.
222222
* @return An instance of {@link OptionsEnhancer} that will lead to the given application provider being used
223223
* when retrieving an authentication token from the IAS service.
224+
*
225+
* @see <a href=
226+
* "https://help.sap.com/docs/cloud-identity-services/cloud-identity-services/consume-apis-from-other-applications?locale=en-US">Consuming
227+
* APIs from Other Applications</a>
224228
*/
225229
@Nonnull
226230
public static OptionsEnhancer<?> withApplicationName( @Nonnull final String applicationName )
227231
{
228-
return new IasCommunicationOptions(applicationName, null, null);
232+
return new IasCommunicationOptions(applicationName, null, null, null, null);
233+
}
234+
235+
/**
236+
* Creates an {@link OptionsEnhancer} that instructs an IAS-based destination to use the given provider client
237+
* ID when performing token retrievals. This is needed in <b>App-To-App</b> communication scenarios.
238+
* <p>
239+
* <b>Hint:</b> This option is <b>mutually exclusive</b> with {@link #withConsumerClient(String)}.
240+
*
241+
* @param providerClientId
242+
* Client ID of the provider application
243+
* @return An instance of {@link OptionsEnhancer} that will lead to the given application provider being used
244+
* when retrieving an authentication token from the IAS service.
245+
*
246+
* @see <a href=
247+
* "https://help.sap.com/docs/cloud-identity-services/cloud-identity-services/consume-apis-from-other-applications?locale=en-US">Consuming
248+
* APIs from Other Applications</a>
249+
*/
250+
@Nonnull
251+
public static OptionsEnhancer<?> withProviderClient( @Nonnull final String providerClientId )
252+
{
253+
return new IasCommunicationOptions(null, providerClientId, null, null, null);
254+
}
255+
256+
/**
257+
* Creates an {@link OptionsEnhancer} that instructs an IAS-based destination to use the given provider client
258+
* ID and provider tenant ID when performing token retrievals. This is needed in <b>App-To-App</b> communication
259+
* scenarios when having dependencies to <i>different tenants</i> of the <i>same, multi-tenant</i> provider
260+
* application (fan-out / 1-N).
261+
* <p>
262+
* <b>Hint:</b> This option is <b>mutually exclusive</b> with {@link #withConsumerClient(String)}
263+
*
264+
* @param providerClientId
265+
* Client ID of the provider application
266+
* @param providerTenantId
267+
* Tenant ID of the provider application
268+
* @return An instance of {@link OptionsEnhancer} that will lead to the given application provider being used
269+
* when retrieving an authentication token from the IAS service.
270+
*
271+
* @see <a href=
272+
* "https://help.sap.com/docs/cloud-identity-services/cloud-identity-services/consume-apis-from-other-applications?locale=en-US">Consuming
273+
* APIs from Other Applications</a>
274+
*/
275+
@Nonnull
276+
public static
277+
OptionsEnhancer<?>
278+
withProviderClient( @Nonnull final String providerClientId, @Nonnull final String providerTenantId )
279+
{
280+
return new IasCommunicationOptions(null, providerClientId, providerTenantId, null, null);
229281
}
230282

231283
/**
@@ -243,7 +295,7 @@ public static OptionsEnhancer<?> withApplicationName( @Nonnull final String appl
243295
@Nonnull
244296
public static OptionsEnhancer<?> withConsumerClient( @Nonnull final String consumerClientId )
245297
{
246-
return new IasCommunicationOptions(null, consumerClientId, null);
298+
return new IasCommunicationOptions(null, null, null, consumerClientId, null);
247299
}
248300

249301
/**
@@ -269,7 +321,7 @@ public static OptionsEnhancer<?> withConsumerClient( @Nonnull final String consu
269321
OptionsEnhancer<?>
270322
withConsumerClient( @Nonnull final String consumerClientId, @Nonnull final String consumerTenantId )
271323
{
272-
return new IasCommunicationOptions(null, consumerClientId, consumerTenantId);
324+
return new IasCommunicationOptions(null, null, null, consumerClientId, consumerTenantId);
273325
}
274326

275327
/**
@@ -315,6 +367,10 @@ public static class IasCommunicationOptions implements OptionsEnhancer<IasCommun
315367
@Nullable
316368
String applicationName;
317369
@Nullable
370+
String providerClientId;
371+
@Nullable
372+
String providerTenantId;
373+
@Nullable
318374
String consumerClientId;
319375
@Nullable
320376
String consumerTenantId;

cloudplatform/connectivity-oauth/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/BtpServicePropertySuppliers.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,15 @@ private void attachIasCommunicationOptions( @Nonnull final OAuth2Options.Builder
210210
return;
211211
}
212212

213+
if( o.getProviderClientId() != null ) {
214+
String resource = "urn:sap:identity:application:provider:clientid:" + o.getProviderClientId();
215+
if( o.getProviderTenantId() != null ) {
216+
resource += ":apptid:" + o.getProviderTenantId();
217+
}
218+
optionsBuilder.withTokenRetrievalParameter("resource", resource);
219+
return;
220+
}
221+
213222
if( o.getConsumerClientId() != null ) {
214223
String value = "urn:sap:identity:consumer:clientid:" + o.getConsumerClientId();
215224
if( o.getConsumerTenantId() != null ) {

cloudplatform/connectivity-oauth/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/BtpServicePropertySuppliersTest.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,66 @@ void testClientIdWithTenantId()
589589
PROVIDER_TENANT_ID));
590590
}
591591

592+
@Test
593+
void testProviderClientId()
594+
{
595+
@SuppressWarnings( "deprecation" )
596+
final ServiceBindingDestinationOptions options =
597+
ServiceBindingDestinationOptions
598+
.forService(BINDING)
599+
.withOption(IasOptions.withProviderClient("provider-client-id"))
600+
.build();
601+
602+
final OAuth2PropertySupplier sut = IDENTITY_AUTHENTICATION.resolve(options);
603+
604+
assertThat(sut).isNotNull();
605+
assertThat(sut.getTokenUri()).hasToString(PROVIDER_URL + "/oauth2/token");
606+
assertThat(sut.getServiceUri()).hasToString(PROVIDER_URL);
607+
608+
final OAuth2Options oAuth2Options = sut.getOAuth2Options();
609+
assertThat(oAuth2Options.skipTokenRetrieval()).isFalse();
610+
assertThat(oAuth2Options.getClientKeyStore()).isNotNull();
611+
assertThatClientCertificateIsContained(oAuth2Options.getClientKeyStore());
612+
assertThat(oAuth2Options.getAdditionalTokenRetrievalParameters())
613+
.containsExactlyInAnyOrderEntriesOf(
614+
Map
615+
.of(
616+
"resource",
617+
"urn:sap:identity:application:provider:clientid:provider-client-id",
618+
"app_tid",
619+
PROVIDER_TENANT_ID));
620+
}
621+
622+
@Test
623+
void testProviderClientIdWithTenantId()
624+
{
625+
@SuppressWarnings( "deprecation" )
626+
final ServiceBindingDestinationOptions options =
627+
ServiceBindingDestinationOptions
628+
.forService(BINDING)
629+
.withOption(IasOptions.withProviderClient("provider-client-id", "provider-tenant-id"))
630+
.build();
631+
632+
final OAuth2PropertySupplier sut = IDENTITY_AUTHENTICATION.resolve(options);
633+
634+
assertThat(sut).isNotNull();
635+
assertThat(sut.getTokenUri()).hasToString(PROVIDER_URL + "/oauth2/token");
636+
assertThat(sut.getServiceUri()).hasToString(PROVIDER_URL);
637+
638+
final OAuth2Options oAuth2Options = sut.getOAuth2Options();
639+
assertThat(oAuth2Options.skipTokenRetrieval()).isFalse();
640+
assertThat(oAuth2Options.getClientKeyStore()).isNotNull();
641+
assertThatClientCertificateIsContained(oAuth2Options.getClientKeyStore());
642+
assertThat(oAuth2Options.getAdditionalTokenRetrievalParameters())
643+
.containsExactlyInAnyOrderEntriesOf(
644+
Map
645+
.of(
646+
"resource",
647+
"urn:sap:identity:application:provider:clientid:provider-client-id:apptid:provider-tenant-id",
648+
"app_tid",
649+
PROVIDER_TENANT_ID));
650+
}
651+
592652
@AllArgsConstructor
593653
private enum MutualTlsForTechnicalProviderAuthenticationTest
594654
{

0 commit comments

Comments
 (0)