ADALiOS - 如何静默刷新accessToken?

时间:2016-04-05 01:24:41

标签: ios adal

我使用ADALiOS v3.0.0-pre.2连接到Azure AD B2C并授权给定用户。我成功获得了用户的accessToken,系统会提示用户在此过程中登录。我在acquireTokenWithScopes实例上使用ADAuthenticationContext方法来执行此操作。

在某个地方,我想确保我之前获得的accessToken仍然有效并且没有被撤销。所以,我使用acquireTokenSilentWithScopes来检查。但是,我立即回复说:

  

引发错误:10。其他信息:域:ADAuthenticationErrorDomain详细信息:用户凭据需要获取访问令牌。请调用非静默的acquireTokenWithResource方法。

该API的正确用法是什么,只有在服务器端撤销令牌时才会静默刷新令牌或抛出错误?

2 个答案:

答案 0 :(得分:2)

我通过对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(在用户配置文件字典中映射到sharedGroup)来解决此问题。

更改#3:

ADKeychainTokenCacheStore ,我将其用作具体的 ADTokenCacheStoring 缓存,它提供了一个sharedGroup属性,允许多个应用程序共享共同的钥匙串机密。默认情况下,com.microsoft.adalcache设置为sharedGroup。但是,由于该类当前是私有的,因此无法覆盖此值。此外,设置该值需要iOS应用程序在其权利中声明共享组名称。如果未正确配置这些权利,则将值设置到钥匙串中会失败。因此,要解决此问题,我会在 ADKeychainTokenCacheStore 类本身中手动将默认nil值设置为nil。我怀疑这个类最终会被公共框架暴露出来,但目前情况并非如此,所以我不得不入侵它。

更改#4

当我通过ADALiOS框架从AD服务器请求身份验证令牌时,我使用策略和一组范围来执行此操作。框架代码使用此策略/范围对来创建查找键,并查看是否已缓存该键的任何令牌。如果未找到,则代码按预期联系服务器。一旦服务器返回auth令牌,框架就会尝试缓存该值。它构建了一个全新的策略/范围关键对象。但是,这一次,它使用服务器返回的策略和范围值,而不是我传入的值。并且,由于某种原因,服务器将这些值返回到ADAuthenticationContext(TokenCaching) 。因此,为存储构建的新策略/范围键是有效的,但不同最初用于查找缓存的令牌。因此,当缓存操作成功时,下次我尝试使用有效的策略/范围对查找身份验证令牌时,查找失败。

这可能再次成为服务器配置错误的问题。

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

    [[ADAuthenticationSettings sharedInstance] setSharedCacheKeychainGroup:nil];

完成所有这些更改后,获取AD身份验证令牌并以静默方式刷新它似乎按预期工作。我有点担心我需要破解代码库以使其工作。如果某些MS人员可以指导我们是否有必要进行这些更改或是否有更直接的解决方案,那将会很有帮助。

<强>更新 事实证明,您不需要直接入侵 ADKeychainTokenCacheStore (更改上面的#3)。 ADAutheticationSettings 类为您提供了一种方法:

{{1}}

答案 1 :(得分:0)

我是Azure Active Directory团队的Brandon Werner。我在这里回答了这个问题:https://stackoverflow.com/a/44170226/1232116针对提出的具体问题。