ADALiOS-如何以静默方式刷新accessToken?

ADALiOS-如何以静默方式刷新accessToken?,ios,adal,Ios,Adal,我正在使用ADALiOS v3.0.0-pre.2连接到Azure AD B2C并授权给定用户。我成功地为用户获取了一个accessToken,用户在登录过程中会收到UI提示。我使用adaauthenticationcontext实例上的acquireTokenWithScopes方法来执行此操作 接下来的某个地方,我想确保我之前获得的accessToken仍然有效,并且没有被撤销。因此,我使用acquireTokenSilentWithScopes进行检查。但是,我立即得到了一个错误,即: 出

我正在使用ADALiOS v3.0.0-pre.2连接到Azure AD B2C并授权给定用户。我成功地为用户获取了一个
accessToken
,用户在登录过程中会收到UI提示。我使用
adaauthenticationcontext
实例上的
acquireTokenWithScopes
方法来执行此操作

接下来的某个地方,我想确保我之前获得的
accessToken
仍然有效,并且没有被撤销。因此,我使用
acquireTokenSilentWithScopes
进行检查。但是,我立即得到了一个错误,即:

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


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

通过对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
,对其调用
IsequalString:
方法将抛出。我把它改成这样:

id matchString = [identifier userIdMatchString:info];
if (!matchString || ![matchString isKindOfClass:[NSString class]] || [matchString isEqualToString:identifier.userId])
{
    return YES;
}
这似乎是框架中一个合法的bug,值得修复

变化#2: 当从AD接收到令牌时,ADALiOS会尝试将该值存储在缓存中。在某些情况下,它调用ADTokenCacheStoreItem
userCacheKey
属性,该属性定义如下:

-(NSString*)userCacheKey
{
    switch (_identifierType)
    {
        case OptionalDisplayableId:
        case RequiredDisplayableId:
            return _profileInfo.username;

        case UniqueId:
            return _profileInfo.subject;
    }
}
在我的例子中,我使用
RequiredDisplayableId
来识别用户。在上面的switch语句中,它转换为
\u profileInfo.username
,然后从用户配置文件字典返回
首选\u username
值。对我来说,这个值没有设置。因此,
userCacheKey
返回
NSNull
,缓存机制失败

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

变化#3: ADKeychainTokenCacheStore是我选择的具体的ADTokenCacheStoring缓存,它公开了一个
sharedGroup
属性,允许多个应用程序共享公共密钥链机密。默认情况下,
sharedGroup
设置为
com.microsoft.adalcache
。但是,由于该类当前是私有的,因此无法重写该值。此外,设置该值需要iOS应用程序在其权限中声明共享组名。如果没有正确配置这些权限,将值设置到密钥链将失败。因此,为了解决这个问题,我在ADKeychainTokenCacheStore类本身中将默认的
sharedGroup
值手动设置为
nil
。我怀疑这个类最终会被框架公开,但目前情况并非如此,所以我不得不入侵它

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

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

不管怎样,为了解决这个问题,我现在将服务器响应中的策略和范围值重置为最初用于生成服务器请求的原始值。这在
adaauthenticationcontext(令牌缓存)
中的以下方法中发生:


我是Azure Active Directory团队的Brandon Werner。我在这里回答了这个问题:针对所问的具体问题。

这对我来说似乎不是问题。现在看来,框架试图使用nil作为将令牌数据存储在缓存中的密钥,但失败了。那么以后在缓存中找不到任何东西。仍在调查。。。但是谢谢你的链接-我感谢你的建议!你能提供日志给我们帮助调查吗?请随时将它们发送到brandwe@microsoft.comthanks对于这个提议,@BrandonWerner!很遗憾,我无法与您共享日志。关于律师和NDA的事情-不是我的决定。也就是说,我找到了需要改变什么才能让无声刷新通话正常工作。我会在下面公布我的发现。如果您能查看一下,让我知道我是否发现了实际的bug,是否遇到了配置错误的服务器,或者是否只是使用了与预期不同的API,这将非常有帮助。
- (void)updateCacheToResult:(ADAuthenticationResult*)result
              cacheInstance:(id<ADTokenCacheStoring>)tokenCacheStoreInstance
                  cacheItem:(ADTokenCacheStoreItem*)cacheItem
           withRefreshToken:(NSString*)refreshToken 
    [[ADAuthenticationSettings sharedInstance] setSharedCacheKeychainGroup:nil];