Skip to content

Commit 7b770d0

Browse files
committed
Accept both base64 and base64url tokens in the bidstream
This behaviour matches that of the .NET SDK.
1 parent adc1b67 commit 7b770d0

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

src/main/java/com/uid2/client/Uid2Encryption.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,19 @@ static DecryptionResponse decrypt(String token, KeyContainer keys, Instant now,
4343
}
4444
else if (unsignedByte == AdvertisingTokenVersion.V4.value())
4545
{
46-
//same as V3 but use Base64URL encoding
47-
return decryptV3(Uid2Base64UrlCoder.decode(token), keys, now, identityScope, domainName, clientType, 4);
46+
// Accept either base64 or base64url encoding.
47+
return decryptV3(Base64.getDecoder().decode(base64UrlToBase64(token)), keys, now, identityScope, domainName, clientType, 4);
4848
}
4949

5050
return DecryptionResponse.makeError(DecryptionStatus.VERSION_NOT_SUPPORTED);
5151
}
5252

53+
static String base64UrlToBase64(String value) {
54+
// Base64 decoder doesn't require padding.
55+
return value.replace('-', '+')
56+
.replace('_', '/');
57+
}
58+
5359
static DecryptionResponse decryptV2(byte[] encryptedId, KeyContainer keys, Instant now, String domainName, ClientType clientType) throws Exception {
5460
try {
5561
ByteBuffer rootReader = ByteBuffer.wrap(encryptedId);

src/test/java/com/uid2/client/BidstreamClientTests.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@
44
import com.google.gson.JsonObject;
55
import org.junit.jupiter.api.Test;
66
import org.junit.jupiter.params.ParameterizedTest;
7-
import org.junit.jupiter.params.provider.Arguments;
8-
import org.junit.jupiter.params.provider.CsvSource;
9-
import org.junit.jupiter.params.provider.MethodSource;
10-
import org.junit.jupiter.params.provider.ValueSource;
7+
import org.junit.jupiter.params.provider.*;
118

129
import java.time.Duration;
1310
import java.time.Instant;
1411
import java.time.temporal.ChronoUnit;
1512
import java.util.Arrays;
13+
import java.util.Base64;
1614
import java.util.stream.Stream;
1715

1816
import static com.uid2.client.EncryptionTestsV4.validateAdvertisingToken;
@@ -288,6 +286,26 @@ public void tokenExpiryAndCustomNow() throws Exception {
288286
assertEquals(EXAMPLE_UID, res.getUid());
289287
}
290288

289+
@ParameterizedTest
290+
@EnumSource(IdentityScope.class)
291+
void decryptV4TokenEncodedAsBase64(IdentityScope identityScope) throws Exception {
292+
refresh(keyBidstreamResponse(identityScope, MASTER_KEY, SITE_KEY));
293+
294+
String advertisingToken;
295+
do {
296+
advertisingToken = AdvertisingTokenBuilder.builder()
297+
.withVersion(TokenVersionForTesting.V4)
298+
.withScope(identityScope)
299+
.build();
300+
301+
byte[] tokenAsBytes = Uid2Base64UrlCoder.decode(advertisingToken);
302+
advertisingToken = Base64.getEncoder().encodeToString(tokenAsBytes);
303+
}
304+
while (!advertisingToken.contains("=") || !advertisingToken.contains("/") || !advertisingToken.contains("+"));
305+
306+
decryptAndAssertSuccess(advertisingToken, TokenVersionForTesting.V4);
307+
}
308+
291309
private void refresh(String json) {
292310
RefreshResponse refreshResponse = bidstreamClient.refreshJson(json);
293311
assertTrue(refreshResponse.isSuccess());

0 commit comments

Comments
 (0)