Skip to content

Commit a346e00

Browse files
committed
merge dev into feature/mfa-otp
2 parents fa49d9c + 3faf17b commit a346e00

21 files changed

Lines changed: 610 additions & 20 deletions

File tree

changelog.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
vNext
22
----------
3+
- [MINOR] Implement TenantUtil (#2761)
4+
- [MAJOR] Update proguard rules in common (#2756)
5+
- [MINOR] Add query parameter for Android Release OS Version (#2754)
6+
- [MINOR] Add client scenario to JwtRequestBody (#2755)
7+
8+
Version 22.1.0
9+
----------
310
- [PATCH] Fix Switch browser back stack (#2750)
411
- [MINOR] Move ests telemetry behind feature flag (#2742)
512
- [MINOR] Update Broker ATS flow for Resource Account (#2704)

common/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ dependencies {
174174
implementation "androidx.credentials:credentials-play-services-auth:$rootProject.ext.AndroidCredentialsVersion"
175175
implementation "com.google.android.gms:play-services-fido:$rootProject.ext.LegacyFidoApiVersion"
176176
implementation "com.google.android.libraries.identity.googleid:googleid:$rootProject.ext.GoogleIdVersion"
177+
implementation "com.github.stephenc.jcip:jcip-annotations:$rootProject.ext.jcipAnnotationVersion"
177178

178179
constraints {
179180
implementation ("com.squareup.okio:okio:3.4.0") {

common/consumer-rules.pro

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,33 @@
1717
#}
1818

1919
##---------------Begin: proguard configuration for Common --------
20-
# Intentionally blank, left to consumers of common to implement.
20+
# keep with optmizations and shrinking, but do not obfuscate
21+
-keep,allowoptimization,allowshrinking class !com.microsoft.identity.common.java.nativeauth.**, !com.microsoft.identity.common.nativeauth.**, com.microsoft.identity.** { *; }
22+
-keep class * extends com.microsoft.identity.common.java.authorities.Authority { *; }
23+
-keep class * extends com.microsoft.identity.common.java.authorities.AzureActiveDirectoryAudience { *; }
24+
-keep class * extends com.microsoft.identity.common.java.cache.ICacheRecord { *; }
25+
-keep class * extends com.microsoft.identity.common.java.cache.ITokenCacheItem { *; }
26+
-keep class * extends com.microsoft.identity.common.java.authscheme.AbstractAuthenticationScheme { *; }
27+
-keep class com.microsoft.identity.common.internal.broker.AuthUxJsonPayload { *; }
28+
29+
30+
#For Android Credential Manager: https://developer.android.com/training/sign-in/passkeys#proguard
31+
-if class androidx.credentials.CredentialManager
32+
-keep class androidx.credentials.playservices.** {
33+
*;
34+
}
35+
36+
# Runtime annotations
37+
-keep class net.jcip.annotations.GuardedBy
38+
-keep class net.jcip.annotations.Immutable
39+
-keep class net.jcip.annotations.ThreadSafe
40+
41+
# Compile time annotations
42+
-dontwarn edu.umd.cs.findbugs.annotations.NonNull
43+
-dontwarn edu.umd.cs.findbugs.annotations.Nullable
44+
-dontwarn edu.umd.cs.findbugs.annotations.SuppressFBWarnings
45+
46+
-keepattributes SourceFile,LineNumberTable
2147

2248
##---------------Begin: proguard configuration for Nimbus ----------
2349
# Intentionally blank, left to consumers of common to implement.
@@ -28,7 +54,7 @@
2854
##---------------Begin: proguard configuration for Gson --------
2955
# Gson uses generic type information stored in a class file when working with fields. Proguard
3056
# removes such information by default, so configure it to keep all of it.
31-
-keepattributes Signature
57+
-keepattributes Signature,SourceFile,LineNumberTable
3258

3359
# For using GSON @Expose annotation
3460
-keepattributes *Annotation*
@@ -37,26 +63,27 @@
3763
-dontwarn sun.misc.**
3864
#-keep class com.google.gson.stream.** { *; }
3965

40-
# Application classes that will be serialized/deserialized over Gson
41-
-keep class com.google.gson.examples.android.model.** { <fields>; }
42-
4366
# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
4467
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
4568
-keep class * extends com.google.gson.TypeAdapter
4669
-keep class * implements com.google.gson.TypeAdapterFactory
4770
-keep class * implements com.google.gson.JsonSerializer
4871
-keep class * implements com.google.gson.JsonDeserializer
72+
-keep class com.google.gson.reflect.TypeToken { *; }
73+
-keep class * extends com.google.gson.reflect.TypeToken { *; }
4974

75+
##---------------Begin: proguard configuration for OpenTelemetry --------
5076
# keep everything in this package from being removed or renamed
5177
-keep class io.opentelemetry.** { *; }
5278

5379
# Prevent R8 from leaving Data object members always null
54-
-keepclassmembers,allowobfuscation class * {
80+
-keepclassmembers class com.microsoft.identity.** {
5581
@com.google.gson.annotations.SerializedName <fields>;
82+
@com.squareup.moshi.Json <fields>;
5683
}
5784

58-
#For Android Credential Manager: https://developer.android.com/training/sign-in/passkeys#proguard
59-
-if class androidx.credentials.CredentialManager
60-
-keep class androidx.credentials.playservices.** {
61-
*;
62-
}
85+
## Other
86+
# Compile time annotation
87+
-dontwarn com.google.auto.value.AutoValue$CopyAnnotations
88+
-dontwarn com.google.auto.value.AutoValue
89+
-dontwarn com.google.auto.value.extension.memoized.Memoized

common/src/main/java/com/microsoft/identity/common/base64/AndroidBase64.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
// THE SOFTWARE.
2323
package com.microsoft.identity.common.base64
2424

25+
import androidx.annotation.Keep
2526
import com.microsoft.identity.common.java.base64.Base64Flags
2627
import com.microsoft.identity.common.java.base64.Base64Util
2728
import com.microsoft.identity.common.java.base64.IBase64
@@ -33,8 +34,9 @@ import com.microsoft.identity.common.java.base64.IBase64
3334
* you'll need to make change in [Base64Util] too.
3435
*
3536
* see [Base64Util] for more info.
37+
* This is called using reflection from [Base64Util], hence the @Keep annotation.
3638
**/
37-
39+
@Keep
3840
class AndroidBase64 : IBase64 {
3941

4042
override fun encode(input: ByteArray, vararg flags: Base64Flags): ByteArray {

common/src/main/java/com/microsoft/identity/common/internal/platform/AndroidDeviceMetadata.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,16 @@ public String getCpu() {
7373

7474
@Override
7575
public @NonNull String getOsForMats() {
76-
return android.os.Build.VERSION.RELEASE;
76+
return getAndroidReleaseOs();
7777
}
7878

7979
@Override
8080
public @NonNull String getOsForDrs() {
81+
return getAndroidReleaseOs();
82+
}
83+
84+
@Override
85+
public @NonNull String getAndroidReleaseOs() {
8186
return android.os.Build.VERSION.RELEASE;
8287
}
8388

common/src/main/java/com/microsoft/identity/common/internal/util/AndroidKeyStoreUtil.java

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
import edu.umd.cs.findbugs.annotations.Nullable;
5757
import io.opentelemetry.api.common.Attributes;
58+
import io.opentelemetry.api.common.AttributesBuilder;
5859
import io.opentelemetry.api.metrics.LongCounter;
5960
import lombok.NonNull;
6061

@@ -84,6 +85,11 @@ public class AndroidKeyStoreUtil {
8485
*/
8586
private static final String ANDROID_KEY_STORE_TYPE = "AndroidKeyStore";
8687

88+
/**
89+
* Max length of stack trace to search for a keystore exception
90+
*/
91+
private static int KEYSTORE_EXCEPTION_CAUSE_CHAIN_MAX_DEPTH = 20;
92+
8793
private AndroidKeyStoreUtil() {
8894
}
8995

@@ -447,12 +453,11 @@ public static synchronized SecretKey unwrap(@NonNull final byte[] wrappedKeyBlob
447453
exception
448454
);
449455
if (exception instanceof InvalidKeyException) {
450-
final Attributes attributes = Attributes.builder()
456+
final Attributes attributes = createAttributesBuilderFromInvalidKeyException((InvalidKeyException) exception)
451457
.put(AttributeName.keystore_operation.name(), "unwrap")
452458
.put(AttributeName.error_code.name(), errCode)
453-
.put(AttributeName.error_type.name(), clientException.getClass().getSimpleName())
454-
.put(AttributeName.keystore_exception_stack_trace.name(), ThrowableUtil.getStackTraceAsString(clientException))
455459
.build();
460+
456461
sFailedAndroidKeyStoreUnwrapOperationCount.add(1, attributes);
457462
}
458463
Logger.error(
@@ -464,4 +469,65 @@ public static synchronized SecretKey unwrap(@NonNull final byte[] wrappedKeyBlob
464469
throw clientException;
465470
}
466471

472+
/**
473+
* Populate attributes from an InvalidKeyException, attempting to extract details from a nested
474+
* KeyStoreException if available (API Level 33+).
475+
*/
476+
private static AttributesBuilder createAttributesBuilderFromInvalidKeyException(final InvalidKeyException exception) {
477+
String ksMessage;
478+
final String errorType;
479+
final String ksNumericErrorCode;
480+
481+
// Check API Level before attempting to extract KeyStoreException details
482+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
483+
final android.security.KeyStoreException keyStoreException = findKeyStoreException(exception);
484+
if (keyStoreException != null) {
485+
ksMessage = keyStoreException.getMessage();
486+
if (ksMessage == null) {
487+
ksMessage = "Keystore exception found, no error message";
488+
}
489+
errorType = "KeyStoreException";
490+
ksNumericErrorCode = String.valueOf(keyStoreException.getNumericErrorCode());
491+
} else {
492+
ksMessage = "No keystore exception found";
493+
errorType = "InvalidKeyException";
494+
ksNumericErrorCode = "";
495+
}
496+
} else {
497+
ksMessage = "API Level below 33, keystore exception not available";
498+
errorType = "InvalidKeyException";
499+
ksNumericErrorCode = "";
500+
}
501+
502+
return Attributes.builder()
503+
.put(AttributeName.error_type.name(), errorType)
504+
.put(AttributeName.keystore_exception_stack_trace.name(), ThrowableUtil.getStackTraceAsString(exception))
505+
.put(AttributeName.keystore_exception_message.name(), ksMessage)
506+
.put(AttributeName.keystore_numeric_error_code.name(), ksNumericErrorCode);
507+
}
508+
509+
/**
510+
* Searches the causal chain of the given throwable for an instance of
511+
* {@link android.security.KeyStoreException}.
512+
*
513+
* @param throwable The throwable to search.
514+
* @return The found KeyStoreException, or null if none was found or the API level is below 33.
515+
*/
516+
private static @Nullable android.security.KeyStoreException findKeyStoreException(@NonNull Throwable throwable) {
517+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
518+
// Check up to a max depth to avoid infinite loops in case of circular references
519+
int count = 0;
520+
while (throwable != null && count < KEYSTORE_EXCEPTION_CAUSE_CHAIN_MAX_DEPTH) {
521+
if (throwable instanceof android.security.KeyStoreException) {
522+
return (android.security.KeyStoreException) throwable;
523+
}
524+
throwable = throwable.getCause();
525+
count++;
526+
}
527+
528+
return null;
529+
} else {
530+
return null;
531+
}
532+
}
467533
}

common4j/src/main/com/microsoft/identity/common/java/commands/parameters/BrokerResourceAccountCommandParameters.java

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import lombok.EqualsAndHashCode;
3030
import lombok.Getter;
31+
import lombok.NonNull;
3132
import lombok.experimental.SuperBuilder;
3233

3334
/**
@@ -37,15 +38,54 @@
3738
@Getter
3839
@SuperBuilder(toBuilder = true)
3940
@EqualsAndHashCode(callSuper = true)
40-
public class BrokerResourceAccountCommandParameters extends ResourceAccountCommandParameters {
41+
public class BrokerResourceAccountCommandParameters extends ResourceAccountCommandParameters
42+
implements IBrokerTokenCommandParameters {
43+
/**
44+
* UID of the calling application process as seen by the Broker.
45+
*/
4146
@Expose
4247
private final int callerUid;
4348

49+
/**
50+
* Version name/code of the calling application that initiated the request.
51+
*/
4452
@Expose
4553
private final String callerAppVersion;
4654

55+
/**
56+
* Version of the Broker executing this request.
57+
*/
4758
@Expose
4859
private final String brokerVersion;
4960

61+
/**
62+
* The AAD tenant id (home tenant) for the user account this request is for. It
63+
* is derived from the {@link #getHomeAccountId()} value and is used
64+
*/
65+
@Expose
66+
@NonNull
67+
private final String homeTenantId;
68+
69+
/**
70+
* The user id in home tenant retrieved from {@link #getHomeAccountId()}.
71+
*/
72+
@NonNull
73+
private final String localAccountId;
74+
75+
/**
76+
* {@link IBrokerAccount} if already present, otherwise null.
77+
*/
5078
private final IBrokerAccount brokerAccount;
79+
80+
/**
81+
* The protocol version that was negotiated between the calling app / library
82+
* and the Broker.
83+
*/
84+
@Expose
85+
private final String negotiatedBrokerProtocolVersion;
86+
87+
/**
88+
* For this parameter class it is always {@link BrokerRequestType#REGULAR} as this request is not started in broker.
89+
*/
90+
private final BrokerRequestType requestType = BrokerRequestType.REGULAR;
5191
}

common4j/src/main/com/microsoft/identity/common/java/jwt/AbstractJwtRequest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public static class ClaimNames {
6262
public static final String JWE_CRYPTO = "jwe_crypto";
6363
public static final String SESSION_KEY_CRYPTO = "session_key_crypto";
6464
public static final String PURPOSE = "purpose";
65+
public static final String CLIENT_SCENARIO = "client_scenario";
6566
}
6667

6768
@SerializedName(ClaimNames.REFRESH_TOKEN)

common4j/src/main/com/microsoft/identity/common/java/jwt/JwtRequestBody.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ public final class JwtRequestBody extends AbstractJwtRequest {
8888
@SerializedName(ClaimNames.PURPOSE)
8989
private String mPurpose;
9090

91+
@SerializedName(ClaimNames.CLIENT_SCENARIO)
92+
private String mClientScenario;
93+
9194
public void setIat(final long iat) {
9295
mIat = String.valueOf(iat);
9396
}

common4j/src/main/com/microsoft/identity/common/java/opentelemetry/AttributeName.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,16 @@ public enum AttributeName {
305305
*/
306306
keystore_exception_stack_trace,
307307

308+
/**
309+
* Indicates the exception message from a Android KeyStore operation exception.
310+
*/
311+
keystore_exception_message,
312+
313+
/**
314+
* Indicates the error code from a Android KeyStore operation exception.
315+
*/
316+
keystore_numeric_error_code,
317+
308318
/**
309319
* Indicates the new nonce found in the eSTS request.
310320
*/

0 commit comments

Comments
 (0)