Skip to content

Commit fa1b262

Browse files
authored
Merge branch 'release/1.17.1' into ameyapat/refresh-1.17.0-dev-changes-into-bart
2 parents b460fb6 + b6a9e5c commit fa1b262

15 files changed

+634
-21
lines changed

IdentityCore/src/MSIDBrokerConstants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ extern NSString * _Nonnull const MSID_IS_CALLER_MANAGED_KEY;
9999
extern NSString * _Nonnull const MSID_BROKER_PREFERRED_AUTH_CONFIGURATION_KEY;
100100
extern NSString * _Nonnull const MSID_BROKER_CLIENT_FLIGHTS_KEY;
101101
extern NSString * _Nonnull const MSID_BROKER_SDM_WPJ_ATTEMPTED;
102+
extern NSString * _Nonnull const MSID_BART_DEVICE_ID_KEY;
102103
extern NSString * _Nonnull const MSID_EXP_RETRY_ON_NETWORK;
103104
extern NSString * _Nonnull const MSID_EXP_ENABLE_CONNECTION_CLOSE;
104105
extern NSString * _Nonnull const MSID_HTTP_CONNECTION;

IdentityCore/src/MSIDBrokerConstants.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
NSString *const MSID_JIT_TROUBLESHOOTING_HOST = @"jit_troubleshooting";
9898
NSString *const MSID_IS_CALLER_MANAGED_KEY = @"isCallerAppManaged";
9999
NSString *const MSID_BROKER_SDM_WPJ_ATTEMPTED = @"sdm_reg_attempted";
100+
NSString *const MSID_BART_DEVICE_ID_KEY = @"bart_device_id";
100101
NSString *const MSID_FORCE_REFRESH_KEY = @"force_refresh";
101102

102103
// Experiments

IdentityCore/src/MSIDOAuth2Constants.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ extern NSString *const MSID_CCS_REQUEST_ID_RESPONSE;
179179

180180
extern NSString *const MSID_CCS_REQUEST_SEQUENCE_KEY;
181181
extern NSString *const MSID_CCS_REQUEST_SEQUENCE_RESPONSE;
182+
extern NSString *const MSID_REFRESH_TOKEN_TYPE;
183+
extern NSString *const MSID_REFRESH_TOKEN_TYPE_BOUND_APP_RT;
182184
extern NSString *const MSID_BOUND_DEVICE_ID_CACHE_KEY;
183185
extern NSString *const MSID_MSAL_CLIENT_APV_PREFIX;
184186
extern NSString *const MSID_BOUND_REFRESH_TOKEN_EXCHANGE;

IdentityCore/src/MSIDOAuth2Constants.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@
180180
NSString *const MSID_CCS_REQUEST_SEQUENCE_KEY = @"x-ms-srs";
181181
NSString *const MSID_CCS_REQUEST_SEQUENCE_RESPONSE = @"ccs-request-sequence";
182182

183+
NSString *const MSID_REFRESH_TOKEN_TYPE = @"refresh_token_type";
184+
NSString *const MSID_REFRESH_TOKEN_TYPE_BOUND_APP_RT = @"bound_app_rt";
183185
NSString *const MSID_BOUND_REFRESH_TOKEN_EXCHANGE = @"bound_rt_exchange";
184186
NSString *const MSID_BOUND_DEVICE_ID_CACHE_KEY = @"bound_device_id";
185187
NSString *const MSID_MSAL_CLIENT_APV_PREFIX = @"MsalClient";

IdentityCore/src/cache/accessor/MSIDDefaultTokenCacheAccessor.m

Lines changed: 117 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
#import "MSIDAuthenticationScheme.h"
4949
#import "MSIDFamilyRefreshToken.h"
5050
#import "MSIDAADTokenRequestServerTelemetry.h"
51+
#import "MSIDBartFeatureUtil.h"
52+
#import "MSIDBoundRefreshToken.h"
5153

5254
@interface MSIDDefaultTokenCacheAccessor()
5355
{
@@ -132,6 +134,15 @@ - (MSIDRefreshToken *)getRefreshTokenWithAccount:(MSIDAccountIdentifier *)accoun
132134
context:(id<MSIDRequestContext>)context
133135
error:(NSError *__autoreleasing *)error
134136
{
137+
MSIDBoundRefreshToken *boundAppRefreshToken = [self getBoundApplicationRefreshTokenWithAccount:accountIdentifier
138+
familyId:familyId
139+
configuration:configuration
140+
context:context
141+
error:error];
142+
if (boundAppRefreshToken)
143+
{
144+
return boundAppRefreshToken;
145+
}
135146
NSError *frtError = nil;
136147
MSIDIsFRTEnabledStatus frtStatus = [_accountCredentialCache checkFRTEnabled:context error:&frtError];
137148
BOOL frtEnabled = frtStatus == MSIDIsFRTEnabledStatusEnabled;
@@ -151,7 +162,6 @@ - (MSIDRefreshToken *)getRefreshTokenWithAccount:(MSIDAccountIdentifier *)accoun
151162
#endif
152163

153164
MSIDCredentialType credentialType = frtEnabled ? MSIDFamilyRefreshTokenType : MSIDRefreshTokenType;
154-
155165
MSIDRefreshToken *refreshToken = [self getRefreshableTokenWithAccount:accountIdentifier
156166
familyId:familyId
157167
credentialType:credentialType
@@ -193,6 +203,44 @@ - (MSIDRefreshToken *)getRefreshTokenWithAccount:(MSIDAccountIdentifier *)accoun
193203
return nil;
194204
}
195205

206+
/// Get a bound refresh token if available. Returns nil if not found or if feature is disabled.
207+
- (MSIDBoundRefreshToken *)getBoundApplicationRefreshTokenWithAccount:(MSIDAccountIdentifier *)accountIdentifier
208+
familyId:(NSString *)familyId
209+
configuration:(MSIDConfiguration *)configuration
210+
context:(id<MSIDRequestContext>)context
211+
error:(NSError *__autoreleasing *)error
212+
{
213+
MSIDBoundRefreshToken *boundAppRefreshToken;
214+
if ([[MSIDBartFeatureUtil sharedInstance] isBartFeatureEnabled])
215+
{
216+
boundAppRefreshToken = (MSIDBoundRefreshToken *)[self getRefreshableTokenWithAccount:accountIdentifier
217+
familyId:familyId
218+
credentialType:MSIDBoundRefreshTokenType
219+
configuration:configuration
220+
context:context
221+
error:error];
222+
if (boundAppRefreshToken)
223+
{
224+
return boundAppRefreshToken;
225+
}
226+
for (id<MSIDCacheAccessor> accessor in _otherAccessors)
227+
{
228+
boundAppRefreshToken = (MSIDBoundRefreshToken *)[accessor getRefreshTokenWithAccount:accountIdentifier
229+
familyId:familyId
230+
configuration:configuration
231+
context:context
232+
error:error];
233+
234+
if (boundAppRefreshToken)
235+
{
236+
MSID_LOG_WITH_CTX(MSIDLogLevelInfo, context, @"(Default accessor) Found Bound app refresh token in a different accessor %@", [accessor class]);
237+
return boundAppRefreshToken;
238+
}
239+
}
240+
}
241+
return nil;
242+
}
243+
196244
- (MSIDPrimaryRefreshToken *)getPrimaryRefreshTokenWithAccount:(MSIDAccountIdentifier *)accountIdentifier
197245
familyId:(NSString *)familyId
198246
configuration:(MSIDConfiguration *)configuration
@@ -254,7 +302,14 @@ - (MSIDRefreshToken *)getRefreshableTokenWithAccount:(MSIDAccountIdentifier *)ac
254302
context:(id<MSIDRequestContext>)context
255303
error:(NSError *__autoreleasing *)error
256304
{
257-
if (credentialType != MSIDRefreshTokenType && credentialType != MSIDPrimaryRefreshTokenType && credentialType != MSIDFamilyRefreshTokenType) return nil;
305+
BOOL shouldQueryBarts = [[MSIDBartFeatureUtil sharedInstance] isBartFeatureEnabled];
306+
if (credentialType != MSIDRefreshTokenType &&
307+
credentialType != MSIDPrimaryRefreshTokenType &&
308+
credentialType != MSIDFamilyRefreshTokenType &&
309+
(!shouldQueryBarts || credentialType != MSIDBoundRefreshTokenType))
310+
{
311+
return nil;
312+
}
258313

259314
// For nested auth, get the RT using the broker/hub's client id
260315
NSString *clientId = [configuration isNestedAuthProtocol] ? configuration.nestedAuthBrokerClientId : configuration.clientId;
@@ -817,12 +872,20 @@ - (BOOL)validateAndRemoveRefreshToken:(MSIDRefreshToken *)token
817872
MSID_LOG_WITH_CTX(MSIDLogLevelError, context, @"Error checking FRT enabled status, not using new FRT.");
818873
}
819874

820-
MSIDCredentialType credentialType = frtEnabled ? MSIDFamilyRefreshTokenType : MSIDRefreshTokenType;
875+
BOOL result;
876+
if ([[MSIDBartFeatureUtil sharedInstance] isBartFeatureEnabled])
877+
{
878+
result = [self validateAndRemoveRefreshableToken:token
879+
credentialType:MSIDBoundRefreshTokenType
880+
context:context
881+
error:error];
882+
}
821883

822-
BOOL result = [self validateAndRemoveRefreshableToken:token
823-
credentialType:credentialType
824-
context:context
825-
error:error];
884+
MSIDCredentialType credentialType = frtEnabled ? MSIDFamilyRefreshTokenType : MSIDRefreshTokenType;
885+
result = [self validateAndRemoveRefreshableToken:token
886+
credentialType:credentialType
887+
context:context
888+
error:error];
826889

827890
// If family refresh token is not enabled, return list of regular refresh tokens
828891
if (!frtEnabled)
@@ -851,7 +914,11 @@ - (BOOL)validateAndRemoveRefreshableToken:(MSIDRefreshToken *)token
851914
context:(id<MSIDRequestContext>)context
852915
error:(NSError *__autoreleasing*)error
853916
{
854-
if (credentialType != MSIDRefreshTokenType && credentialType != MSIDPrimaryRefreshTokenType && credentialType != MSIDFamilyRefreshTokenType)
917+
BOOL shouldBartBeRemoved = [[MSIDBartFeatureUtil sharedInstance] isBartFeatureEnabled];
918+
if (credentialType != MSIDRefreshTokenType &&
919+
credentialType != MSIDPrimaryRefreshTokenType &&
920+
credentialType != MSIDFamilyRefreshTokenType &&
921+
(!shouldBartBeRemoved || credentialType != MSIDBoundRefreshTokenType))
855922
{
856923
return NO;
857924
}
@@ -995,6 +1062,20 @@ - (BOOL)saveRefreshTokenWithConfiguration:(MSIDConfiguration *)configuration
9951062

9961063
if (![NSString msidIsStringNilOrBlank:refreshToken.familyId])
9971064
{
1065+
// If FRT is a bound refresh token, we can assume it to be sFRT bound app refresh token
1066+
if ([[MSIDBartFeatureUtil sharedInstance] isBartFeatureEnabled] &&
1067+
refreshToken.credentialType == MSIDBoundRefreshTokenType)
1068+
{
1069+
MSIDBoundRefreshToken *bart = (MSIDBoundRefreshToken *)refreshToken;
1070+
if (bart && bart.boundDeviceId)
1071+
{
1072+
MSID_LOG_WITH_CTX_PII(MSIDLogLevelVerbose, context, @"(Default accessor) Saving the sFRT as family bound refresh token %@", MSID_EUII_ONLY_LOG_MASKABLE(refreshToken));
1073+
return [self saveToken:refreshToken
1074+
context:context
1075+
error:error];
1076+
}
1077+
}
1078+
9981079
NSError *frtError = nil;
9991080
// Check if FRT is enabled, this will update the configuration object, and then use it to decide if
10001081
// we should save the token as FRT or legacy RT (with familyId, if it contains that value).
@@ -1066,7 +1147,9 @@ - (BOOL)removeToken:(MSIDBaseToken *)token
10661147
CONDITIONAL_START_CACHE_EVENT(event, MSID_TELEMETRY_EVENT_TOKEN_CACHE_DELETE, context);
10671148
BOOL result = [_accountCredentialCache removeCredential:token.tokenCacheItem context:context error:error];
10681149

1069-
if (result && (token.credentialType == MSIDRefreshTokenType || token.credentialType == MSIDFamilyRefreshTokenType))
1150+
if (result && (token.credentialType == MSIDRefreshTokenType ||
1151+
token.credentialType == MSIDFamilyRefreshTokenType ||
1152+
([[MSIDBartFeatureUtil sharedInstance] isBartFeatureEnabled] && token.credentialType == MSIDBoundRefreshTokenType)))
10701153
{
10711154
[_accountCredentialCache saveWipeInfoWithContext:context error:nil];
10721155
}
@@ -1131,7 +1214,9 @@ - (MSIDBaseToken *)getTokenWithEnvironment:(NSString *)environment
11311214
return resultTokens[0];
11321215
}
11331216

1134-
if (cacheQuery.credentialType == MSIDRefreshTokenType || cacheQuery.credentialType == MSIDFamilyRefreshTokenType)
1217+
if (cacheQuery.credentialType == MSIDRefreshTokenType ||
1218+
cacheQuery.credentialType == MSIDFamilyRefreshTokenType ||
1219+
([[MSIDBartFeatureUtil sharedInstance] isBartFeatureEnabled] && cacheQuery.credentialType == MSIDBoundRefreshTokenType))
11351220
{
11361221
NSError *wipeError = nil;
11371222
CONDITIONAL_STOP_FAILED_CACHE_EVENT(event, [_accountCredentialCache wipeInfoWithContext:context error:&wipeError], context);
@@ -1288,7 +1373,6 @@ - (BOOL)saveAccount:(MSIDAccount *)account
12881373
}
12891374

12901375
MSIDCredentialType credentialType = frtEnabled ? MSIDFamilyRefreshTokenType : MSIDRefreshTokenType;
1291-
12921376
NSSet<NSString *> *firstSet = [self homeAccountIdsFromRTsWithAuthority:authority
12931377
clientId:clientId
12941378
familyId:familyId
@@ -1303,6 +1387,28 @@ - (BOOL)saveAccount:(MSIDAccount *)account
13031387
return firstSet;
13041388
}
13051389

1390+
if ([[MSIDBartFeatureUtil sharedInstance] isBartFeatureEnabled])
1391+
{
1392+
NSSet<NSString *> *bartSet = [self homeAccountIdsFromRTsWithAuthority:authority
1393+
clientId:clientId
1394+
familyId:familyId
1395+
credentialType:MSIDBoundRefreshTokenType
1396+
accountCredentialCache:accountCredentialCache
1397+
context:context
1398+
error:error];
1399+
if (bartSet)
1400+
{
1401+
[firstSet setByAddingObjectsFromSet:bartSet];
1402+
}
1403+
else
1404+
{
1405+
if (error)
1406+
{
1407+
MSID_LOG_WITH_CTX(MSIDLogLevelError, context, @"(Default accessor) Failed to retrieve homeAccountIds from BARTs: %@", MSID_PII_LOG_MASKABLE(*error));
1408+
}
1409+
}
1410+
}
1411+
13061412
NSSet<NSString *> *secondSet = [self homeAccountIdsFromRTsWithAuthority:authority
13071413
clientId:clientId
13081414
familyId:familyId

IdentityCore/src/oauth2/MSIDOauth2Factory.m

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#import "MSIDAccessToken.h"
2828
#import "MSIDBaseToken.h"
2929
#import "MSIDRefreshToken.h"
30+
#import "MSIDBoundRefreshToken.h"
3031
#import "MSIDLegacySingleResourceToken.h"
3132
#import "MSIDIdToken.h"
3233
#import "MSIDAccount.h"
@@ -170,6 +171,10 @@ - (MSIDRefreshToken *)refreshTokenFromResponse:(MSIDTokenResponse *)response
170171
BOOL result = [self fillRefreshToken:refreshToken fromResponse:response configuration:configuration];
171172

172173
if (!result) return nil;
174+
if (refreshToken && [self doesResponseHaveBoundAppRefreshToken:response])
175+
{
176+
return [[MSIDBoundRefreshToken alloc] initWithRefreshToken:refreshToken boundDeviceId:response.boundAppRefreshTokenDeviceId];
177+
}
173178
return refreshToken;
174179
}
175180

@@ -411,6 +416,13 @@ - (BOOL)fillAppMetadata:(MSIDAppMetadataCacheItem *)metadata
411416
return YES;
412417
}
413418

419+
- (BOOL)doesResponseHaveBoundAppRefreshToken:(MSIDTokenResponse *)response
420+
{
421+
return ![NSString msidIsStringNilOrBlank:response.boundAppRefreshTokenDeviceId] &&
422+
([MSID_REFRESH_TOKEN_TYPE_BOUND_APP_RT isEqualToString:response.additionalServerInfo[MSID_REFRESH_TOKEN_TYPE]] ||
423+
[response.additionalServerInfo[MSID_BART_DEVICE_ID_KEY] length] > 0);
424+
}
425+
414426
#pragma mark - Webview
415427
- (MSIDWebviewFactory *)webviewFactory
416428
{

IdentityCore/src/oauth2/MSIDTokenResponse.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@
9595

9696
@property (nonatomic) BOOL createdFromCache;
9797

98+
@property (nonatomic, nullable) NSString *boundAppRefreshTokenDeviceId;
99+
98100
- (nullable instancetype)initWithJSONDictionary:(nonnull NSDictionary *)json
99101
refreshToken:(nullable MSIDBaseToken<MSIDRefreshableToken> *)token
100102
error:(NSError * _Nullable __autoreleasing *_Nullable)error;

IdentityCore/src/oauth2/MSIDTokenResponse.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ - (instancetype)initWithJSONDictionary:(NSDictionary *)json error:(NSError *__au
170170
_stsErrorCodes = [json msidArrayOfIntegersForKey: MSID_OAUTH2_ERROR_CODES];
171171
_errorDescription = [[json msidStringObjectForKey:MSID_OAUTH2_ERROR_DESCRIPTION] msidURLDecode];
172172
_clientAppVersion = [json msidStringObjectForKey:MSID_BROKER_CLIENT_APP_VERSION_KEY];
173+
_boundAppRefreshTokenDeviceId = [json msidStringObjectForKey:MSID_BART_DEVICE_ID_KEY];
173174
[self setAdditionalServerInfo:json];
174175
}
175176

IdentityCore/src/oauth2/token/MSIDBoundRefreshToken.m

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,10 @@ - (instancetype)initWithRefreshToken:(MSIDRefreshToken *)refreshToken
5454

5555
- (instancetype)initWithTokenCacheItem:(MSIDCredentialCacheItem *)tokenCacheItem
5656
{
57-
if (![tokenCacheItem isKindOfClass:[MSIDBoundRefreshTokenCacheItem class]])
58-
{
59-
MSID_LOG_WITH_CTX(MSIDLogLevelError, nil, @"Failed to create bound refresh token: tokenCacheItem is not of type MSIDBoundRefreshTokenCacheItem.");
60-
return nil;
61-
}
62-
63-
MSIDBoundRefreshTokenCacheItem *boundTokenCacheItem = (MSIDBoundRefreshTokenCacheItem *)tokenCacheItem;
64-
self = [super initWithTokenCacheItem:boundTokenCacheItem];
65-
57+
self = [super initWithTokenCacheItem:tokenCacheItem];
6658
if (self)
6759
{
68-
NSDictionary *jsonDictionary = boundTokenCacheItem.jsonDictionary;
60+
NSDictionary *jsonDictionary = tokenCacheItem.jsonDictionary;
6961
_boundDeviceId = [jsonDictionary msidObjectForKey:MSID_BOUND_DEVICE_ID_CACHE_KEY ofClass:[NSString class]];
7062
if ([NSString msidIsStringNilOrBlank:_boundDeviceId])
7163
{

IdentityCore/src/requests/sdk/MSIDTokenResponseValidator.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#import "MSIDBrokerResponse.h"
3030
#import "MSIDAccessToken.h"
3131
#import "MSIDRefreshToken.h"
32+
#import "MSIDBoundRefreshToken.h"
3233
#import "MSIDBasicContext.h"
3334
#import "MSIDAccountMetadataCacheAccessor.h"
3435
#import "MSIDAccountIdentifier.h"
@@ -262,6 +263,12 @@ - (MSIDTokenResult *)validateAndSaveTokenResponse:(MSIDTokenResponse *)tokenResp
262263
return nil;
263264
}
264265

266+
if ([MSID_REFRESH_TOKEN_TYPE_BOUND_APP_RT isEqualToString:tokenResponse.additionalServerInfo[MSID_REFRESH_TOKEN_TYPE]] && tokenResponse.boundAppRefreshTokenDeviceId)
267+
{
268+
tokenResult.refreshToken = [[MSIDBoundRefreshToken alloc] initWithRefreshToken:(MSIDRefreshToken *)tokenResult.refreshToken
269+
boundDeviceId:tokenResponse.boundAppRefreshTokenDeviceId];
270+
}
271+
265272
//save metadata
266273
NSError *authorityError;
267274
MSIDAuthority *resultingAuthority = [factory resultAuthorityWithConfiguration:parameters.msidConfiguration tokenResponse:tokenResponse error:&authorityError];

0 commit comments

Comments
 (0)