.NET Core 3预览版8升级后,React SPA / 嵌入式身份服务器问题

12
我们有一个React SPA,最初是使用SPA模板创建的,并在.NET Core 3预览版7上运行。React SPA“客户端”被配置为隐式流并成功使用oidc-client。一切正常。
以下是我的startup.cs中的客户端配置:
        var mySPAClient = new IdentityServer4.Models.Client()
        {
            AccessTokenLifetime = accessTokenLifetime,
            RedirectUris =
                {
                    $"{host}/authentication/login-callback",
                    $"{host}/silent-refresh.html"
                },
            PostLogoutRedirectUris =
                {
                    $"{host}/authentication/logout-callback"
                },
            ClientId = "projectName.web",
            AllowedScopes =
                {
                    "projectName.webAPI",
                    "openid",
                    "profile"
                },
            ClientName = "projectName.web",
            RequireConsent = false,
            AllowedGrantTypes =
                {
                    IdentityModel.OidcConstants.GrantTypes.Implicit
                },
            AllowAccessTokensViaBrowser = true,
        };

但是现在当我升级到预览8时,对于任何预览7的程序集,在日志中出现以下错误:

[10:55:34 错误] 客户端的授权类型无效: "authorization_code" AuthorizeRequestValidationLog { ClientId: "projectName.web", ClientName: "projectName.web", RedirectUri: "https://localhost:44343/authentication/login-callback", AllowedRedirectUris: ["https://localhost:44343/authentication/login-callback", "https://localhost:44343/silent-refresh.html"], SubjectId: "anonymous", ResponseType: "code", ResponseMode: "query", GrantType: "authorization_code", RequestedScopes: "", State: "a1e84334a8c94b7db599ddb9336447c8", UiLocales: null, Nonce: null, AuthenticationContextReferenceClasses: null, DisplayMode: null, PromptMode: null, MaxAge: null, LoginHint: null, SessionId: null, Raw: [("client_id": "projectName.web"), ("redirect_uri": "https://localhost:44343/authentication/login-callback"), ("response_type": "code"), ("scope": "projectName.webAPI openid profile"), ("state": "a1e84334a8c94b7db599ddb9336447c8"), ("code_challenge": "E8p1sg1Y0TdbhxccGB-_fbx7D6GnJXfCpcYu1IHZC_k"), ("code_challenge_method": "S256"), ("prompt": "none")] } (IdentityServer4.Validation.AuthorizeRequestValidator) [10:55:34 错误] 请求验证失败 (IdentityServer4.Endpoints.AuthorizeEndpoint)

我不知道为什么现在会涉及到“authorization_code”,并出现此错误?

感谢任何帮助。


你能让我们看一下你的令牌终端调用吗? - bobek
我有同样的问题。看起来令牌端点被调用了两次,第二次失败了,因为授权代码只能使用一次。(在此之前有一个成功的令牌端点调用,在其中间进行了用户信息调用)。我不确定是什么原因导致了这种行为。到目前为止,我可以确定登录组件被挂载了两次,因此在componentDidMount中有两个LoginCallback操作。有什么想法吗? - laorient
嘿,有趣的事情。我现在不在,但一周后回来会看看它。 - Andrew Duffy
2个回答

1

response_type更改为"token"而不是"code",这样你就可以了

更新:

确保您提供正确的authority,client_id,response_type,scope设置


当我访问端点https://localhost:44343/_configuration/projectName.web时,它返回{ "authority": "https://localhost:44343", "client_id": "projectName.web", "redirect_uri": "https://localhost:44343/authentication/login-callback", "post_logout_redirect_uri": "https://localhost:44343/authentication/logout-callback", "response_type": "id_token token", "scope": "projectName.webAPI openid profile" }因此,这似乎已经正确设置。也就是说,响应类型是正确的。 - Andrew Duffy
我很确定我的设置是正确的。如前所述,在第7个预览版本中一切都正常工作。 - Andrew Duffy
我正在使用隐式授权而不是授权码,但它却将客户端视为授权码,尽管明显没有定义为这样。 - Andrew Duffy
1
授权码现在是JavaScript应用程序的推荐授权类型。请参阅Implicit的说明:http://docs.identityserver.io/en/latest/topics/grant_types.html。我会尝试通过更改客户端配置以使用“GrantTypes.Code”而不是“IdentityModel.OidcConstants.GrantTypes.Implicit”来使授权码工作。 - Richard
谢谢@Richard,也许预览版8不支持隐式,或者它只是有问题。是的,我知道隐式存在漏洞。 - Andrew Duffy
显示剩余3条评论

0

我已经解决了我的问题。但不确定是否适用于您的情况。 在我的情况下,问题是我有一个流程存在某种不匹配。当我尝试修改React with Auth示例以使用EF Core时,updateState调用不会在AuthorizeService.js/completeSignIn()中进行。代码似乎会在回到SignIn()之前导致对令牌端点的另一个调用,而没有updateState()调用来保存状态。第二个调用失败,因为第一次调用后代码已过期。 我在React with Redux示例中找到了另一个源代码,该示例在completeSignIn()中具有必需的updateState()调用。除了非常不同的AuthorizeService.js文件之外,React with Auth示例和React with Redux示例之间的其他身份验证/授权相关代码都是相同的。 这是新的completeSignIn代码:

    async completeSignIn(url) {
        await this.ensureUserManagerInitialized();
        try {
            const { state } = await this.userManager.readSigninResponseState(url, this.userManager.settings.stateStore);
            if (state.request_type === 'si:r' || !state.request_type) {
                let user = await this.userManager.signinRedirectCallback(url);
                this.updateState(user);
                return this.success(state.data.userState);
            }
            if (state.request_type === 'si:p') {
                await this.userManager.signinSilentCallback(url);
                return this.success(undefined);
            }
            if (state.request_type === 'si:s') {
              await this.userManager.signinSilentCallback(url);
              return this.success(undefined);
            }

            throw new Error(`Invalid login mode '${state.request_type}'.`);
        } catch (signInResponseError) {
            console.log('There was an error signing in', signInResponseError);
            return this.error('Sing in callback authentication error.');
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接