英文:
Azure AD B2C UseOpenIdConnectAuthentication - Can't find Refresh Token
问题
以下是您要求的翻译部分:
我们有一个有些复杂且过时的工作流程,我们正试图“有点”现代化。我们使用一个非常旧的代码集(.NET 4.6.2),并将Azure AD B2C ROPC流迁移到授权码流。我们已经有了基本的设置工作原理 - 我们使用IAppBuilder.Map
捕获认证端点,然后使用IAppBuilder.Run
调用Authentication.Challenge
以指定的认证类型。
关于认证提供程序的注册,我们使用UseOpenIdConnectAuthentication
,具有以下选项:
AuthenticationType = AuthenticationType.Storefront,
ClientId = clientId,
Authority = authority,
SignInAsAuthenticationType = AuthenticationType.Storefront,
Scope = OpenIdConnectScopes.OpenId,
ResponseType = OpenIdConnectResponseTypes.CodeIdToken,
PostLogoutRedirectUri = "/",
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
NameClaimType = "name",
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse();
return Task.CompletedTask;
},
RedirectToIdentityProvider = RedirectToSameDomain,
SecurityTokenValidated = OnOrgUserSecurityTokenValidated,
AuthorizationCodeReceived = OnOrgAuthorizationCodeReceived
}
这对于将浏览器重定向用户到Azure AD B2C,然后使用SecurityTokenValidated
回调捕获响应完全有效。问题在于在该响应中,刷新令牌始终丢失。我们尝试了几个不同的地方:
AuthenticationTicket.Properties.AllowRefresh
始终为false
,尽管在Authentication.Challenge
步骤中将AuthenticationProperties.AllowRefresh
设置为true
ProtocolMessage.AccessToken
包含有效的访问令牌,但ProtocolMessage.RefreshToken
始终为null
- 无论我们查看
SecurityTokenValidated
还是AuthorizationCodeReceived
,上述两点都是正确的
除了上述所有内容,还有一个问题我们不太确定。目前,我们使用ROPC来刷新访问令牌。如果我们使用授权码流进行登录,这是否仍然有效?
对于任何建议,我们将不胜感激。谢谢!
编辑
将来自Rukmini的答案(https://stackoverflow.com/a/76578895/1289046)标记为正确,但我想详细说明一下我需要采取的具体步骤,以使其正常工作。
首先 - 就发送到Azure AD B2C的设置信息而言,第一个authorize
调用使用scope=openid
和response_type=code id_token
发送。然后,我深入到Azure AD B2C在认证成功时发送的SecurityTokenValidated
消息中。
在那里,我显著修改了整个流程。从Azure AD B2C返回的响应中,我仅获取ProtocolMessage.Code
值,并使用它来发起另一个调用到Azure AD B2C。不过,这一次,我使用grant_type=authorization_code
进行调用,并将code
参数设置为前述的ProtocolMessage.Code
值。我使用在Azure AD B2C中注册的client_id
和client_secret
进行此调用。
这第二个调用的响应正确包含refresh_token
,以及id_token
和两个令牌的expires_in
值。
最后但同样重要的是,我重新调整了刷新令牌的行为 - 只要refresh_token
尚未过期,我就使用它来获取新的id_token
,如果id_token
已过期或即将过期。如果refresh_token
已过期,我将用户登出。
英文:
Got a somewhat convoluted and outdated workflow that we're trying to "somewhat" modernize. We are using a very old set of code (.NET 4.6.2), and are migrating an Azure AD B2C ROPC flow to an Authorization Code flow. We have the basic setup working - we capture the auth endpoint using IAppBuilder.Map
, and then use IAppBuilder.Run
to call Authentication.Challenge
with the specified auth type.
In terms of the auth provider registration, we use UseOpenIdConnectAuthentication
, with the following options:
AuthenticationType = AuthenticationType.Storefront,
ClientId = clientId,
Authority = authority,
SignInAsAuthenticationType = AuthenticationType.Storefront,
Scope = OpenIdConnectScopes.OpenId,
ResponseType = OpenIdConnectResponseTypes.CodeIdToken,
PostLogoutRedirectUri = "/",
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
NameClaimType = "name",
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse();
return Task.CompletedTask;
},
RedirectToIdentityProvider = RedirectToSameDomain,
SecurityTokenValidated = OnOrgUserSecurityTokenValidated,
AuthorizationCodeReceived = OnOrgAuthorizationCodeReceived
}
This works perfectly for getting the browser to redirect the user to Azure AD B2C, and then capturing the response with the SecurityTokenValidated
callback. The problem is that in that response, the refresh token is always missing. We've tried several different places:
AuthenticationTicket.Properties.AllowRefresh
is alwaysfalse
, despite settingAuthenticationProperties.AllowRefresh
totrue
during theAuthentication.Challenge
stepProtocolMessage.AccessToken
contains a valid access token, howeverProtocolMessage.RefreshToken
is alwaysnull
- Both of the above hold true regardless of whether we look at
SecurityTokenValidated
or atAuthorizationCodeReceived
On top of all of the above, there's one more question which we're unsure about. Currently we use ROPC to refresh the access token. Will that work even if we use the Authorization Code flow for signing in?
Any suggestions would be appreciated. Thanks!
EDIT
Going to mark the answer from Rukmini (https://stackoverflow.com/a/76578895/1289046) as correct, but I wanted to elaborate a bit on the specific steps I needed to take, to get this working.
First things first - in terms of the setup info for what gets sent over to Azure AD B2C, the first authorize
call is sent using scope=openid
and response_type=code id_token
. I then hook into the SecurityTokenValidated
message that Azure AD B2C sends back when authentication has occurred successfully.
In there, I modified the overall flow significantly. From the response I get from Azure AD B2C, I take only the ProtocolMessage.Code
value, and I use that to make another call to Azure AD B2C. This time, though, I call it using grant_type=authorization_code
and I set the code
parameter to the aforementioned ProtocolMessage.Code
value. I make this call using a client_id
and client_secret
registered in Azure AD B2C.
The response of this second call properly contains the refresh_token
, alongside the id_token
and an expires_in
value for both tokens.
Last, but not least, I rewired the refresh token behaviour - as long as the refresh_token
hasn't expired, I use it to get a new id_token
if it has expired or will soon do so. If the refresh_token
has expired, I log the user out.
答案1
得分: 1
我创建了一个Azure AD B2C应用程序,并授予了如下的API权限:
现在,我使用以下参数通过Postman生成了ROPC流程的访问令牌:
> 注意:要生成刷新令牌,需要offline_access
范围。
要生成刷新令牌,请授予offline_access
API权限:
现在,在生成令牌时,传递offline_access
范围,如下所示:
要获取刷新令牌,请修改代码如下:
> 除了上述所有内容,我们还有一个不确定的问题。当前,我们使用ROPC来刷新访问令牌。即使我们使用授权代码流进行登录,这种方法仍然有效吗?
是的,即使使用授权代码流进行登录,您仍然可以使用ROPC来刷新访问令牌。我能够刷新由授权代码生成的访问令牌,并使用ROPC的刷新令牌:
英文:
I created an Azure AD B2C Application and granted API permissions like below:
Now, I generated access token using ROPC flow using below parameters via Postman:
https://b2ctenant.b2clogin.com/b2ctenant.onmicrosoft.com/<policy-name>/oauth2/v2.0/token
client_id:ClientID
scope:openid
username:admin@b2ctenant.onmicrosoft.com
password:*****
grant_type:password
client_secret:ClientSecret
> Note that: To generate refresh token, the offline_access
scope is required.
To generate the refresh token, grant offline_access
API permission:
Now while generating the token, pass offline_access
scope like below:
scope:openid offline_access
To get refresh token, modify the code like below:
AuthenticationType = AuthenticationType.Storefront,
ClientId = clientId,
Authority = authority, SignInAsAuthenticationType = AuthenticationType.Storefront,
Scope = OpenIdConnectScopes.OpenId + "offline_access",
ResponseType = OpenIdConnectResponseTypes.CodeIdToken,
> On top of all of the above, there's one more question which we're unsure about. Currently we use ROPC to refresh the access token. Will that work even if we use the Authorization Code flow for signing in?
https://b2ctenant.b2clogin.com/b2ctenant.onmicrosoft.com/B2C_1_Signinsignup/oauth2/v2.0/token
client_id:xxxx
grant_type:authorization_code
scope:openid offline_access
code:code
redirect_uri:https://jwt.ms
client_secret:ClientSecret
Yes, you can use ROPC to refresh the access token even if Authorization Code flow is used for signing in.
I am able to refresh the access token generated by authorization code and using refresh token of ROPC:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论