最近我正在尝试使用IdentityServer4与React客户端设置身份验证。 我部分地遵循了IdentityServer文档的Adding a JavaScript client
教程,链接在这里:https://media.readthedocs.org/pdf/identityserver4/release/identityserver4.pdf,同时使用了Quickstart7_JavaScriptClient
文件。
不幸的是,我正在使用React作为我的前端,而我的React知识不足以使用React实现教程中使用的相同功能。
尽管如此,我开始阅读并尝试着入门。我的IdentityServer项目和API已经设置好,并且似乎正常工作(也测试过其他客户端)。
我首先将oidc-client.js添加到我的Visual Code项目中。 接下来,我创建了一个页面,在启动时呈现此页面(命名为Authentication.js),这是包含登录、调用API和注销按钮的地方。 此页面(Authentication.js)如下所示:
import React, { Component } from 'react';
import {login, logout, api, log} from '../../testoidc'
import {Route, Link} from 'react-router';
export default class Authentication extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div>
<button id="login" onClick={() => {login()}}>Login</button>
<button id="api" onClick={() => {api()}}>Call API</button>
<button id="logout" onClick={() => {logout()}}>Logout</button>
<pre id="results"></pre>
</div>
<div>
<Route exact path="/callback" render={() => {window.location.href="callback.html"}} />
{/* {<Route path='/callback' component={callback}>callback</Route>} */}
</div>
</div>
);
}
}
在上面被导入的testoidc.js文件中,我添加了所有使用的oidc函数(例如在示例项目中的app.js)。路由部分应该使callback.html可用,我将该文件保留为原样(可能是错误的)。testoidc.js文件包含以下函数:
import Oidc from 'oidc-client'
export function log() {
document.getElementById('results').innerText = '';
Array.prototype.forEach.call(arguments, function (msg) {
if (msg instanceof Error) {
msg = "Error: " + msg.message;
}
else if (typeof msg !== 'string') {
msg = JSON.stringify(msg, null, 2);
}
document.getElementById('results').innerHTML += msg + '\r\n';
});
}
var config = {
authority: "http://localhost:5000",
client_id: "js",
redirect_uri: "http://localhost:3000/callback.html",
response_type: "id_token token",
scope:"openid profile api1",
post_logout_redirect_uri : "http://localhost:3000/index.html",
};
var mgr = new Oidc.UserManager(config);
mgr.getUser().then(function (user) {
if (user) {
log("User logged in", user.profile);
}
else {
log("User not logged in");
}
});
export function login() {
mgr.signinRedirect();
}
export function api() {
mgr.getUser().then(function (user) {
var url = "http://localhost:5001/identity";
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = function () {
log(xhr.status, JSON.parse(xhr.responseText));
}
xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
xhr.send();
});
}
export function logout() {
mgr.signoutRedirect();
}
有多个问题。当我点击登录按钮时,我被重定向到identityServer的登录页面(这是好的)。当我使用有效凭据登录后,会重定向到我的React应用程序:http://localhost:3000/callback.html#id_token=Token
身份验证项目中的此客户端定义如下:
new Client
{
ClientId = "js",
ClientName = "JavaScript Client",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
// where to redirect to after login
RedirectUris = { "http://localhost:3000/callback.html" },
// where to redirect to after logout
PostLogoutRedirectUris = { "http://localhost:3000/index.html" },
AllowedCorsOrigins = { "http://localhost:3000" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
}
}
虽然看起来回调函数从未被调用,但它仍停留在具有非常长令牌的回调 URL 上。
登录后,getUser 函数始终显示“未登录的用户”,而Call API按钮则表示没有令牌。显然,事情并没有正常工作。我只是不知道哪些地方出了问题。 检查时,我可以看到在本地存储中生成了一个令牌:
此外,当我点击注销按钮时,我被重定向到身份主机的注销页面,但是当我在那里点击注销时,我没有被重定向到客户端。
我的问题是:
- 我在使用 oidc-client 与 IdentityServer4 结合时走上了正确的轨道吗?
- 我是否使用了正确的库,或者 react 是否需要与 oidc-client.js 不同的库。
- 是否有任何教程介绍了使用 react 前端与 IdentityServer4 和 oidc-client(不使用 redux)的组合,我找不到任何教程。
- 如何/在哪里添加 callback.html,是否应该进行改写?
能否有人指点我正确的方向,这里可能有更多的事情出了问题,但是此时我卡在了甚至不知道从哪里开始。