我正在使用ADALiOS v3.0.0-pre.2连接到Azure AD B2C并授权给定用户。我成功为用户获取了一个accessToken,该用户被提示使用UI登录该过程。我在acquireTokenWithScopes实例上使用了ADAuthenticationContext方法。

我想确定早先获得的accessToken仍然有效,并且尚未被撤消。因此,我使用acquireTokenSilentWithScopes进行检查。但是,我立即收到一个错误消息:

引发的错误:10.其他信息:域:ADAuthenticationErrorDomain详细信息:需要用户凭据才能获得访问 token 。请调用非静音的acquireTokenWithResource方法。

此API的正确用法是什么,以使 token 仅在服务器端被吊销时才被静默刷新或引发错误?

最佳答案

通过对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收到 token 后,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,并且缓存机制失败。

用户配置文件字典中设置的值是nametid。这可能是服务器配置错误,但是我通过将此方法的返回值更改为_profileInfo.friendlyName(映射到用户配置文件字典中的name)来解决此问题。

变更#3:

我用作选择的具体 ADTokenCacheStoring 缓存的 ADKeychainTokenCacheStore 公开了sharedGroup属性,该属性允许多个应用程序共享 public 钥匙串秘密。默认情况下,sharedGroup设置为com.microsoft.adalcache。但是,由于该类当前是 private 的,因此无法覆盖此值。此外,设置该值需要iOS应用在其权利中声明共享组名称。如果没有正确配置这些权利,则无法在钥匙串中设置值。因此,要变通解决此问题,我在 ADKeychainTokenCacheStore 类本身中手动将默认sharedGroup值设置为nil。我怀疑最终该类将在框架中公开公开,但是目前情况并非如此,因此我不得不对其进行深入研究。

变更#4

当我通过ADALiOS框架从AD服务器请求身份验证 token 时,我会使用策略和一组作用域。框架代码使用该策略/作用域对创建查找密钥,并查看该密钥是否已被缓存。如果未找到,则代码按预期方式与服务器联系。服务器返回认证 token 后,框架将尝试缓存该值。它构造了一个全新的策略/作用域关键对象。但是,这次,它使用服务器返回的策略和作用域值,而不是我传入的值。由于某种原因,服务器将这些值返回给nil。结果,为存储构造的新策略/作用域密钥是有效的,但与我最初用于查找缓存 token 的密钥不同。因此,虽然缓存操作成功,但是下次我尝试使用有效的策略/作用域对查找auth token 时,查找失败。

这可能再次是服务器配置错误。

无论如何,要解决此问题,我现在将服务器响应中的策略和作用域值重置为最初用于生成服务器请求的原始值。这是在ADAuthenticationContext(TokenCaching)中的以下方法中发生的:
- (void)updateCacheToResult:(ADAuthenticationResult*)result
              cacheInstance:(id<ADTokenCacheStoring>)tokenCacheStoreInstance
                  cacheItem:(ADTokenCacheStoreItem*)cacheItem
           withRefreshToken:(NSString*)refreshToken

完成所有这些更改之后,获取AD身份验证 token 并以静默方式刷新它似乎可以按预期工作。我有点担心要侵入代码库才能使其正常工作。如果某些MS专家可以指导我有关是否需要进行这些更改或是否有更直接的解决方案,这将很有帮助。

更新:
事实证明,您不需要直接侵入 ADKeychainTokenCacheStore (上面的更改#3)。 ADAutheticationSettings 类公开了一个方法供您这样做:
    [[ADAuthenticationSettings sharedInstance] setSharedCacheKeychainGroup:nil];

关于ios - ADALiOS-如何以静默方式刷新accessToken?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36415587/

10-14 00:43