Azure AD B2C UseOpenIdConnectAuthentication – 无法找到刷新令牌

huangapple go评论62阅读模式
英文:

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=openidresponse_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_idclient_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 always false, despite setting AuthenticationProperties.AllowRefresh to true during the Authentication.Challenge step
  • ProtocolMessage.AccessToken contains a valid access token, however ProtocolMessage.RefreshToken is always null
  • Both of the above hold true regardless of whether we look at SecurityTokenValidated or at AuthorizationCodeReceived

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:

Azure AD B2C UseOpenIdConnectAuthentication – 无法找到刷新令牌

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

Azure AD B2C UseOpenIdConnectAuthentication – 无法找到刷新令牌

> Note that: To generate refresh token, the offline_access scope is required.

To generate the refresh token, grant offline_access API permission:

Azure AD B2C UseOpenIdConnectAuthentication – 无法找到刷新令牌

Now while generating the token, pass offline_access scope like below:

scope:openid offline_access

Azure AD B2C UseOpenIdConnectAuthentication – 无法找到刷新令牌

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

Azure AD B2C UseOpenIdConnectAuthentication – 无法找到刷新令牌

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:

Azure AD B2C UseOpenIdConnectAuthentication – 无法找到刷新令牌

huangapple
  • 本文由 发表于 2023年6月29日 00:43:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76575198.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定