Skip to content

Commit 883db98

Browse files
mohitc1CopilotCopilot
authored
Add provisionResourceAccountCredentials API to Common's DRCA, Fixes AB#3450074 (#3086)
## Summary Adds the `provisionResourceAccountCredentials` IPC API to `DeviceRegistrationClientApplication` (DRCA) enabling OneAuth consumers to provision resource account credentials via the broker. Also adds Teams IP Phone (Sakurai) app entries to `AppRegistry`. ## Changes ### New API: `provisionResourceAccountCredentials` - Added `provisionResourceAccountCredentials(tenantId, raObjectId, correlationId, sdkType, sdkVersion)` to `DeviceRegistrationClientApplication` - `sdkType` (`SdkType`) and `sdkVersion` (`String`) are required parameters - Returns an `AccountRecord` for the provisioned resource account ### Protocol Files - Added `ProvisionResourceAccountCredentialsV0Parameters` — V0 wire params (correlationId, tenantId, raObjectId, sdkType, sdkVersion) - Added `ProvisionResourceAccountCredentialsV0Response` — V0 wire response carrying `AccountRecord` - Renamed protocol constant to `PROVISION_RESOURCE_ACCOUNT_CREDENTIALS_V0` ### AppRegistry - Added `IPPHONE_PROD` and `IPPHONE_DEBUG` entries for Teams IP Phone (Sakurai) devices using existing constants from `AuthenticationConstants` ### Tests - Added `provisionResourceAccountCredentials_returnsAccountRecord` unit test to `DeviceRegistrationClientApplicationTest` ## Files Changed | File | Change | |------|--------| | `DeviceRegistrationClientApplication.kt` | New `provisionResourceAccountCredentials` method | | `ProvisionResourceAccountCredentialsV0Parameters.java` | New V0 protocol params (Java + Lombok) | | `ProvisionResourceAccountCredentialsV0Response.java` | New V0 protocol response (Java + Lombok) | | `DeviceRegistrationProtocolConstants.java` | Renamed constant | | `AppRegistry.kt` | Added IPPhone entries | | `DeviceRegistrationClientApplicationTest.kt` | New unit test | | `changelog.txt` | Added vNext entry | ## Companion PR - **Broker**: https://github.com/identity-authnz-teams/ad-accounts-for-android/pull/153 ## Work Item Fixes [AB#3450074](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3450074) --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: mohitc1 <22034758+mohitc1@users.noreply.github.com>
1 parent aaf68b4 commit 883db98

7 files changed

Lines changed: 155 additions & 30 deletions

File tree

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
vNext
22
----------
3+
- [MINOR] Add provisionResourceAccountCredentials API to DeviceRegistrationClientApplication with V0 protocol params/response and add IPPhone to AppRegistry (#3086)
34
- [PATCH] Extend filter-then-clone optimization to deleteAccessTokensWithIntersectingScopes and add telemetry attributes (#3114)
45
- [PATCH] Wire ClientDataInfo through AcquireTokenResult, exceptions (#3109)
56
- [MINOR] Add additional step ID and blocking error constants for full onboarding telemetry coverage (#3117)

common/src/main/java/com/microsoft/identity/common/internal/apps/AppRegistry.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import com.microsoft.identity.common.adal.internal.AuthenticationConstants.Broke
2929
import com.microsoft.identity.common.adal.internal.AuthenticationConstants.Broker.INTUNE_APP_PACKAGE_NAME
3030
import com.microsoft.identity.common.adal.internal.AuthenticationConstants.Broker.INTUNE_APP_SHA512_DEBUG_SIGNATURE
3131
import com.microsoft.identity.common.adal.internal.AuthenticationConstants.Broker.INTUNE_APP_SHA512_RELEASE_SIGNATURE
32+
import com.microsoft.identity.common.adal.internal.AuthenticationConstants.Broker.IPPHONE_APP_PACKAGE_NAME
33+
import com.microsoft.identity.common.adal.internal.AuthenticationConstants.Broker.IPPHONE_APP_SHA512_DEBUG_SIGNATURE
34+
import com.microsoft.identity.common.adal.internal.AuthenticationConstants.Broker.IPPHONE_APP_SHA512_RELEASE_SIGNATURE
3235
import com.microsoft.identity.common.adal.internal.AuthenticationConstants.Broker.ONE_AUTH_TEST_APP_SIGNATURE
3336
import com.microsoft.identity.common.adal.internal.AuthenticationConstants.Broker.SHARED_EDGE_SIGNATURE
3437
import com.microsoft.identity.common.internal.broker.BrokerData
@@ -112,6 +115,18 @@ object AppRegistry {
112115
signingCertificateThumbprint = INTUNE_APP_SHA512_DEBUG_SIGNATURE
113116
)
114117

118+
val TEAMS_IPPHONE_PROD = App(
119+
nickName = "Teams IP Phone - Teams Devices (prod)",
120+
packageName = IPPHONE_APP_PACKAGE_NAME,
121+
signingCertificateThumbprint = IPPHONE_APP_SHA512_RELEASE_SIGNATURE
122+
)
123+
124+
val TEAMS_IPPHONE_DEBUG = App(
125+
nickName = "Teams IP Phone - Teams Devices (debug)",
126+
packageName = IPPHONE_APP_PACKAGE_NAME,
127+
signingCertificateThumbprint = IPPHONE_APP_SHA512_DEBUG_SIGNATURE
128+
)
129+
115130
val MSAL_TEST_APP = App(
116131
nickName = "MSAL Test App",
117132
packageName = "com.msft.identity.client.sample.local",
@@ -145,12 +160,14 @@ object AppRegistry {
145160
add(BrokerData.prodCompanyPortal)
146161
add(INTUNE_CE_PROD)
147162
add(INTUNE_AOSP_AGENT_PROD)
163+
add(TEAMS_IPPHONE_PROD)
148164
if (BrokerData.getShouldTrustDebugBrokers()) {
149165
add(INTUNE_AOSP_AGENT_DEBUG)
150166
add(BrokerData.debugBrokerHost)
151167
add(BrokerData.debugMicrosoftAuthenticator)
152168
add(BrokerData.debugCompanyPortal)
153169
add(INTUNE_CE_DEBUG)
170+
add(TEAMS_IPPHONE_DEBUG)
154171
}
155172
}
156173

common/src/main/java/com/microsoft/identity/deviceregistration/api/DeviceRegistrationClientApplication.kt

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import com.microsoft.identity.deviceregistration.java.protocol.parameters.GetIns
5252
import com.microsoft.identity.deviceregistration.java.protocol.parameters.GetRegistrationStateV0Parameters
5353
import com.microsoft.identity.deviceregistration.java.protocol.parameters.InstallCertificateSilentlyV0Parameters
5454
import com.microsoft.identity.deviceregistration.java.protocol.parameters.PreProvisionedBlobV0Parameters
55+
import com.microsoft.identity.deviceregistration.java.protocol.parameters.ProvisionResourceAccountCredentialsV0Parameters
5556
import com.microsoft.identity.deviceregistration.java.protocol.parameters.UnregisterDeviceV0Parameters
5657
import com.microsoft.identity.deviceregistration.java.protocol.response.DeviceRegistrationPreAuthorizedV0Response
5758
import com.microsoft.identity.deviceregistration.java.protocol.response.DeviceRegistrationWithTokensV0Response
@@ -62,6 +63,9 @@ import com.microsoft.identity.deviceregistration.java.protocol.response.GetInsta
6263
import com.microsoft.identity.deviceregistration.java.protocol.response.GetRegistrationStateV0Response
6364
import com.microsoft.identity.deviceregistration.java.protocol.response.InstallCertificateSilentlyV0Response
6465
import com.microsoft.identity.deviceregistration.java.protocol.response.PreProvisionedBlobV0Response
66+
import com.microsoft.identity.deviceregistration.java.protocol.response.ProvisionResourceAccountCredentialsV0Response
67+
import com.microsoft.identity.common.java.dto.AccountRecord
68+
import com.microsoft.identity.common.java.request.SdkType
6569
import java.util.UUID
6670

6771
/**
@@ -89,7 +93,7 @@ class DeviceRegistrationClientApplication {
8993
mController = buildController(
9094
context,
9195
components,
92-
BrokerDiscoveryClientFactory.Companion.getInstanceForClientSdk(context, components),
96+
BrokerDiscoveryClientFactory.getInstanceForClientSdk(context, components),
9397
DeviceRegistrationIpcStrategiesProvider()
9498
)
9599
}
@@ -121,7 +125,7 @@ class DeviceRegistrationClientApplication {
121125
): AndroidDeviceRegistrationClientController {
122126
val cacheUpdater = ActiveBrokerCacheUpdater(
123127
context,
124-
ClientActiveBrokerCache.Companion.getBrokerSdkCache(components.storageSupplier)
128+
ClientActiveBrokerCache.getBrokerSdkCache(components.storageSupplier)
125129
)
126130
return AndroidDeviceRegistrationClientController(
127131
context,
@@ -432,4 +436,36 @@ class DeviceRegistrationClientApplication {
432436
return GetDeviceRegistrationRecordV0Response.create(responseSerialized)
433437
.deviceRegistrationRecord
434438
}
439+
440+
/**
441+
* Provisions resource account credentials for the specified tenant and resource account object ID.
442+
*
443+
* @param tenantId tenant ID for the resource account.
444+
* @param raObjectId resource account object ID (user ID in home tenant).
445+
* @param correlationId correlation ID for request tracing.
446+
* @param sdkType SDK type of the caller (required).
447+
* @param sdkVersion SDK version of the caller (required).
448+
* @param drsDiscoveryEndpoint discovery endpoint name. Default is "PROD".
449+
* @return [AccountRecord] representing the provisioned resource account credentials.
450+
*/
451+
@JvmOverloads
452+
@Throws(BaseException::class)
453+
fun provisionResourceAccountCredentials(
454+
tenantId: String,
455+
raObjectId: String,
456+
correlationId: UUID,
457+
sdkType: SdkType,
458+
sdkVersion: String,
459+
drsDiscoveryEndpoint: DrsDiscoveryEndpoint = DrsDiscoveryEndpoint.PROD
460+
): AccountRecord {
461+
val methodTag = "$TAG:provisionResourceAccountCredentials"
462+
Logger.info(methodTag, "ProvisionResourceAccountCredentials started. CorrelationId: $correlationId")
463+
val responseSerialized = mController.execute(
464+
ProvisionResourceAccountCredentialsV0Parameters(correlationId, tenantId, raObjectId, sdkType.name, sdkVersion, drsDiscoveryEndpoint.name)
465+
)
466+
val response = ProvisionResourceAccountCredentialsV0Response.create(responseSerialized)
467+
val result = response.accountRecord
468+
Logger.info(methodTag, "ProvisionResourceAccountCredentials ended successfully.")
469+
return result
470+
}
435471
}

common/src/test/java/com/microsoft/identity/deviceregistration/api/DeviceRegistrationClientApplicationTest.kt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ import com.microsoft.identity.deviceregistration.java.protocol.response.GetDevic
4141
import com.microsoft.identity.deviceregistration.java.protocol.response.GetDeviceRegistrationRecordsV0Response
4242
import com.microsoft.identity.deviceregistration.java.protocol.response.GetRegistrationStateV0Response
4343
import com.microsoft.identity.deviceregistration.java.protocol.response.PreProvisionedBlobV0Response
44+
import com.microsoft.identity.deviceregistration.java.protocol.parameters.ProvisionResourceAccountCredentialsV0Parameters
45+
import com.microsoft.identity.deviceregistration.java.protocol.response.ProvisionResourceAccountCredentialsV0Response
46+
import com.microsoft.identity.common.java.dto.AccountRecord
47+
import com.microsoft.identity.common.java.request.SdkType
4448
import org.junit.Assert
4549
import org.junit.Before
4650
import org.junit.Test
@@ -197,4 +201,50 @@ class DeviceRegistrationClientApplicationTest {
197201
drca.getPreProvisionedBlob("test-tenant", correlationId)
198202
// If we get here without exception, the correlationId was accepted and the flow completed
199203
}
204+
205+
@Test
206+
fun provisionResourceAccountCredentials_returnsAccountRecord() {
207+
val accountRecord = AccountRecord()
208+
accountRecord.homeAccountId = "uid.utid"
209+
accountRecord.localAccountId = "uid"
210+
accountRecord.username = "ra@test.com"
211+
accountRecord.environment = "login.microsoftonline.com"
212+
accountRecord.realm = "utid"
213+
val response = ProvisionResourceAccountCredentialsV0Response(UUID.randomUUID(), accountRecord)
214+
val drca = createDrca(successStrategy(packer.pack(response)))
215+
216+
val result = drca.provisionResourceAccountCredentials("utid", "uid", UUID.randomUUID(), SdkType.MSAL, "1.0.0")
217+
218+
Assert.assertNotNull(result)
219+
Assert.assertEquals("uid.utid", result.homeAccountId)
220+
Assert.assertEquals("uid", result.localAccountId)
221+
Assert.assertEquals("ra@test.com", result.username)
222+
Assert.assertEquals("login.microsoftonline.com", result.environment)
223+
Assert.assertEquals("utid", result.realm)
224+
}
225+
226+
@Test
227+
fun provisionResourceAccountCredentials_passesParamsToIpc() {
228+
val correlationId = UUID.randomUUID()
229+
val accountRecord = AccountRecord()
230+
val response = ProvisionResourceAccountCredentialsV0Response(UUID.randomUUID(), accountRecord)
231+
val strategy: IIpcStrategy = mock()
232+
whenever(strategy.getType()).thenReturn(IIpcStrategy.Type.CONTENT_PROVIDER)
233+
whenever(strategy.communicateToBroker(any())).thenAnswer { invocation ->
234+
val bundle = (invocation.arguments[0] as BrokerOperationBundle).bundle
235+
val protocolData = bundle?.getByteArray("protocol.data")
236+
Assert.assertNotNull(protocolData)
237+
val parameters = ProvisionResourceAccountCredentialsV0Parameters.create(protocolData)
238+
Assert.assertEquals(correlationId, parameters.correlationId)
239+
Assert.assertEquals("test-tenant", parameters.tenantId)
240+
Assert.assertEquals("test-ra-oid", parameters.raObjectId)
241+
Assert.assertEquals("MSAL", parameters.sdkType)
242+
Assert.assertEquals("1.0.0", parameters.sdkVersion)
243+
Assert.assertEquals("PROD", parameters.drsDiscoveryEndpoint)
244+
packer.pack(response)
245+
}
246+
247+
val drca = createDrca(strategy)
248+
drca.provisionResourceAccountCredentials("test-tenant", "test-ra-oid", correlationId, SdkType.MSAL, "1.0.0")
249+
}
200250
}

common4j/src/main/com/microsoft/identity/deviceregistration/java/protocol/DeviceRegistrationProtocolConstants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@ public final class DeviceRegistrationProtocolConstants {
3636
public static final String UNREGISTER_DEVICE_V0 = "protocol.unregister.v0";
3737
public static final String INSTALL_CERTIFICATE_SILENTLY_V0 = "protocol.install.certificate.silently.v0";
3838
public static final String GET_DEVICE_REGISTRATION_RECORD_VO = "get.device.registration.record.v0";
39-
public static final String PROVISION_RESOURCE_ACCOUNT_V0 = "protocol.provision.resource.account.v0";
39+
public static final String PROVISION_RESOURCE_ACCOUNT_CREDENTIALS_V0 = "protocol.provision.resource.account.credentials.v0";
4040
}

common4j/src/main/com/microsoft/identity/deviceregistration/java/protocol/parameters/ProvisionResourceAccountV0Parameters.java renamed to common4j/src/main/com/microsoft/identity/deviceregistration/java/protocol/parameters/ProvisionResourceAccountCredentialsV0Parameters.java

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,42 +22,48 @@
2222
// THE SOFTWARE.
2323
package com.microsoft.identity.deviceregistration.java.protocol.parameters;
2424

25+
import com.microsoft.identity.common.java.exception.ClientException;
2526
import com.microsoft.identity.deviceregistration.java.protocol.DeviceRegistrationProtocolConstants;
27+
import com.microsoft.identity.deviceregistration.java.protocol.packer.DeviceRegistrationProtocolMoshiSerializer;
28+
import com.microsoft.identity.deviceregistration.java.protocol.packer.IDeviceRegistrationProtocolSerializer;
2629

2730
import java.util.UUID;
2831

32+
import edu.umd.cs.findbugs.annotations.Nullable;
2933
import lombok.Getter;
3034
import lombok.NonNull;
3135
import lombok.experimental.Accessors;
3236

33-
import com.microsoft.identity.deviceregistration.java.protocol.packer.DeviceRegistrationProtocolMoshiSerializer;
34-
import com.microsoft.identity.deviceregistration.java.protocol.packer.IDeviceRegistrationProtocolSerializer;
35-
import com.microsoft.identity.common.java.exception.ClientException;
36-
3737
/**
38-
* Implements a protocol parameters for provisioning a resource account.
38+
* Implements protocol parameters for provisioning resource account credentials.
3939
*/
4040
@Accessors(prefix = "m")
41-
public class ProvisionResourceAccountV0Parameters extends AbstractDeviceRegistrationProtocolParameters {
41+
public class ProvisionResourceAccountCredentialsV0Parameters extends AbstractDeviceRegistrationProtocolParameters {
4242

43-
private static final IDeviceRegistrationProtocolSerializer<ProvisionResourceAccountV0Parameters> serializer
44-
= new DeviceRegistrationProtocolMoshiSerializer<>(ProvisionResourceAccountV0Parameters.class);
43+
private static final IDeviceRegistrationProtocolSerializer<ProvisionResourceAccountCredentialsV0Parameters> serializer
44+
= new DeviceRegistrationProtocolMoshiSerializer<>(ProvisionResourceAccountCredentialsV0Parameters.class);
4545

4646
/**
4747
* Creates a protocol object from a byte array (serialized protocol).
4848
*
4949
* @param serializedData protocol data serialized
5050
*/
51-
public static ProvisionResourceAccountV0Parameters create(final byte[] serializedData) throws ClientException {
51+
public static ProvisionResourceAccountCredentialsV0Parameters create(final byte[] serializedData) throws ClientException {
5252
return serializer.deserialize(serializedData);
5353
}
5454

55-
public ProvisionResourceAccountV0Parameters(@NonNull final UUID correlationId,
56-
@NonNull final String tenantId,
57-
@NonNull final String raObjectId) {
55+
public ProvisionResourceAccountCredentialsV0Parameters(@NonNull final UUID correlationId,
56+
@NonNull final String tenantId,
57+
@NonNull final String raObjectId,
58+
@Nullable final String sdkType,
59+
@Nullable final String sdkVersion,
60+
@Nullable final String drsDiscoveryEndpoint) {
5861
super(correlationId);
5962
mTenantId = tenantId;
6063
mRaObjectId = raObjectId;
64+
mSdkType = sdkType;
65+
mSdkVersion = sdkVersion;
66+
mDrsDiscoveryEndpoint = drsDiscoveryEndpoint;
6167
}
6268

6369
@Getter
@@ -68,10 +74,22 @@ public ProvisionResourceAccountV0Parameters(@NonNull final UUID correlationId,
6874
@NonNull
6975
private final String mRaObjectId;
7076

77+
@Getter
78+
@Nullable
79+
private final String mSdkType;
80+
81+
@Getter
82+
@Nullable
83+
private final String mSdkVersion;
84+
85+
@Getter
86+
@Nullable
87+
private final String mDrsDiscoveryEndpoint;
88+
7189
@Override
7290
@NonNull
7391
public String getProtocolName() {
74-
return DeviceRegistrationProtocolConstants.PROVISION_RESOURCE_ACCOUNT_V0;
92+
return DeviceRegistrationProtocolConstants.PROVISION_RESOURCE_ACCOUNT_CREDENTIALS_V0;
7593
}
7694

7795
/**

common4j/src/main/com/microsoft/identity/deviceregistration/java/protocol/response/ProvisionResourceAccountV0Response.java renamed to common4j/src/main/com/microsoft/identity/deviceregistration/java/protocol/response/ProvisionResourceAccountCredentialsV0Response.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,53 +22,56 @@
2222
// THE SOFTWARE.
2323
package com.microsoft.identity.deviceregistration.java.protocol.response;
2424

25+
import com.microsoft.identity.common.java.dto.AccountRecord;
26+
import com.microsoft.identity.common.java.exception.ClientException;
2527
import com.microsoft.identity.deviceregistration.java.protocol.DeviceRegistrationProtocolConstants;
28+
import com.microsoft.identity.deviceregistration.java.protocol.packer.DeviceRegistrationProtocolMoshiSerializer;
29+
import com.microsoft.identity.deviceregistration.java.protocol.packer.IDeviceRegistrationProtocolSerializer;
2630

2731
import java.util.UUID;
2832

2933
import lombok.Getter;
3034
import lombok.NonNull;
3135
import lombok.experimental.Accessors;
3236

33-
import com.microsoft.identity.deviceregistration.java.protocol.packer.DeviceRegistrationProtocolMoshiSerializer;
34-
import com.microsoft.identity.deviceregistration.java.protocol.packer.IDeviceRegistrationProtocolSerializer;
35-
import com.microsoft.identity.common.java.exception.ClientException;
36-
37+
/**
38+
* Response for the provision resource account credentials protocol.
39+
*/
3740
@Accessors(prefix = "m")
38-
public class ProvisionResourceAccountV0Response extends AbstractDeviceRegistrationProtocolResponse {
41+
public class ProvisionResourceAccountCredentialsV0Response extends AbstractDeviceRegistrationProtocolResponse {
3942

40-
private static final IDeviceRegistrationProtocolSerializer<ProvisionResourceAccountV0Response> serializer
41-
= new DeviceRegistrationProtocolMoshiSerializer<>(ProvisionResourceAccountV0Response.class);
43+
private static final IDeviceRegistrationProtocolSerializer<ProvisionResourceAccountCredentialsV0Response> serializer
44+
= new DeviceRegistrationProtocolMoshiSerializer<>(ProvisionResourceAccountCredentialsV0Response.class);
4245

4346
/**
4447
* Creates a protocol object from a byte array (serialized protocol).
4548
*
4649
* @param serializedData protocol data serialized
4750
*/
48-
public static ProvisionResourceAccountV0Response create(final byte[] serializedData) throws ClientException {
51+
public static ProvisionResourceAccountCredentialsV0Response create(final byte[] serializedData) throws ClientException {
4952
return serializer.deserialize(serializedData);
5053
}
5154

52-
public ProvisionResourceAccountV0Response(@NonNull final UUID correlationId,
53-
@NonNull final String result) {
55+
public ProvisionResourceAccountCredentialsV0Response(@NonNull final UUID correlationId,
56+
@NonNull final AccountRecord accountRecord) {
5457
super(correlationId);
55-
mResult = result;
58+
mAccountRecord = accountRecord;
5659
}
5760

5861
@Getter
5962
@NonNull
60-
private final String mResult;
63+
private final AccountRecord mAccountRecord;
6164

6265
/**
6366
* Returns the name of the protocol.
6467
*/
6568
@Override
6669
public String getProtocolName() {
67-
return DeviceRegistrationProtocolConstants.PROVISION_RESOURCE_ACCOUNT_V0;
70+
return DeviceRegistrationProtocolConstants.PROVISION_RESOURCE_ACCOUNT_CREDENTIALS_V0;
6871
}
6972

7073
/**
71-
* return the serialized the protocol.
74+
* Serialization is handled by the packer layer.
7275
*/
7376
@Override
7477
public byte[] serialize() {

0 commit comments

Comments
 (0)