我正在开发一个iOS应用,将ROPC流程与AADB2C一起用作支持此功能的后端端点。
https://login.microsoftonline.com/{TENANTNAME}.onmicrosoft.com/oauth2/v2.0/token?p={ROPC Policy Name}
在客户首次成功使用电子邮件/密码登录后,我已经能够成功请求和检索access token
,refresh token
和ID token
。
成功登录后,以后每次登录后,我们都希望利用生物识别技术(触摸/面部识别码)。我的第一个想法是将refreshToken存储在钥匙串中,在强制用户输入其电子邮件/密码之前检查refreshToken
是否存在。
如果存在refreshToken
,那么我想我将使用对?p=refresh_token
而不是?p={INSERT ROPC Policy Name}
的令牌端点的调用,如果我返回成功,那么我使用Touch / Face ID登录。
我的另一种想法是仅使用令牌ID进行身份验证。
因此,我的问题有两个方面:
更好的做法是-对于iOS本机应用程序使用刷新令牌或ID令牌。
我尝试使用刷新令牌,将{ROPC Policy Name}
参数替换为?p=refresh_token
,但是每次尝试配置请求时,都会收到一条错误消息,提示"The request body must contain the following parameter: 'grant_type'"
我添加了“ refresh_token”作为键grant_type
的值,并且该错误仍然出现。 -为什么会这样?如果刷新令牌grant_type更好,该如何解决。
答案 0 :(得分:2)
你是对的。
您可以将刷新令牌保存到钥匙串中,并通过Face或Touch ID保护该刷新令牌的使用。
The "Redeem a refresh token" section中的the "Configure the resource owner password credentials flow in Azure AD B2C" document描述了如何兑换为资源所有者策略发出的刷新令牌:
POST /{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&response_type=id_token
&client_id={client_id}
&resource={client_id}
&refresh_token={refresh_token}
答案 1 :(得分:0)
感谢@Chris Padgett。我能够使用经过稍微修改的请求将其启动并与AppAuth一起运行。这是我的代码。
let authorizationEndpoint = URL(string: "https://login.microsoftonline.com/{TENANT_NAME}.onmicrosoft.com/oauth2/v2.0/authorize?p={ROPC_POLICY_NAME}")
let tokenEndpoint = URL(string: "https://login.microsoftonline.com/{TENANT_NAME}.onmicrosoft.com/oauth2/v2.0/token?p={ROPC_POLICY_NAME}")
let configuration = OIDServiceConfiguration(authorizationEndpoint: authorizationEndpoint!, tokenEndpoint: tokenEndpoint!)
//Configuring the token request
let tokenExchangeRequest = OIDTokenRequest(
configuration: configuration,
grantType: OIDGrantTypeRefreshToken,
authorizationCode: nil,
redirectURL: self.redirectUri!,
clientID: self.clientId,
clientSecret: nil,
scope: "openid \(self.clientId) offline_access",
refreshToken: {INSERT_REFRESH_TOKEN_HERE},
codeVerifier: nil,
additionalParameters: nil
)
//Performing token request
OIDAuthorizationService.perform(tokenExchangeRequest, callback: { tokenResponse, error in
if tokenResponse == nil {
print("Token request error: %@", error?.localizedDescription as Any)
} else {
guard let tokenResponse = tokenResponse else { return }
...handle tokenResponse how you need to...
}
})