通过对 ADALiOS v3.0.0-pre.2 进行以下更改,我成功地击败了 acquireTokenSilentWithScopes 提交。
更改 #1:
ADUserIdentifier有如下类方法:
+(BOOL) identifier:(ADUserIdentifier*)identifier matchesInfo:(ADProfileInfo*)info
其中有以下几行代码:
NSString* matchString = [identifier userIdMatchString:info];
if (!matchString || [matchString isEqualToString:identifier.userId])
{
return YES;
}
出于某种原因,matchString 有时会以NSNull 的形式返回,并在其上调用isEqualToString: 方法会抛出异常。我就这样改了:
id matchString = [identifier userIdMatchString:info];
if (!matchString || ![matchString isKindOfClass:[NSString class]] || [matchString isEqualToString:identifier.userId])
{
return YES;
}
这似乎是框架中值得修复的合法错误。
更改 #2:
当从 AD 接收到令牌时,ADALiOS 会尝试将该值存储在缓存中。在某些时候,它会调用 ADTokenCacheStoreItem 的 userCacheKey 属性,其定义如下:
-(NSString*)userCacheKey
{
switch (_identifierType)
{
case OptionalDisplayableId:
case RequiredDisplayableId:
return _profileInfo.username;
case UniqueId:
return _profileInfo.subject;
}
}
就我而言,我使用RequiredDisplayableId 来识别用户。在上面的 switch 语句中,它转换为 _profileInfo.username,而后者又从用户配置文件字典中返回 preferred_username 值。对我来说,这个值没有设定。所以,userCacheKey 返回NSNull,缓存机制失败。
在用户配置文件字典中设置的值为name 和tid。这可能是服务器配置错误,但我通过将此方法的返回值更改为_profileInfo.friendlyName(映射到用户配置文件字典中的name)解决了这个问题。
更改 #3:
ADKeychainTokenCacheStore,我用作选择的具体 ADTokenCacheStoring 缓存,它公开了一个sharedGroup 属性,允许多个应用程序共享公共钥匙串秘密。默认情况下,sharedGroup 设置为 com.microsoft.adalcache。但是,由于该类当前是私有的,因此无法覆盖此值。此外,设置该值需要 iOS 应用程序在其权利中声明共享组名称。如果没有正确配置这些权利,将值设置到钥匙串中会失败。因此,为了解决这个问题,我在 ADKeychainTokenCacheStore 类本身中手动将默认 sharedGroup 值设置为 nil。我怀疑这个类最终会被框架公开,但目前情况并非如此,所以我不得不侵入它。
更改 #4
当我通过 ADALiOS 框架从 AD 服务器请求身份验证令牌时,我会使用一个策略和一组范围来执行此操作。框架代码使用此策略/范围对来创建查找键并查看该键的任何令牌是否已被缓存。如果没有找到,代码会按预期联系服务器。一旦服务器返回一个身份验证令牌,框架就会尝试缓存该值。它构造了一个全新的策略/范围关键对象。但是,这一次,它使用服务器返回的策略和范围值,而不是我传入的值。并且,出于某种原因,服务器将这些值返回给nil。因此,为存储而构建的新策略/范围键是有效的,但 与我最初用于查找缓存令牌的键不同。因此,当缓存操作成功时,下次我尝试使用我的有效策略/范围对查找身份验证令牌时,查找失败。
这又可能是服务器配置错误的问题。
无论如何,为了解决这个问题,我现在将来自服务器的响应中的策略和范围值重置为最初用于生成服务器请求的原始值。这发生在ADAuthenticationContext(TokenCaching) 中的以下方法中:
- (void)updateCacheToResult:(ADAuthenticationResult*)result
cacheInstance:(id<ADTokenCacheStoring>)tokenCacheStoreInstance
cacheItem:(ADTokenCacheStoreItem*)cacheItem
withRefreshToken:(NSString*)refreshToken
在所有这些更改之后,获取 AD 身份验证令牌并静默刷新它似乎可以按预期工作。我有点担心我需要多少侵入代码库才能使其工作。如果一些 MS 人员可以指导我这些更改是否有必要或是否有更直接的解决方案,将会很有帮助。
更新:
事实证明,您不需要直接侵入 ADKeychainTokenCacheStore(更改上面的 #3)。 ADAutheticationSettings 类公开了一个方法供您这样做:
[[ADAuthenticationSettings sharedInstance] setSharedCacheKeychainGroup:nil];