如何解决MSAL B2C PasswordReset流导致“无效授权”错误
我正在尝试使用iOS上的MSAL(1.1.7)库来构建“登录/注册-和密码重置”流程。
对于B2C_1A_SignUpSignIn
策略,一切似乎都正常。往返浏览器后会收到令牌。
当用户请求重设时,通过在Web视图中点击“忘记密码”:
根据文档,我捕获了AADB2C90118
错误代码,并使用具有B2C_1A_PasswordReset
策略的授权机构开始了新的流程。
let authority = try MSALB2CAuthority(url: authURL)
let config = MSALPublicClientApplicationConfig(clientId: AuthCredential.clientID.description,redirectUri: AuthCredential.redirectUri.description,authority: authority)
config.knownAuthorities = [authority]
let application = try MSALPublicClientApplication(configuration: config)
return application
一切正常,重置流程,开始,可以完成,并生成accessToken和refreshToken。
现在是问题所在
这些新获取的令牌仅对B2C_1A_PasswordReset
策略有效,当我无声地获取令牌以用于我们的api时,它会与B2C_1A_SignUpSignIn
策略一起使用。这意味着我第一次尝试发出包含对MSAL.getTokenSilently
的调用的请求时,会出现以下错误:
MSALErrorDescriptionKey=User interaction is required,MSALOAuthErrorKey=invalid_grant,NSUnderlyingError=0x6000018a5590 {
UserInfo = { MSALErrorDescriptionKey=AADB2C90088: The provided grant has not been issued for this endpoint.
Actual Value : B2C_1A_SignUpSignIn and Expected Value : B2C_1A_PasswordReset,MSALInternalErrorCodeKey=-42004
}
}
该错误似乎非常清楚,如果至少我的理解是正确的,则没有用户,只有链接到B2C_1A_PasswordReset
策略的accessToken和refreshToken。并且需要手动登录。
我应该立即为用户启动手动登录流程吗?
iOS忘记密码的流程几乎是愚蠢的:
- 点击帐户(通过
B2C_1A_SignUpSignIn
策略交互式地请求令牌) - iOS提示允许在野生动物园中打开Webview
- 用户在网络视图中点击“忘记密码”
- 重定向回捕获错误代码(
AADB2C90118
)的应用程序 - 以
B2C_1A_PasswordReset
的策略交互式地启动令牌 - iOS提示允许在野生动物园中打开Webview
- 用户会跳过所有重置密码圈
- 使用accessToken和refreshToken(我什么都不能使用)重定向回应用程序
- 以
B2C_1A_SignUpSignIn
的策略交互式地启动令牌 - iOS提示允许在野生动物园中打开Webview
- 用户使用新凭据登录
- 使用accessToken和refreshToken(我可以使用)将其重定向回应用程序
Android 并没有提示您打开浏览器,而对于我的同事开发该流程,用户在重置密码后登录,似乎登录成功在后台进行。
我无法在iOS的文档中找到密码重置流程的示例。还有其他平台的示例。
我可以用其他方式构造它以获得更好的流程吗?
我们有权访问后端,我们在那里可以做些什么?
解决方法
在上下文中检索到的策略和令牌是链接的。可能有不同的权限和流与不同的策略相关联,因此从MSAL /应用程序的角度来看,它们也可能是不同的后端。
好的,更好的流程是确保在使用getTokenSilently
时,还必须确保使用与检索令牌的策略匹配的令牌。
在网上我发现的所有MSAL示例中,这都不是问题,因为它们直接在ViewController中进行操作并保留对application
对象的引用。
我每次需要时都设置它:
let authority = try MSALB2CAuthority(url: authURL)
let config = MSALPublicClientApplicationConfig(clientId: AuthCredential.clientID.description,redirectUri: AuthCredential.redirectUri.description,authority: authority)
config.knownAuthorities = [authority]
let application = try MSALPublicClientApplication(configuration: config)
具有执行特定任务所需的权限。因此,在我的情况下,当用户需要重设密码时,我将更改权限,转到Web视图并重设密码,取回令牌,它们会自动放入MSAL中。现在,当我致电getTokenSilently
时,我将使用SignInSignUp策略,但MSAL中的令牌将链接到密码重置策略=>“ invalid grant”
我做了什么修复,因为我仍然认为仅在需要时实例化MSALPublicClientApplication
的模式要好得多,因为它与应用程序中不同位置的各种API调用相关联,而不仅仅是一个ViewController,是使用应用程序类方法在MSALPublicClientApplication
上进行扩展,该方法从上次成功执行的getTokenSilently
或getTokenInteractively
中提取策略,并始终使用该方法构造应用程序对象。>
class func application() -> MSALPublicClientApplication? {
do {
let authURLString = UserDefaults.getMSALPolicyKey() ?? AuthCredential.signInAuthority.description
let authURL = URL(string: authURLString)!
let authority = try MSALB2CAuthority(url: authURL)
let config = MSALPublicClientApplicationConfig(clientId: AuthCredential.clientID.description,authority: authority)
config.knownAuthorities = [authority]
let application = try MSALPublicClientApplication(configuration: config)
return application
} catch {
// catch and log error
return nil
}
}
,该策略应按以下方式保存:
application.acquireTokenSilent(with: silentParameters) { (result,error) in
guard let result = result,let key = result.account.identifier,error == nil else {
// Error handling
UserDefaults.clearMSALPolicies() // clear policies so we default to standard policy
}
completion(.failure(nsError))
}
// get policy directly from result
UserDefaults.setMSALPolicyKey(key: result.authority.url.absoluteString)
completion(.success(result.accessToken))
}
这会将问题中的密码重置流程列表缩减为7个步骤,并且用户已登录。
在Android上它实际上不起作用,我们只有相当长的令牌寿命,因此直到很久以后带有密码重置策略的令牌过期并且客户端尝试使用SignInSignOut刷新令牌时,该错误才会出现策略=>“无效的授权”。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。